aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Polden <mpolden@mpolden.no>2022-08-17 11:37:07 +0200
committerMartin Polden <mpolden@mpolden.no>2022-08-17 11:37:07 +0200
commit265dad4b6c20059978edd4b9f5ebe17ea4712764 (patch)
treed0478d66f61bc0597a369e7e6947070f88ffdfb8
parent7431909f44dcdf905cd81c3032e5322551abcff1 (diff)
Require that requested region is configured in cloud account
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/zone/ZoneRegistry.java4
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/pkg/ApplicationPackageValidator.java23
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java17
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ZoneRegistryMock.java12
4 files changed, 48 insertions, 8 deletions
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/zone/ZoneRegistry.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/zone/ZoneRegistry.java
index 8b4c00e9b9d..e0524091c39 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/zone/ZoneRegistry.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/zone/ZoneRegistry.java
@@ -4,6 +4,7 @@ package com.yahoo.vespa.hosted.controller.api.integration.zone;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ApplicationName;
import com.yahoo.config.provision.AthenzDomain;
+import com.yahoo.config.provision.CloudAccount;
import com.yahoo.config.provision.CloudName;
import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.NodeType;
@@ -34,6 +35,9 @@ public interface ZoneRegistry {
/** Returns whether the system of this registry contains the given zone */
boolean hasZone(ZoneId zoneId);
+ /** Returns whether cloudAccount in this system supports given zone */
+ boolean hasZone(ZoneId zoneId, CloudAccount cloudAccount);
+
/** Returns a list containing the id of all zones in this registry */
ZoneFilter zones();
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/pkg/ApplicationPackageValidator.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/pkg/ApplicationPackageValidator.java
index 281ac50e63a..b3df417bd80 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/pkg/ApplicationPackageValidator.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/pkg/ApplicationPackageValidator.java
@@ -11,6 +11,7 @@ import com.yahoo.config.provision.CloudAccount;
import com.yahoo.config.provision.CloudName;
import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.InstanceName;
+import com.yahoo.config.provision.RegionName;
import com.yahoo.config.provision.TenantName;
import com.yahoo.config.provision.zone.ZoneApi;
import com.yahoo.config.provision.zone.ZoneId;
@@ -54,8 +55,8 @@ public class ApplicationPackageValidator {
* @throws IllegalArgumentException if any validations fail
*/
public void validate(Application application, ApplicationPackage applicationPackage, Instant instant) {
- validateSteps(applicationPackage.deploymentSpec());
validateCloudAccounts(application, applicationPackage.deploymentSpec());
+ validateSteps(applicationPackage.deploymentSpec());
validateEndpointRegions(applicationPackage.deploymentSpec());
validateEndpointChange(application, applicationPackage, instant);
validateCompactedEndpoint(applicationPackage);
@@ -88,12 +89,22 @@ public class ApplicationPackageValidator {
private void validateSteps(DeploymentSpec deploymentSpec) {
for (var spec : deploymentSpec.instances()) {
for (var zone : spec.zones()) {
- if (zone.environment().isManuallyDeployed())
- throw new IllegalArgumentException("region must be one with automated deployments, but got: " + zone.environment());
+ Environment environment = zone.environment();
+ if (environment.isManuallyDeployed())
+ throw new IllegalArgumentException("region must be one with automated deployments, but got: " + environment);
- if ( zone.environment() == Environment.prod
- && ! controller.zoneRegistry().hasZone(ZoneId.from(zone.environment(), zone.region().orElseThrow())))
- throw new IllegalArgumentException("Zone " + zone + " in deployment spec was not found in this system!");
+ if (environment == Environment.prod) {
+ RegionName region = zone.region().orElseThrow();
+ if (!controller.zoneRegistry().hasZone(ZoneId.from(environment, region))) {
+ throw new IllegalArgumentException("Zone " + zone + " in deployment spec was not found in this system!");
+ }
+ Optional<CloudAccount> cloudAccount = spec.cloudAccount(environment, region);
+ if (cloudAccount.isPresent() && !controller.zoneRegistry().hasZone(ZoneId.from(environment, region), cloudAccount.get())) {
+ throw new IllegalArgumentException("Zone " + zone + " in deployment spec is not configured for " +
+ "use in cloud account '" + cloudAccount.get().value() +
+ "', in this system");
+ }
+ }
}
}
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java
index b5177cd1d3e..6c193e9b539 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java
@@ -9,6 +9,7 @@ import com.yahoo.config.application.api.ValidationOverrides;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.AthenzDomain;
import com.yahoo.config.provision.AthenzService;
+import com.yahoo.config.provision.CloudAccount;
import com.yahoo.config.provision.CloudName;
import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.Environment;
@@ -1194,13 +1195,25 @@ public class ControllerTest {
.cloudAccount(cloudAccount)
.region(zone.region())
.build();
+ // Deployment fails because cloud account is not declared for this tenant
try {
context.submit(applicationPackage).deploy();
- fail("Expected exception"); // Account invalid for tenant
- } catch (IllegalArgumentException ignored) {
+ fail("Expected exception");
+ } catch (IllegalArgumentException e) {
+ assertEquals("Cloud account '012345678912' is not valid for tenant 'tenant'", e.getMessage());
}
+ // Deployment fails because requested region is not configured in cloud account
tester.controllerTester().flagSource().withListFlag(PermanentFlags.CLOUD_ACCOUNTS.id(), List.of(cloudAccount), String.class);
+ try {
+ context.submit(applicationPackage).deploy();
+ fail("Expected exception");
+ } catch (IllegalArgumentException e) {
+ assertEquals("Zone prod.us-west-1 in deployment spec is not configured for use in cloud account '012345678912', in this system", e.getMessage());
+ }
+
+ // Deployment succeeds
+ tester.controllerTester().zoneRegistry().setCloudAccountZones(new CloudAccount(cloudAccount), zone);
context.submit(applicationPackage).deploy();
assertEquals(cloudAccount, tester.controllerTester().configServer().cloudAccount(context.deploymentIdIn(zone)).get().value());
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ZoneRegistryMock.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ZoneRegistryMock.java
index 4131bfd8b9f..680e69998b6 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ZoneRegistryMock.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ZoneRegistryMock.java
@@ -5,6 +5,7 @@ import com.yahoo.component.AbstractComponent;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ApplicationName;
import com.yahoo.config.provision.AthenzDomain;
+import com.yahoo.config.provision.CloudAccount;
import com.yahoo.config.provision.CloudName;
import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.NodeType;
@@ -43,6 +44,7 @@ public class ZoneRegistryMock extends AbstractComponent implements ZoneRegistry
private final Map<Environment, RegionName> defaultRegionForEnvironment = new HashMap<>();
private final Map<CloudName, UpgradePolicy> osUpgradePolicies = new HashMap<>();
private final Map<ZoneApi, List<RoutingMethod>> zoneRoutingMethods = new HashMap<>();
+ private final Map<CloudAccount, Set<ZoneId>> cloudAccountZones = new HashMap<>();
private final Set<ZoneApi> reprovisionToUpgradeOs = new HashSet<>();
private final SystemName system; // Don't even think about making it non-final! ƪ(`▿▿▿▿´ƪ)
@@ -146,6 +148,11 @@ public class ZoneRegistryMock extends AbstractComponent implements ZoneRegistry
return this;
}
+ public ZoneRegistryMock setCloudAccountZones(CloudAccount cloudAccount, ZoneId... zones) {
+ this.cloudAccountZones.put(cloudAccount, Set.of(zones));
+ return this;
+ }
+
@Override
public SystemName system() {
return system;
@@ -254,6 +261,11 @@ public class ZoneRegistryMock extends AbstractComponent implements ZoneRegistry
}
@Override
+ public boolean hasZone(ZoneId zoneId, CloudAccount cloudAccount) {
+ return hasZone(zoneId) && cloudAccountZones.getOrDefault(cloudAccount, Set.of()).contains(zoneId);
+ }
+
+ @Override
public URI getConfigServerVipUri(ZoneId zoneId) {
return URI.create(Text.format("https://cfg.%s.test.vip:4443/", zoneId.value()));
}