From 99d8d804a7e478900585fc60244b6cfbb999c3db Mon Sep 17 00:00:00 2001 From: Valerij Fredriksen Date: Fri, 24 Feb 2023 14:46:55 +0100 Subject: Use ArchiveUris in ArchiveUriManager --- .../provision/archive/ArchiveUriManager.java | 88 ++++++++++------------ .../persistence/ArchiveUriSerializer.java | 56 ++++++++++++++ .../hosted/provision/persistence/CuratorDb.java | 13 ++-- .../persistence/TenantArchiveUriSerializer.java | 45 ----------- .../hosted/provision/restapi/ArchiveResponse.java | 20 ++++- .../provision/archive/ArchiveUriManagerTest.java | 69 ++++++++--------- .../persistence/ArchiveUriSerializerTest.java | 29 +++++++ .../TenantArchiveUriSerializerTest.java | 27 ------- 8 files changed, 183 insertions(+), 164 deletions(-) create mode 100644 node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/ArchiveUriSerializer.java delete mode 100644 node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/TenantArchiveUriSerializer.java create mode 100644 node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/ArchiveUriSerializerTest.java delete mode 100644 node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/TenantArchiveUriSerializerTest.java (limited to 'node-repository') diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/archive/ArchiveUriManager.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/archive/ArchiveUriManager.java index 722fd0bac56..27488e4027c 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/archive/ArchiveUriManager.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/archive/ArchiveUriManager.java @@ -1,94 +1,88 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.provision.archive; +import com.yahoo.config.provision.ApplicationId; +import com.yahoo.config.provision.CloudAccount; import com.yahoo.config.provision.TenantName; import com.yahoo.config.provision.Zone; import com.yahoo.lang.CachedSupplier; import com.yahoo.vespa.curator.Lock; import com.yahoo.vespa.hosted.provision.Node; -import com.yahoo.vespa.hosted.provision.node.Allocation; import com.yahoo.vespa.hosted.provision.persistence.CuratorDb; import java.time.Duration; -import java.util.Map; import java.util.Optional; -import java.util.TreeMap; -import java.util.logging.Level; +import java.util.function.Function; import java.util.logging.Logger; -import java.util.regex.Pattern; /** - * Thread safe class to get and set archive URI for given tenants. Archive URIs are stored in ZooKeeper so that - * nodes within the same tenant have the same archive URI from all the config servers. + * Thread safe class to get and set archive URI for given account and tenants. * * @author freva */ public class ArchiveUriManager { private static final Logger log = Logger.getLogger(ArchiveUriManager.class.getName()); - private static final Pattern validUriPattern = Pattern.compile("[a-z0-9]+://(?:(?:[a-z0-9]+(?:[-_][a-z0-9.]+)*)+/)+"); private static final Duration cacheTtl = Duration.ofMinutes(1); private final CuratorDb db; - private final CachedSupplier> archiveUris; private final Zone zone; + private final CachedSupplier archiveUris; public ArchiveUriManager(CuratorDb db, Zone zone) { this.db = db; - this.archiveUris = new CachedSupplier<>(db::readArchiveUris, cacheTtl); this.zone = zone; + this.archiveUris = new CachedSupplier<>(db::readArchiveUris, cacheTtl); } - /** Returns the current archive URI for each tenant */ - public Map getArchiveUris() { + public ArchiveUris archiveUris() { return archiveUris.get(); } - /** Returns the archive URI to use for given tenant */ - private Optional archiveUriFor(TenantName tenant) { - return Optional.ofNullable(archiveUris.get().get(tenant)); - } - /** Returns the archive URI to use for given node */ public Optional archiveUriFor(Node node) { - if (node.cloudAccount().isEnclave(zone)) return Optional.empty(); // TODO (freva): Implement for exclave - - return node.allocation().map(Allocation::owner) - .flatMap(app -> archiveUriFor(app.tenant()) - .map(uri -> { - StringBuilder sb = new StringBuilder(100).append(uri) - .append(app.application().value()).append('/') - .append(app.instance().value()).append('/') - .append(node.allocation().get().membership().cluster().id().value()).append('/'); - - for (char c: node.hostname().toCharArray()) { - if (c == '.') break; - sb.append(c); - } - - return sb.append('/').toString(); - })); + if (node.allocation().isEmpty()) return Optional.empty(); + ApplicationId app = node.allocation().get().owner(); + + return Optional.ofNullable(node.cloudAccount().isEnclave(zone) ? + archiveUris.get().accountArchiveUris().get(node.cloudAccount()) : + archiveUris.get().tenantArchiveUris().get(app.tenant())) + .map(uri -> { + StringBuilder sb = new StringBuilder(100).append(uri) + .append(app.application().value()).append('/') + .append(app.instance().value()).append('/') + .append(node.allocation().get().membership().cluster().id().value()).append('/'); + + for (char c: node.hostname().toCharArray()) { + if (c == '.') break; + sb.append(c); + } + + return sb.append('/').toString(); + }); } /** Set (or remove, if archiveURI is empty) archive URI to use for given tenant */ public void setArchiveUri(TenantName tenant, Optional archiveUri) { + setArchiveUri(au -> au.with(tenant, archiveUri)); + } + + /** Set (or remove, if archiveURI is empty) archive URI to use for given account */ + public void setArchiveUri(CloudAccount account, Optional archiveUri) { + if (!account.isEnclave(zone) || account.isUnspecified()) + throw new IllegalArgumentException("Cannot set archive URI for non-enclave account: " + account); + setArchiveUri(au -> au.with(account, archiveUri)); + } + + private void setArchiveUri(Function mapper) { try (Lock lock = db.lockArchiveUris()) { - Map archiveUris = new TreeMap<>(db.readArchiveUris()); - if (Optional.ofNullable(archiveUris.get(tenant)).equals(archiveUri)) return; // No change + ArchiveUris archiveUris = db.readArchiveUris(); + ArchiveUris updated = mapper.apply(archiveUris); + if (archiveUris.equals(updated)) return; // No change - archiveUri.map(ArchiveUriManager::normalizeUri).ifPresentOrElse(uri -> archiveUris.put(tenant, uri), - () -> archiveUris.remove(tenant)); - db.writeArchiveUris(archiveUris); + db.writeArchiveUris(updated); this.archiveUris.invalidate(); // Throw away current cache - log.log(Level.FINE, () -> archiveUri.map(s -> "Set archive URI for " + tenant + " to " + s) - .orElseGet(() -> "Remove archive URI for " + tenant)); } } - static String normalizeUri(String uri) { - if (!uri.endsWith("/")) uri = uri + "/"; - if (!validUriPattern.matcher(uri).matches()) - throw new IllegalArgumentException("Invalid archive URI: " + uri); - return uri; - } } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/ArchiveUriSerializer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/ArchiveUriSerializer.java new file mode 100644 index 00000000000..3bf37816dd4 --- /dev/null +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/ArchiveUriSerializer.java @@ -0,0 +1,56 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.provision.persistence; + +import com.yahoo.config.provision.CloudAccount; +import com.yahoo.config.provision.TenantName; +import com.yahoo.slime.Cursor; +import com.yahoo.slime.Inspector; +import com.yahoo.slime.ObjectTraverser; +import com.yahoo.slime.Slime; +import com.yahoo.slime.SlimeUtils; +import com.yahoo.vespa.hosted.provision.archive.ArchiveUris; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.util.HashMap; +import java.util.Map; + +/** + * Serializer for archive URIs that are set per tenant and per account. + * + * @author freva + */ +public class ArchiveUriSerializer { + + private ArchiveUriSerializer() {} + + public static byte[] toJson(ArchiveUris archiveUris) { + Slime slime = new Slime(); + Cursor root = slime.setObject(); + + Cursor tenantObject = root.setObject("tenant"); + archiveUris.tenantArchiveUris().forEach((tenant, uri) -> tenantObject.setString(tenant.value(), uri)); + + Cursor accountObject = root.setObject("account"); + archiveUris.accountArchiveUris().forEach((account, uri) -> accountObject.setString(account.value(), uri)); + + try { + return SlimeUtils.toJsonBytes(slime); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + public static ArchiveUris fromJson(byte[] data) { + Inspector inspector = SlimeUtils.jsonToSlime(data).get(); + + Map tenantArchiveUris = new HashMap<>(); + inspector.field("tenant").traverse((ObjectTraverser) (key, value) -> tenantArchiveUris.put(TenantName.from(key), value.asString())); + + Map accountArchiveUris = new HashMap<>(); + inspector.field("account").traverse((ObjectTraverser) (key, value) -> accountArchiveUris.put(CloudAccount.from(key), value.asString())); + + return new ArchiveUris(tenantArchiveUris, accountArchiveUris); + } + +} diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDb.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDb.java index c25dfe9f1e2..5aea6858f60 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDb.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDb.java @@ -10,7 +10,6 @@ import com.yahoo.config.provision.ApplicationTransaction; import com.yahoo.config.provision.HostName; import com.yahoo.config.provision.NodeFlavors; import com.yahoo.config.provision.NodeType; -import com.yahoo.config.provision.TenantName; import com.yahoo.path.Path; import com.yahoo.transaction.NestedTransaction; import com.yahoo.transaction.Transaction; @@ -21,6 +20,7 @@ import com.yahoo.vespa.curator.transaction.CuratorOperations; import com.yahoo.vespa.curator.transaction.CuratorTransaction; import com.yahoo.vespa.hosted.provision.Node; import com.yahoo.vespa.hosted.provision.applications.Application; +import com.yahoo.vespa.hosted.provision.archive.ArchiveUris; import com.yahoo.vespa.hosted.provision.lb.LoadBalancer; import com.yahoo.vespa.hosted.provision.lb.LoadBalancerId; import com.yahoo.vespa.hosted.provision.node.Agent; @@ -70,7 +70,7 @@ public class CuratorDb { private static final Path infrastructureVersionsPath = root.append("infrastructureVersions"); private static final Path osVersionsPath = root.append("osVersions"); private static final Path firmwareCheckPath = root.append("firmwareCheck"); - private static final Path archiveUrisPath = root.append("archiveUris"); + private static final Path archiveUrisPath = root.append("archiveUri"); private static final Duration defaultLockTimeout = Duration.ofMinutes(1); @@ -102,6 +102,7 @@ public class CuratorDb { db.create(archiveUrisPath); db.create(loadBalancersPath); provisionIndexCounter.initialize(100); + CuratorOperations.delete(root.append("archiveUris").toString()); // TODO (freva): March 2023 } /** Adds a set of nodes. Rollbacks/fails transaction if any node is not in the expected state. */ @@ -375,16 +376,16 @@ public class CuratorDb { // Archive URIs ----------------------------------------------------------- - public void writeArchiveUris(Map archiveUris) { - byte[] data = TenantArchiveUriSerializer.toJson(archiveUris); + public void writeArchiveUris(ArchiveUris archiveUris) { + byte[] data = ArchiveUriSerializer.toJson(archiveUris); NestedTransaction transaction = new NestedTransaction(); CuratorTransaction curatorTransaction = db.newCuratorTransactionIn(transaction); curatorTransaction.add(CuratorOperations.setData(archiveUrisPath.getAbsolute(), data)); transaction.commit(); } - public Map readArchiveUris() { - return read(archiveUrisPath, TenantArchiveUriSerializer::fromJson).orElseGet(Map::of); + public ArchiveUris readArchiveUris() { + return read(archiveUrisPath, ArchiveUriSerializer::fromJson).orElseGet(() -> new ArchiveUris(Map.of(), Map.of())); } public Lock lockArchiveUris() { diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/TenantArchiveUriSerializer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/TenantArchiveUriSerializer.java deleted file mode 100644 index d381d25704a..00000000000 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/TenantArchiveUriSerializer.java +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.hosted.provision.persistence; - -import com.yahoo.config.provision.TenantName; -import com.yahoo.slime.Cursor; -import com.yahoo.slime.Inspector; -import com.yahoo.slime.ObjectTraverser; -import com.yahoo.slime.Slime; -import com.yahoo.slime.SlimeUtils; - -import java.io.IOException; -import java.io.UncheckedIOException; -import java.util.Map; -import java.util.TreeMap; - -/** - * Serializer for archive URIs that are set per tenant. - * - * @author freva - */ -public class TenantArchiveUriSerializer { - - private TenantArchiveUriSerializer() {} - - public static byte[] toJson(Map archiveUrisByTenantName) { - Slime slime = new Slime(); - Cursor object = slime.setObject(); - archiveUrisByTenantName.forEach((tenantName, archiveUri) -> - object.setString(tenantName.value(), archiveUri)); - try { - return SlimeUtils.toJsonBytes(slime); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - - public static Map fromJson(byte[] data) { - Map archiveUrisByTenantName = new TreeMap<>(); // Use TreeMap to sort by tenant name - Inspector inspector = SlimeUtils.jsonToSlime(data).get(); - inspector.traverse((ObjectTraverser) (key, value) -> - archiveUrisByTenantName.put(TenantName.from(key), value.asString())); - return archiveUrisByTenantName; - } - -} diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/ArchiveResponse.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/ArchiveResponse.java index 7c844b983d9..84c82d314c9 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/ArchiveResponse.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/ArchiveResponse.java @@ -4,6 +4,9 @@ package com.yahoo.vespa.hosted.provision.restapi; import com.yahoo.restapi.SlimeJsonResponse; import com.yahoo.slime.Cursor; import com.yahoo.vespa.hosted.provision.NodeRepository; +import com.yahoo.vespa.hosted.provision.archive.ArchiveUris; + +import java.util.Map; /** * Returns tenant archive URIs. @@ -13,11 +16,22 @@ import com.yahoo.vespa.hosted.provision.NodeRepository; public class ArchiveResponse extends SlimeJsonResponse { public ArchiveResponse(NodeRepository nodeRepository) { + ArchiveUris archiveUris = nodeRepository.archiveUriManager().archiveUris(); Cursor archivesArray = slime.setObject().setArray("archives"); - nodeRepository.archiveUriManager().getArchiveUris().forEach((tenant, uri) -> { + + archiveUris.tenantArchiveUris().entrySet().stream() + .sorted(Map.Entry.comparingByKey()) + .forEach(entry -> { + Cursor archiveObject = archivesArray.addObject(); + archiveObject.setString("tenant", entry.getKey().value()); + archiveObject.setString("uri", entry.getValue()); + }); + archiveUris.accountArchiveUris().entrySet().stream() + .sorted(Map.Entry.comparingByKey()) + .forEach(entry -> { Cursor archiveObject = archivesArray.addObject(); - archiveObject.setString("tenant", tenant.value()); - archiveObject.setString("uri", uri); + archiveObject.setString("account", entry.getKey().value()); + archiveObject.setString("uri", entry.getValue()); }); } } diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/archive/ArchiveUriManagerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/archive/ArchiveUriManagerTest.java index 0b3ae8183af..8ee72d12f57 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/archive/ArchiveUriManagerTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/archive/ArchiveUriManagerTest.java @@ -3,10 +3,16 @@ package com.yahoo.vespa.hosted.provision.archive; import com.yahoo.component.Version; import com.yahoo.config.provision.ApplicationId; +import com.yahoo.config.provision.Cloud; +import com.yahoo.config.provision.CloudAccount; import com.yahoo.config.provision.ClusterMembership; +import com.yahoo.config.provision.Environment; import com.yahoo.config.provision.Flavor; import com.yahoo.config.provision.NodeResources; import com.yahoo.config.provision.NodeType; +import com.yahoo.config.provision.RegionName; +import com.yahoo.config.provision.SystemName; +import com.yahoo.config.provision.Zone; import com.yahoo.vespa.hosted.provision.Node; import com.yahoo.vespa.hosted.provision.node.Allocation; import com.yahoo.vespa.hosted.provision.node.Generation; @@ -15,10 +21,9 @@ import org.junit.Test; import java.util.Optional; -import static com.yahoo.vespa.hosted.provision.archive.ArchiveUriManager.normalizeUri; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.fail; +import static org.junit.Assert.assertThrows; /** * @author freva @@ -27,19 +32,35 @@ public class ArchiveUriManagerTest { @Test public void archive_uri() { - ApplicationId app = ApplicationId.from("vespa", "music", "main"); - Node allocated = createNode(app); - Node unallocated = createNode(null); - ArchiveUriManager archiveUriManager = new ProvisioningTester.Builder().build().nodeRepository().archiveUriManager(); + ApplicationId app1 = ApplicationId.from("vespa", "music", "main"); + ApplicationId app2 = ApplicationId.from("yahoo", "music", "main"); + CloudAccount account1 = CloudAccount.from("123456789012"); + CloudAccount account2 = CloudAccount.from("210987654321"); + CloudAccount accountSystem = CloudAccount.from("555444333222"); + ArchiveUriManager archiveUriManager = new ProvisioningTester.Builder() + .zone(new Zone(Cloud.builder().account(accountSystem).build(), SystemName.Public, Environment.prod, RegionName.defaultName())) + .build().nodeRepository().archiveUriManager(); - assertFalse(archiveUriManager.archiveUriFor(unallocated).isPresent()); - assertFalse(archiveUriManager.archiveUriFor(allocated).isPresent()); + // Initially no uris are set + assertFalse(archiveUriManager.archiveUriFor(createNode(null, null)).isPresent()); + assertFalse(archiveUriManager.archiveUriFor(createNode(app1, account1)).isPresent()); - archiveUriManager.setArchiveUri(app.tenant(), Optional.of("scheme://hostname/dir")); - assertEquals("scheme://hostname/dir/music/main/default/h432a/", archiveUriManager.archiveUriFor(allocated).get()); + archiveUriManager.setArchiveUri(app1.tenant(), Optional.of("scheme://tenant-bucket/dir")); + archiveUriManager.setArchiveUri(account1, Optional.of("scheme://account-bucket/dir")); + assertThrows(IllegalArgumentException.class, () -> archiveUriManager.setArchiveUri(accountSystem, Optional.of("scheme://something"))); + assertThrows(IllegalArgumentException.class, () -> archiveUriManager.setArchiveUri(CloudAccount.empty, Optional.of("scheme://something"))); + + assertFalse(archiveUriManager.archiveUriFor(createNode(null, null)).isPresent()); // Not allocated + assertFalse(archiveUriManager.archiveUriFor(createNode(null, account1)).isPresent()); // URI set for this account, but not allocated + assertFalse(archiveUriManager.archiveUriFor(createNode(null, account2)).isPresent()); // Not allocated + assertFalse(archiveUriManager.archiveUriFor(createNode(app2, null)).isPresent()); // No URI set for this tenant or account + assertEquals("scheme://tenant-bucket/dir/music/main/default/h432a/", archiveUriManager.archiveUriFor(createNode(app1, null)).get()); + assertEquals("scheme://account-bucket/dir/music/main/default/h432a/", archiveUriManager.archiveUriFor(createNode(app1, account1)).get()); // Account has precedence + assertFalse(archiveUriManager.archiveUriFor(createNode(app1, account2)).isPresent()); // URI set for this tenant, but is ignored because enclave account + assertEquals("scheme://tenant-bucket/dir/music/main/default/h432a/", archiveUriManager.archiveUriFor(createNode(app1, accountSystem)).get()); // URI for tenant because non-enclave acocunt } - private Node createNode(ApplicationId appId) { + private Node createNode(ApplicationId appId, CloudAccount account) { Node.Builder nodeBuilder = Node.create("id", "h432a.prod.us-south-1.vespa.domain.tld", new Flavor(NodeResources.unspecified()), Node.State.parked, NodeType.tenant); Optional.ofNullable(appId) .map(app -> new Allocation(app, @@ -48,31 +69,7 @@ public class ArchiveUriManagerTest { Generation.initial(), false)) .ifPresent(nodeBuilder::allocation); + Optional.ofNullable(account).ifPresent(nodeBuilder::cloudAccount); return nodeBuilder.build(); } - - @Test - public void normalize_test() { - assertEquals("ftp://domain/legal-dir123/", normalizeUri("ftp://domain/legal-dir123")); - assertEquals("ftp://domain/legal-dir123/", normalizeUri("ftp://domain/legal-dir123/")); - assertEquals("s3://my-bucket-prod.region/my-tenant-123/", normalizeUri("s3://my-bucket-prod.region/my-tenant-123/")); - assertEquals("s3://my-bucket-prod.region/my-tenant_123/", normalizeUri("s3://my-bucket-prod.region/my-tenant_123/")); - assertThrows(IllegalArgumentException.class, () -> normalizeUri("domain/dir/")); - assertThrows(IllegalArgumentException.class, () -> normalizeUri("ftp:/domain/dir/")); - assertThrows(IllegalArgumentException.class, () -> normalizeUri("ftp:/domain//dir/")); - assertThrows(IllegalArgumentException.class, () -> normalizeUri("ftp://domain/illegal:dir/")); - assertThrows(IllegalArgumentException.class, () -> normalizeUri("ftp://domain/-illegal-dir/")); - assertThrows(IllegalArgumentException.class, () -> normalizeUri("ftp://domain/_illegal-dir/")); - assertThrows(IllegalArgumentException.class, () -> normalizeUri("ftp://domain/illegal-dir-/")); - assertThrows(IllegalArgumentException.class, () -> normalizeUri("ftp://domain/illegal-dir_/")); - } - - private static void assertThrows(Class clazz, Runnable runnable) { - try { - runnable.run(); - fail("Expected " + clazz); - } catch (Throwable e) { - if (!clazz.isInstance(e)) throw e; - } - } } diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/ArchiveUriSerializerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/ArchiveUriSerializerTest.java new file mode 100644 index 00000000000..6204ace8a51 --- /dev/null +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/ArchiveUriSerializerTest.java @@ -0,0 +1,29 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.provision.persistence; + +import com.yahoo.config.provision.CloudAccount; +import com.yahoo.config.provision.TenantName; +import com.yahoo.vespa.hosted.provision.archive.ArchiveUris; +import org.junit.Test; + +import java.util.Map; + +import static org.junit.Assert.assertEquals; + +/** + * @author freva + */ +public class ArchiveUriSerializerTest { + + @Test + public void test_serialization() { + ArchiveUris archiveUris = new ArchiveUris(Map.of( + TenantName.from("tenant1"), "ftp://host123.test/dir/", + TenantName.from("tenant2"), "ftp://archive.test/vespa/"), + Map.of(CloudAccount.from("321456987012"), "ftp://host123.test/dir/")); + + ArchiveUris serialized = ArchiveUriSerializer.fromJson(ArchiveUriSerializer.toJson(archiveUris)); + assertEquals(archiveUris, serialized); + } + +} \ No newline at end of file diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/TenantArchiveUriSerializerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/TenantArchiveUriSerializerTest.java deleted file mode 100644 index 2ae4f6363e0..00000000000 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/TenantArchiveUriSerializerTest.java +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.hosted.provision.persistence; - -import com.yahoo.config.provision.TenantName; -import org.junit.Test; - -import java.util.Map; -import java.util.TreeMap; - -import static org.junit.Assert.assertEquals; - -/** - * @author freva - */ -public class TenantArchiveUriSerializerTest { - - @Test - public void test_serialization() { - Map archiveUris = new TreeMap<>(); - archiveUris.put(TenantName.from("tenant1"), "ftp://host123.test/dir/"); - archiveUris.put(TenantName.from("tenant2"), "ftp://archive.test/vespa/"); - - Map serialized = TenantArchiveUriSerializer.fromJson(TenantArchiveUriSerializer.toJson(archiveUris)); - assertEquals(archiveUris, serialized); - } - -} \ No newline at end of file -- cgit v1.2.3