aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorValerij Fredriksen <valerijf@yahooinc.com>2023-02-24 14:23:55 +0100
committerValerij Fredriksen <valerijf@yahooinc.com>2023-02-24 14:23:55 +0100
commit1af61047e6009df087dee4e6d2e0f16ac0e7dd55 (patch)
treecbc27888109fe021c973800c8678f6b8756ddaf7
parent6db540e4d94a9d80784c44eb51164e66f91848bf (diff)
Crate ArchiveUri to hold both tenant and account archive URIs
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/archive/ArchiveUris.java45
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/archive/ArchiveUrisTest.java49
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()));
+ }
+
+}