aboutsummaryrefslogtreecommitdiffstats
path: root/config-provisioning/src/main/java/com/yahoo/config
diff options
context:
space:
mode:
authorValerij Fredriksen <valerijf@yahooinc.com>2023-05-30 16:31:26 +0200
committerValerij Fredriksen <valerijf@yahooinc.com>2023-05-30 17:01:53 +0200
commitfbdc11ed2c64aa29d7c6b567bc6aad5ff86d8135 (patch)
treea244d8c98d282adba0e7f8d02511486959bfe3b6 /config-provisioning/src/main/java/com/yahoo/config
parent8e3d49401f0a8d24690cd29522eca1414f659263 (diff)
Add CloudName to CloudAccount
Diffstat (limited to 'config-provisioning/src/main/java/com/yahoo/config')
-rw-r--r--config-provisioning/src/main/java/com/yahoo/config/provision/CloudAccount.java96
1 files changed, 63 insertions, 33 deletions
diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/CloudAccount.java b/config-provisioning/src/main/java/com/yahoo/config/provision/CloudAccount.java
index 215afbca255..465e4573d60 100644
--- a/config-provisioning/src/main/java/com/yahoo/config/provision/CloudAccount.java
+++ b/config-provisioning/src/main/java/com/yahoo/config/provision/CloudAccount.java
@@ -1,40 +1,41 @@
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.config.provision;
-import ai.vespa.validation.PatternedStringWrapper;
-import ai.vespa.validation.Validation;
-
+import java.util.Map;
+import java.util.Objects;
import java.util.regex.Pattern;
+import java.util.stream.Collectors;
/**
* Identifies an account in a public cloud, such as {@link CloudName#AWS} or {@link CloudName#GCP}.
*
* @author mpolden
*/
-public class CloudAccount extends PatternedStringWrapper<CloudAccount> {
+public class CloudAccount implements Comparable<CloudAccount> {
- private static final String EMPTY = "";
- private static final String AWS_ACCOUNT_ID = "[0-9]{12}";
- private static final Pattern AWS_ACCOUNT_ID_PATTERN = Pattern.compile(AWS_ACCOUNT_ID);
- private static final String GCP_PROJECT_ID = "[a-z][a-z0-9-]{4,28}[a-z0-9]";
- private static final Pattern GCP_PROJECT_ID_PATTERN = Pattern.compile(GCP_PROJECT_ID);
+ private record CloudMeta(String accountType, Pattern pattern) {
+ private boolean matches(String account) { return pattern.matcher(account).matches(); }
+ }
+ private static final Map<String, CloudMeta> META_BY_CLOUD = Map.of(
+ "aws", new CloudMeta("Account ID", Pattern.compile("[0-9]{12}")),
+ "gcp", new CloudMeta("Project name", Pattern.compile("[a-z][a-z0-9-]{4,28}[a-z0-9]")));
/** Empty value. When this is used, either implicitly or explicitly, the zone will use its default account */
- public static final CloudAccount empty = new CloudAccount("", EMPTY, "cloud account");
+ public static final CloudAccount empty = new CloudAccount("", CloudName.DEFAULT);
- /** Verifies accountId is a valid AWS account ID, or throw an IllegalArgumentException. */
- public static void requireAwsAccountId(String accountId) {
- Validation.requireMatch(accountId, "AWS account ID", AWS_ACCOUNT_ID_PATTERN);
- }
+ private final String account;
+ private final CloudName cloudName;
- /** Verifies accountId is a valid GCP project ID, or throw an IllegalArgumentException. */
- public static void requireGcpProjectId(String projectId) {
- Validation.requireMatch(projectId, "GCP project ID", GCP_PROJECT_ID_PATTERN);
+ private CloudAccount(String account, CloudName cloudName) {
+ this.account = account;
+ this.cloudName = cloudName;
}
- private CloudAccount(String value, String regex, String description) {
- super(value, Pattern.compile("^(" + regex + ")$"), description);
- }
+ public String account() { return account; }
+ public CloudName cloudName() { return cloudName; }
+
+ /** Returns the serialized value of this account that can be deserialized with {@link CloudAccount#from} */
+ public final String value() { return account; } // TODO (freva): Change to cloudName:account
public boolean isUnspecified() {
return this.equals(empty);
@@ -47,27 +48,56 @@ public class CloudAccount extends PatternedStringWrapper<CloudAccount> {
!equals(zone.cloud().account());
}
- /** Verifies this account is a valid AWS account ID, or throw an IllegalArgumentException. */
- public void requireAwsAccountId() {
- requireAwsAccountId(value());
+ @Override
+ public String toString() {
+ return isUnspecified() ? "unspecified account" : "account '" + account + "' in " + cloudName;
}
- /** Verifies this account is a valid GCP project ID, or throw an IllegalArgumentException. */
- public void requireGcpProjectId() {
- requireGcpProjectId(value());
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ CloudAccount that = (CloudAccount) o;
+ return account.equals(that.account) && cloudName.equals(that.cloudName);
}
+ @Override
+ public int hashCode() {
+ return Objects.hash(account, cloudName);
+ }
+
+ @Override
+ public int compareTo(CloudAccount o) {
+ return this.value().compareTo(o.value());
+ }
+
+
public static CloudAccount from(String cloudAccount) {
- return switch (cloudAccount) {
+ int index = cloudAccount.indexOf(':');
+ if (index < 0) {
// Tenants are allowed to specify "default" in services.xml.
- case "", "default" -> empty;
- default -> new CloudAccount(cloudAccount, AWS_ACCOUNT_ID + "|" + GCP_PROJECT_ID, "cloud account");
- };
+ if (cloudAccount.isEmpty() || cloudAccount.equals("default"))
+ return empty;
+ if (META_BY_CLOUD.get("aws").matches(cloudAccount))
+ return new CloudAccount(cloudAccount, CloudName.AWS);
+ if (META_BY_CLOUD.get("gcp").matches(cloudAccount)) // TODO (freva): Remove July 2023
+ return new CloudAccount(cloudAccount, CloudName.GCP);
+ throw illegal(cloudAccount, "Must be on format '<cloud-name>:<account>' or 'default'");
+ }
+
+ String cloud = cloudAccount.substring(0, index);
+ String account = cloudAccount.substring(index + 1);
+ CloudMeta cloudMeta = META_BY_CLOUD.get(cloud);
+ if (cloudMeta == null)
+ throw illegal(cloudAccount, "Cloud name must be one of: " + META_BY_CLOUD.keySet().stream().sorted().collect(Collectors.joining(", ")));
+
+ if (!cloudMeta.matches(account))
+ throw illegal(cloudAccount, cloudMeta.accountType + " must match '" + cloudMeta.pattern.pattern() + "'");
+ return new CloudAccount(account, CloudName.from(cloud));
}
- @Override
- public String toString() {
- return isUnspecified() ? "unspecified account" : "account '" + value() + "'";
+ private static IllegalArgumentException illegal(String cloudAccount, String details) {
+ return new IllegalArgumentException("Invalid cloud account '" + cloudAccount + "': " + details);
}
}