diff options
author | Valerij Fredriksen <valerijf@yahooinc.com> | 2023-02-24 14:23:55 +0100 |
---|---|---|
committer | Valerij Fredriksen <valerijf@yahooinc.com> | 2023-02-24 14:23:55 +0100 |
commit | 1af61047e6009df087dee4e6d2e0f16ac0e7dd55 (patch) | |
tree | cbc27888109fe021c973800c8678f6b8756ddaf7 | |
parent | 6db540e4d94a9d80784c44eb51164e66f91848bf (diff) |
Crate ArchiveUri to hold both tenant and account archive URIs
2 files changed, 94 insertions, 0 deletions
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/archive/ArchiveUris.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/archive/ArchiveUris.java new file mode 100644 index 00000000000..7ec9bd36744 --- /dev/null +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/archive/ArchiveUris.java @@ -0,0 +1,45 @@ +package com.yahoo.vespa.hosted.provision.archive; + +import com.yahoo.config.provision.CloudAccount; +import com.yahoo.config.provision.TenantName; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.regex.Pattern; + +public record ArchiveUris(Map<TenantName, String> tenantArchiveUris, Map<CloudAccount, String> accountArchiveUris) { + private static final Pattern validUriPattern = Pattern.compile("[a-z0-9]+://(?:(?:[a-z0-9]+(?:[-_][a-z0-9.]+)*)+/)+"); + + public ArchiveUris(Map<TenantName, String> tenantArchiveUris, Map<CloudAccount, String> accountArchiveUris) { + this.tenantArchiveUris = Map.copyOf(tenantArchiveUris); + this.accountArchiveUris = Map.copyOf(accountArchiveUris); + } + + public ArchiveUris with(TenantName tenant, Optional<String> archiveUri) { + Map<TenantName, String> updated = updateIfChanged(tenantArchiveUris, tenant, archiveUri); + if (updated == tenantArchiveUris) return this; + return new ArchiveUris(updated, accountArchiveUris); + } + + public ArchiveUris with(CloudAccount account, Optional<String> archiveUri) { + Map<CloudAccount, String> updated = updateIfChanged(accountArchiveUris, account, archiveUri); + if (updated == accountArchiveUris) return this; + return new ArchiveUris(tenantArchiveUris, updated); + } + + private static <T> Map<T, String> updateIfChanged(Map<T, String> current, T key, Optional<String> archiveUri) { + archiveUri = archiveUri.map(ArchiveUris::normalizeUri); + if (Optional.ofNullable(current.get(key)).equals(archiveUri)) return current; + Map<T, String> updated = new HashMap<>(current); + archiveUri.ifPresentOrElse(uri -> updated.put(key, uri), () -> updated.remove(key)); + return updated; + } + + 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/test/java/com/yahoo/vespa/hosted/provision/archive/ArchiveUrisTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/archive/ArchiveUrisTest.java new file mode 100644 index 00000000000..9770d60b27a --- /dev/null +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/archive/ArchiveUrisTest.java @@ -0,0 +1,49 @@ +package com.yahoo.vespa.hosted.provision.archive; + + +import com.yahoo.config.provision.TenantName; +import org.junit.jupiter.api.Test; + +import java.util.Map; +import java.util.Optional; + +import static com.yahoo.vespa.hosted.provision.archive.ArchiveUris.normalizeUri; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class ArchiveUrisTest { + + @Test + 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_/")); + } + + @Test + void updates_in_place_if_possible() { + TenantName t1 = TenantName.from("t1"); + + ArchiveUris uris0 = new ArchiveUris(Map.of(), Map.of()); + ArchiveUris uris1 = uris0.with(t1, Optional.empty()); + assertSame(uris0, uris1); + + ArchiveUris uris2 = uris0.with(t1, Optional.of("scheme://test123")); + assertEquals(Map.of(t1, "scheme://test123/"), uris2.tenantArchiveUris()); + + assertSame(uris2, uris2.with(t1, Optional.of("scheme://test123"))); + assertSame(uris2, uris2.with(t1, Optional.of("scheme://test123/"))); + assertEquals(uris0, uris2.with(t1, Optional.empty())); + } + +} |