summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Polden <mpolden@mpolden.no>2019-08-14 12:42:52 +0200
committerMartin Polden <mpolden@mpolden.no>2019-08-14 12:42:52 +0200
commit4d749d73789b85c97bbe6e727c577b06c47b776f (patch)
treece0a6d96eb95256c020c40c0c34da95c3b57a6ac
parentb4497df7d1230b3d86352de431b2d8a648e80f85 (diff)
Disallow endpoints containing different clouds
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/DeploymentSpecValidator.java21
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java35
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ZoneRegistryMock.java4
3 files changed, 60 insertions, 0 deletions
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/DeploymentSpecValidator.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/DeploymentSpecValidator.java
index 27053c3ee6c..ce7904dc829 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/DeploymentSpecValidator.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/DeploymentSpecValidator.java
@@ -2,12 +2,16 @@
package com.yahoo.vespa.hosted.controller.application;
import com.yahoo.config.application.api.DeploymentSpec;
+import com.yahoo.config.provision.CloudName;
import com.yahoo.config.provision.Environment;
+import com.yahoo.config.provision.zone.ZoneApi;
import com.yahoo.config.provision.zone.ZoneId;
import com.yahoo.vespa.hosted.controller.Controller;
import com.yahoo.vespa.hosted.controller.deployment.DeploymentSteps;
+import java.util.HashSet;
import java.util.Objects;
+import java.util.stream.Collectors;
/**
* This contains validators for a {@link DeploymentSpec} that depend on a {@link Controller} to perform validation.
@@ -29,6 +33,7 @@ public class DeploymentSpecValidator {
*/
public void validate(DeploymentSpec deploymentSpec) {
validateSteps(deploymentSpec);
+ validateEndpoints(deploymentSpec);
}
/** Verify that each of the production zones listed in the deployment spec exist in this system */
@@ -44,4 +49,20 @@ public class DeploymentSpecValidator {
});
}
+ /** Verify that no single endpoint contains regions in different clouds */
+ private void validateEndpoints(DeploymentSpec deploymentSpec) {
+ for (var endpoint : deploymentSpec.endpoints()) {
+ var clouds = new HashSet<CloudName>();
+ for (var region : endpoint.regions()) {
+ for (ZoneApi zone : controller.zoneRegistry().zones().all().in(region).zones()) {
+ clouds.add(zone.getCloudName());
+ }
+ }
+ if (clouds.size() != 1) {
+ throw new IllegalArgumentException("Endpoint '" + endpoint.endpointId() + "' cannot contain regions in different clouds: " +
+ endpoint.regions().stream().sorted().collect(Collectors.toList()));
+ }
+ }
+ }
+
}
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 f226fe9e4e3..998589dc23c 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
@@ -8,6 +8,7 @@ import com.yahoo.config.application.api.ValidationId;
import com.yahoo.config.application.api.ValidationOverrides;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ApplicationName;
+import com.yahoo.config.provision.CloudName;
import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.InstanceName;
import com.yahoo.config.provision.RegionName;
@@ -734,6 +735,40 @@ public class ControllerTest {
assertTrue("Provisions certificate in " + Environment.dev, certificate.apply(app2).isPresent());
}
+ @Test
+ public void testDeployWithCrossCloudEndpoints() {
+ tester.controllerTester().zoneRegistry().setZones(
+ ZoneApiMock.fromId("prod.us-west-1"),
+ ZoneApiMock.newBuilder().with(CloudName.from("aws")).withId("prod.aws-us-east-1").build()
+ );
+ var application = tester.createApplication("app1", "tenant1", 1L, 1L);
+ var applicationPackage = new ApplicationPackageBuilder()
+ .region("aws-us-east-1")
+ .region("us-west-1")
+ .endpoint("default", "default") // Contains to all regions by default
+ .build();
+
+ try {
+ tester.deployCompletely(application, applicationPackage);
+ fail("Expected exception");
+ } catch (IllegalArgumentException e) {
+ assertEquals("Endpoint 'default' cannot contain regions in different clouds: [aws-us-east-1, us-west-1]", e.getMessage());
+ }
+
+ var applicationPackage2 = new ApplicationPackageBuilder()
+ .region("aws-us-east-1")
+ .region("us-west-1")
+ .endpoint("aws", "default", "aws-us-east-1")
+ .endpoint("foo", "default", "aws-us-east-1", "us-west-1")
+ .build();
+ try {
+ tester.deployCompletely(application, applicationPackage2);
+ fail("Expected exception");
+ } catch (IllegalArgumentException e) {
+ assertEquals("Endpoint 'foo' cannot contain regions in different clouds: [aws-us-east-1, us-west-1]", e.getMessage());
+ }
+ }
+
private void runUpgrade(DeploymentTester tester, ApplicationId application, ApplicationVersion version) {
Version next = Version.fromString("6.2");
tester.upgradeSystem(next);
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 cff0f8da463..b555ae24305 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
@@ -50,6 +50,10 @@ public class ZoneRegistryMock extends AbstractComponent implements ZoneRegistry
this(SystemName.main);
}
+ /**
+ * This sets the default list of zones contained in this. If your test need a particular set of zones, use
+ * {@link #setZones(List)} instead of changing the default set.}
+ */
public ZoneRegistryMock(SystemName system) {
this.system = system;
setZones(List.of(