summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Bratseth <bratseth@oath.com>2019-11-30 08:44:26 +0100
committerGitHub <noreply@github.com>2019-11-30 08:44:26 +0100
commite346de03f3ff1b37e9b7ce94399492fdebcd5ac6 (patch)
tree4023bb0e6c835026ffb18f5f00580121455a906c
parent21620abb46bbfb18abeb6c8cc917b39fb0e316b8 (diff)
parent12fcbd278a5fadb085456f0cde9059755c0fe231 (diff)
Merge pull request #11460 from vespa-engine/revert-11456-jvenstad/test-steps-in-deployment-spec
Revert "Jvenstad/test steps in deployment spec"
-rw-r--r--config-model-api/abi-spec.json68
-rw-r--r--config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentInstanceSpec.java115
-rw-r--r--config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentSpec.java165
-rw-r--r--config-model-api/src/main/java/com/yahoo/config/application/api/xml/DeploymentSpecXmlReader.java23
-rw-r--r--config-model-api/src/test/java/com/yahoo/config/application/api/DeploymentSpecTest.java223
-rw-r--r--config-model-api/src/test/java/com/yahoo/config/application/api/DeploymentSpecWithoutInstanceTest.java207
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java2
-rw-r--r--config-model/src/main/resources/schema/deployment.rnc23
-rw-r--r--config-model/src/test/cfg/application/app_complicated_deployment_spec/deployment.xml48
-rw-r--r--config-model/src/test/cfg/application/app_complicated_deployment_spec/hosts.xml21
-rw-r--r--config-model/src/test/cfg/application/app_complicated_deployment_spec/searchdefinitions/music.sd37
-rw-r--r--config-model/src/test/cfg/application/app_complicated_deployment_spec/services.xml59
-rw-r--r--config-model/src/test/cfg/application/invalid_parallel_deployment_xml/deployment.xml4
-rw-r--r--config-model/src/test/java/com/yahoo/config/model/ApplicationDeployTest.java11
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java12
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentSteps.java3
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunner.java2
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/rotation/RotationRepository.java2
18 files changed, 219 insertions, 806 deletions
diff --git a/config-model-api/abi-spec.json b/config-model-api/abi-spec.json
index 163653f703b..edf83fe4475 100644
--- a/config-model-api/abi-spec.json
+++ b/config-model-api/abi-spec.json
@@ -188,7 +188,7 @@
"fields": []
},
"com.yahoo.config.application.api.DeploymentInstanceSpec": {
- "superClass": "com.yahoo.config.application.api.DeploymentSpec$Steps",
+ "superClass": "com.yahoo.config.application.api.DeploymentSpec$Step",
"interfaces": [],
"attributes": [
"public"
@@ -196,16 +196,20 @@
"methods": [
"public void <init>(com.yahoo.config.provision.InstanceName, java.util.List, com.yahoo.config.application.api.DeploymentSpec$UpgradePolicy, java.util.List, java.util.Optional, java.util.Optional, java.util.Optional, com.yahoo.config.application.api.Notifications, java.util.List)",
"public com.yahoo.config.provision.InstanceName name()",
+ "public java.time.Duration delay()",
+ "public java.util.List steps()",
"public com.yahoo.config.application.api.DeploymentSpec$UpgradePolicy upgradePolicy()",
"public java.util.List changeBlocker()",
"public java.util.Optional globalServiceId()",
"public boolean canUpgradeAt(java.time.Instant)",
"public boolean canChangeRevisionAt(java.time.Instant)",
+ "public java.util.List zones()",
+ "public boolean deploysTo(com.yahoo.config.provision.Environment, java.util.Optional)",
"public java.util.Optional athenzDomain()",
"public java.util.Optional athenzService(com.yahoo.config.provision.Environment, com.yahoo.config.provision.RegionName)",
"public com.yahoo.config.application.api.Notifications notifications()",
"public java.util.List endpoints()",
- "public boolean deploysTo(com.yahoo.config.provision.Environment, java.util.Optional)",
+ "public boolean includes(com.yahoo.config.provision.Environment, java.util.Optional)",
"public boolean equals(java.lang.Object)",
"public int hashCode()",
"public java.lang.String toString()"
@@ -227,23 +231,6 @@
],
"fields": []
},
- "com.yahoo.config.application.api.DeploymentSpec$DeclaredTest": {
- "superClass": "com.yahoo.config.application.api.DeploymentSpec$Step",
- "interfaces": [],
- "attributes": [
- "public"
- ],
- "methods": [
- "public void <init>(com.yahoo.config.provision.RegionName)",
- "public boolean concerns(com.yahoo.config.provision.Environment, java.util.Optional)",
- "public boolean isTest()",
- "public com.yahoo.config.provision.RegionName region()",
- "public boolean equals(java.lang.Object)",
- "public int hashCode()",
- "public java.lang.String toString()"
- ],
- "fields": []
- },
"com.yahoo.config.application.api.DeploymentSpec$DeclaredZone": {
"superClass": "com.yahoo.config.application.api.DeploymentSpec$Step",
"interfaces": [],
@@ -259,8 +246,7 @@
"public java.util.Optional testerFlavor()",
"public java.util.Optional athenzService()",
"public java.util.List zones()",
- "public boolean concerns(com.yahoo.config.provision.Environment, java.util.Optional)",
- "public boolean isTest()",
+ "public boolean deploysTo(com.yahoo.config.provision.Environment, java.util.Optional)",
"public int hashCode()",
"public boolean equals(java.lang.Object)",
"public java.lang.String toString()"
@@ -276,21 +262,22 @@
"methods": [
"public void <init>(java.time.Duration)",
"public java.time.Duration delay()",
- "public boolean concerns(com.yahoo.config.provision.Environment, java.util.Optional)",
+ "public boolean deploysTo(com.yahoo.config.provision.Environment, java.util.Optional)",
"public java.lang.String toString()"
],
"fields": []
},
- "com.yahoo.config.application.api.DeploymentSpec$ParallelSteps": {
- "superClass": "com.yahoo.config.application.api.DeploymentSpec$Steps",
+ "com.yahoo.config.application.api.DeploymentSpec$ParallelZones": {
+ "superClass": "com.yahoo.config.application.api.DeploymentSpec$Step",
"interfaces": [],
"attributes": [
"public"
],
"methods": [
"public void <init>(java.util.List)",
- "public java.time.Duration delay()",
- "public boolean isOrdered()",
+ "public java.util.List zones()",
+ "public java.util.List steps()",
+ "public boolean deploysTo(com.yahoo.config.provision.Environment, java.util.Optional)",
"public boolean equals(java.lang.Object)",
"public int hashCode()",
"public java.lang.String toString()"
@@ -306,31 +293,11 @@
],
"methods": [
"public void <init>()",
- "public final boolean concerns(com.yahoo.config.provision.Environment)",
- "public abstract boolean concerns(com.yahoo.config.provision.Environment, java.util.Optional)",
+ "public final boolean deploysTo(com.yahoo.config.provision.Environment)",
+ "public abstract boolean deploysTo(com.yahoo.config.provision.Environment, java.util.Optional)",
"public java.util.List zones()",
"public java.time.Duration delay()",
- "public java.util.List steps()",
- "public boolean isTest()",
- "public boolean isOrdered()"
- ],
- "fields": []
- },
- "com.yahoo.config.application.api.DeploymentSpec$Steps": {
- "superClass": "com.yahoo.config.application.api.DeploymentSpec$Step",
- "interfaces": [],
- "attributes": [
- "public"
- ],
- "methods": [
- "public void <init>(java.util.List)",
- "public java.util.List zones()",
- "public java.util.List steps()",
- "public boolean concerns(com.yahoo.config.provision.Environment, java.util.Optional)",
- "public java.time.Duration delay()",
- "public boolean equals(java.lang.Object)",
- "public int hashCode()",
- "public java.lang.String toString()"
+ "public java.util.List steps()"
],
"fields": []
},
@@ -364,6 +331,7 @@
"public java.util.List steps()",
"public java.util.Optional athenzDomain()",
"public java.util.Optional athenzService()",
+ "public java.util.Optional athenzService(com.yahoo.config.provision.InstanceName, com.yahoo.config.provision.Environment, com.yahoo.config.provision.RegionName)",
"public java.lang.String xmlForm()",
"public java.util.Optional instance(com.yahoo.config.provision.InstanceName)",
"public com.yahoo.config.application.api.DeploymentInstanceSpec requireInstance(java.lang.String)",
@@ -604,4 +572,4 @@
"public static final com.yahoo.config.application.api.ValidationOverrides all"
]
}
-} \ No newline at end of file
+}
diff --git a/config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentInstanceSpec.java b/config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentInstanceSpec.java
index 541e52cf6e9..f96400fc9a9 100644
--- a/config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentInstanceSpec.java
+++ b/config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentInstanceSpec.java
@@ -7,6 +7,7 @@ import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.InstanceName;
import com.yahoo.config.provision.RegionName;
+import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.HashSet;
@@ -21,11 +22,12 @@ import java.util.stream.Collectors;
*
* @author bratseth
*/
-public class DeploymentInstanceSpec extends DeploymentSpec.Steps {
+public class DeploymentInstanceSpec extends DeploymentSpec.Step {
/** The name of the instance this step deploys */
private final InstanceName name;
+ private final List<DeploymentSpec.Step> steps;
private final DeploymentSpec.UpgradePolicy upgradePolicy;
private final List<DeploymentSpec.ChangeBlocker> changeBlockers;
private final Optional<String> globalServiceId;
@@ -43,54 +45,34 @@ public class DeploymentInstanceSpec extends DeploymentSpec.Steps {
Optional<AthenzService> athenzService,
Notifications notifications,
List<Endpoint> endpoints) {
- super(steps);
this.name = name;
+ this.steps = steps;
this.upgradePolicy = upgradePolicy;
this.changeBlockers = changeBlockers;
this.globalServiceId = globalServiceId;
this.athenzDomain = athenzDomain;
this.athenzService = athenzService;
this.notifications = notifications;
- this.endpoints = List.copyOf(validateEndpoints(endpoints, steps()));
- validateZones(new HashSet<>(), this);
- validateEndpoints(steps(), globalServiceId, this.endpoints);
+ this.endpoints = List.copyOf(validateEndpoints(endpoints, this.steps));
+ validateZones(this.steps);
+ validateEndpoints(this.steps, globalServiceId, this.endpoints);
validateAthenz();
}
public InstanceName name() { return name; }
- /**
- * Throws an IllegalArgumentException if any production deployment or test is declared multiple times,
- * or if any production test is declared not after its corresponding deployment.
- *
- * @param deployments previously seen deployments
- * @param step step whose members to validate
- * @return all contained tests
- */
- private static Set<RegionName> validateZones(Set<RegionName> deployments, DeploymentSpec.Step step) {
- if ( ! step.steps().isEmpty()) {
- Set<RegionName> oldDeployments = Set.copyOf(deployments);
- Set<RegionName> tests = new HashSet<>();
- for (DeploymentSpec.Step nested : step.steps()) {
- for (RegionName test : validateZones(deployments, nested)) {
- if ( ! (step.isOrdered() ? deployments : oldDeployments).contains(test))
- throw new IllegalArgumentException("tests for prod." + test + " must be after the corresponding deployment in deployment.xml");
-
- if ( ! tests.add(test))
- throw new IllegalArgumentException("tests for prod." + test + " arelisted twice in deployment.xml");
- }
- }
- return tests;
- }
- if (step.concerns(Environment.prod)) {
- if (step.isTest())
- return Set.of(((DeploymentSpec.DeclaredTest) step).region());
+ /** Throw an IllegalArgumentException if any production zone is declared multiple times */
+ private void validateZones(List<DeploymentSpec.Step> steps) {
+ Set<DeploymentSpec.DeclaredZone> zones = new HashSet<>();
- RegionName region = ((DeploymentSpec.DeclaredZone) step).region().get();
- if ( ! deployments.add(region))
- throw new IllegalArgumentException("prod." + region + " is listed twice in deployment.xml");
- }
- return Set.of();
+ for (DeploymentSpec.Step step : steps)
+ for (DeploymentSpec.DeclaredZone zone : step.zones())
+ ensureUnique(zone, zones);
+ }
+
+ private void ensureUnique(DeploymentSpec.DeclaredZone zone, Set<DeploymentSpec.DeclaredZone> zones) {
+ if ( ! zones.add(zone))
+ throw new IllegalArgumentException(zone + " is listed twice in deployment.xml");
}
/** Validates the endpoints and makes sure default values are respected */
@@ -98,7 +80,7 @@ public class DeploymentInstanceSpec extends DeploymentSpec.Steps {
Objects.requireNonNull(endpoints, "Missing endpoints parameter");
var productionRegions = steps.stream()
- .filter(step -> step.concerns(Environment.prod))
+ .filter(step -> step.deploysTo(Environment.prod))
.flatMap(step -> step.zones().stream())
.flatMap(zone -> zone.region().stream())
.map(RegionName::value)
@@ -161,6 +143,15 @@ public class DeploymentInstanceSpec extends DeploymentSpec.Steps {
}
}
+ @Override
+ public Duration delay() {
+ return Duration.ofSeconds(steps.stream().mapToLong(step -> (step.delay().getSeconds())).sum());
+ }
+
+ /** Returns the deployment steps inside this in the order they will be performed */
+ @Override
+ public List<DeploymentSpec.Step> steps() { return steps; }
+
/** Returns the upgrade policy of this, which is defaultPolicy if none is specified */
public DeploymentSpec.UpgradePolicy upgradePolicy() { return upgradePolicy; }
@@ -182,16 +173,32 @@ public class DeploymentInstanceSpec extends DeploymentSpec.Steps {
.noneMatch(block -> block.window().includes(instant));
}
+ /** Returns all the deployment steps which are zones in the order they are declared */
+ public List<DeploymentSpec.DeclaredZone> zones() {
+ return steps.stream()
+ .flatMap(step -> step.zones().stream())
+ .collect(Collectors.toList());
+ }
+
+ /** Returns whether this deployment spec specifies the given zone, either implicitly or explicitly */
+ @Override
+ public boolean deploysTo(Environment environment, Optional<RegionName> region) {
+ for (DeploymentSpec.Step step : steps)
+ if (step.deploysTo(environment, region)) return true;
+ return false;
+ }
+
/** Returns the athenz domain if configured */
public Optional<AthenzDomain> athenzDomain() { return athenzDomain; }
/** Returns the athenz service for environment/region if configured */
public Optional<AthenzService> athenzService(Environment environment, RegionName region) {
- return zones().stream()
- .filter(zone -> zone.concerns(environment, Optional.of(region)))
- .findFirst()
- .flatMap(DeploymentSpec.DeclaredZone::athenzService)
- .or(() -> this.athenzService);
+ AthenzService athenzService = zones().stream()
+ .filter(zone -> zone.deploysTo(environment, Optional.of(region)))
+ .findFirst()
+ .flatMap(DeploymentSpec.DeclaredZone::athenzService)
+ .orElse(this.athenzService.orElse(null));
+ return Optional.ofNullable(athenzService);
}
/** Returns the notification configuration of these instances */
@@ -200,9 +207,23 @@ public class DeploymentInstanceSpec extends DeploymentSpec.Steps {
/** Returns the rotations configuration of these instances */
public List<Endpoint> endpoints() { return endpoints; }
- /** Returns whether this instance deploys to the given zone, either implicitly or explicitly */
- public boolean deploysTo(Environment environment, Optional<RegionName> region) {
- return zones().stream().anyMatch(zone -> zone.concerns(environment, region));
+ /** Returns whether this instances deployment specifies the given zone, either implicitly or explicitly */
+ public boolean includes(Environment environment, Optional<RegionName> region) {
+ for (DeploymentSpec.Step step : steps)
+ if (step.deploysTo(environment, region)) return true;
+ return false;
+ }
+
+ DeploymentInstanceSpec withSteps(List<DeploymentSpec.Step> steps) {
+ return new DeploymentInstanceSpec(name,
+ steps,
+ upgradePolicy,
+ changeBlockers,
+ globalServiceId,
+ athenzDomain,
+ athenzService,
+ notifications,
+ endpoints);
}
@Override
@@ -213,7 +234,7 @@ public class DeploymentInstanceSpec extends DeploymentSpec.Steps {
return globalServiceId.equals(other.globalServiceId) &&
upgradePolicy == other.upgradePolicy &&
changeBlockers.equals(other.changeBlockers) &&
- steps().equals(other.steps()) &&
+ steps.equals(other.steps) &&
athenzDomain.equals(other.athenzDomain) &&
athenzService.equals(other.athenzService) &&
notifications.equals(other.notifications) &&
@@ -222,7 +243,7 @@ public class DeploymentInstanceSpec extends DeploymentSpec.Steps {
@Override
public int hashCode() {
- return Objects.hash(globalServiceId, upgradePolicy, changeBlockers, steps(), athenzDomain, athenzService, notifications, endpoints);
+ return Objects.hash(globalServiceId, upgradePolicy, changeBlockers, steps, athenzDomain, athenzService, notifications, endpoints);
}
@Override
diff --git a/config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentSpec.java b/config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentSpec.java
index 67b3d585881..ea7df677e0f 100644
--- a/config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentSpec.java
+++ b/config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentSpec.java
@@ -13,12 +13,10 @@ import java.io.Reader;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
-import java.util.stream.Stream;
/**
* Specifies the environments and regions to which an application should be deployed.
@@ -77,14 +75,14 @@ public class DeploymentSpec {
List<Step> steps = new ArrayList<>(inputSteps);
// Add staging if required and missing
- if (steps.stream().anyMatch(step -> step.concerns(Environment.prod)) &&
- steps.stream().noneMatch(step -> step.concerns(Environment.staging))) {
+ if (steps.stream().anyMatch(step -> step.deploysTo(Environment.prod)) &&
+ steps.stream().noneMatch(step -> step.deploysTo(Environment.staging))) {
steps.add(new DeploymentSpec.DeclaredZone(Environment.staging));
}
// Add test if required and missing
- if (steps.stream().anyMatch(step -> step.concerns(Environment.staging)) &&
- steps.stream().noneMatch(step -> step.concerns(Environment.test))) {
+ if (steps.stream().anyMatch(step -> step.deploysTo(Environment.staging)) &&
+ steps.stream().noneMatch(step -> step.deploysTo(Environment.test))) {
steps.add(new DeploymentSpec.DeclaredZone(Environment.test));
}
@@ -164,6 +162,13 @@ public class DeploymentSpec {
// to have environment, instance or region variants on those.
public Optional<AthenzService> athenzService() { return this.athenzService; }
+ // TODO remove when 7.135 is the oldest version
+ public Optional<AthenzService> athenzService(InstanceName instanceName, Environment environment, RegionName region) {
+ Optional<DeploymentInstanceSpec> instance = instance(instanceName);
+ if (instance.isEmpty()) return this.athenzService;
+ return instance.get().athenzService(environment, region).or(() -> this.athenzService);
+ }
+
/** Returns the XML form of this spec, or null if it was not created by fromXml, nor is empty */
public String xmlForm() { return xmlForm; }
@@ -200,15 +205,11 @@ public class DeploymentSpec {
private static List<DeploymentInstanceSpec> instances(List<DeploymentSpec.Step> steps) {
return steps.stream()
- .flatMap(DeploymentSpec::flatten)
+ .flatMap(step -> step instanceof ParallelZones ? ((ParallelZones) step).steps.stream() : List.of(step).stream())
+ .filter(step -> step instanceof DeploymentInstanceSpec).map(DeploymentInstanceSpec.class::cast)
.collect(Collectors.toList());
}
- private static Stream<DeploymentInstanceSpec> flatten(Step step) {
- if (step instanceof DeploymentInstanceSpec) return Stream.of((DeploymentInstanceSpec) step);
- return step.steps().stream().flatMap(DeploymentSpec::flatten);
- }
-
/**
* Creates a deployment spec from XML.
*
@@ -271,31 +272,23 @@ public class DeploymentSpec {
/** A deployment step */
public abstract static class Step {
- /** Returns whether this step specifies the given environment. */
- public final boolean concerns(Environment environment) {
- return concerns(environment, Optional.empty());
+ /** Returns whether this step deploys to the given region */
+ public final boolean deploysTo(Environment environment) {
+ return deploysTo(environment, Optional.empty());
}
- /** Returns whether this step specifies the given environment, and, optionally, region. */
- public abstract boolean concerns(Environment environment, Optional<RegionName> region);
+ /** Returns whether this step deploys to the given environment, and (if specified) region */
+ public abstract boolean deploysTo(Environment environment, Optional<RegionName> region);
- /** Returns the zones deployed to in this step. */
+ /** Returns the zones deployed to in this step */
public List<DeclaredZone> zones() { return Collections.emptyList(); }
- /** The delay introduced by this step (beyond the time it takes to execute the step). */
+ /** The delay introduced by this step (beyond the time it takes to execute the step). Default is zero. */
public Duration delay() { return Duration.ZERO; }
- /** Returns any steps nested in this. */
+ /** Returns all the steps nested in this. This default implementatiino returns an empty list. */
public List<Step> steps() { return List.of(); }
- /** Returns whether this step is a test step. */
- public boolean isTest() { return false; }
-
- /** Returns whether the nested steps in this, if any, should be performed in declaration order. */
- public boolean isOrdered() {
- return true;
- }
-
}
/** A deployment step which is to wait for some time before progressing to the next step */
@@ -311,7 +304,7 @@ public class DeploymentSpec {
public Duration delay() { return duration; }
@Override
- public boolean concerns(Environment environment, Optional<RegionName> region) { return false; }
+ public boolean deploysTo(Environment environment, Optional<RegionName> region) { return false; }
@Override
public String toString() {
@@ -362,16 +355,13 @@ public class DeploymentSpec {
public List<DeclaredZone> zones() { return Collections.singletonList(this); }
@Override
- public boolean concerns(Environment environment, Optional<RegionName> region) {
+ public boolean deploysTo(Environment environment, Optional<RegionName> region) {
if (environment != this.environment) return false;
if (region.isPresent() && ! region.equals(this.region)) return false;
return true;
}
@Override
- public boolean isTest() { return environment.isTest(); }
-
- @Override
public int hashCode() {
return Objects.hash(environment, region);
}
@@ -393,82 +383,39 @@ public class DeploymentSpec {
}
- /** A declared production test */
- public static class DeclaredTest extends Step {
-
- private final RegionName region;
-
- public DeclaredTest(RegionName region) {
- this.region = Objects.requireNonNull(region);
- }
-
- @Override
- public boolean concerns(Environment environment, Optional<RegionName> region) {
- return region.map(this.region::equals).orElse(true) && environment == Environment.prod;
- }
-
- @Override
- public boolean isTest() { return true; }
-
- /** Returns the region this test is for. */
- public RegionName region() {
- return region;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- DeclaredTest that = (DeclaredTest) o;
- return region.equals(that.region);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(region);
- }
-
- @Override
- public String toString() {
- return "tests for prod." + region;
- }
-
- }
-
- /** A container for several steps, by default in serial order */
- public static class Steps extends Step {
+ /** A deployment step which is to run multiple steps (zones or instances) in parallel */
+ public static class ParallelZones extends Step {
private final List<Step> steps;
- public Steps(List<Step> steps) {
+ public ParallelZones(List<Step> steps) {
this.steps = List.copyOf(steps);
}
+ /** Returns the steps inside this which are zones */
@Override
public List<DeclaredZone> zones() {
- return steps.stream()
- .flatMap(step -> step.zones().stream())
- .collect(Collectors.toUnmodifiableList());
+ return this.steps.stream()
+ .filter(step -> step instanceof DeclaredZone)
+ .map(DeclaredZone.class::cast)
+ .collect(Collectors.toList());
}
+ /** Returns all the steps nested in this */
@Override
public List<Step> steps() { return steps; }
@Override
- public boolean concerns(Environment environment, Optional<RegionName> region) {
- return steps.stream().anyMatch(step -> step.concerns(environment, region));
- }
-
- @Override
- public Duration delay() {
- return steps.stream().map(Step::delay).reduce(Duration.ZERO, Duration::plus);
+ public boolean deploysTo(Environment environment, Optional<RegionName> region) {
+ return steps().stream().anyMatch(zone -> zone.deploysTo(environment, region));
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- return steps.equals(((Steps) o).steps);
+ if (!(o instanceof ParallelZones)) return false;
+ ParallelZones that = (ParallelZones) o;
+ return Objects.equals(steps, that.steps);
}
@Override
@@ -478,43 +425,7 @@ public class DeploymentSpec {
@Override
public String toString() {
- return steps.size() + " steps";
- }
-
- }
-
- /** A container for multiple other steps, which are executed in parallel */
- public static class ParallelSteps extends Steps {
-
- public ParallelSteps(List<Step> steps) {
- super(steps);
- }
-
- @Override
- public Duration delay() {
- return steps().stream().map(Step::delay).max(Comparator.naturalOrder()).orElse(Duration.ZERO);
- }
-
- @Override
- public boolean isOrdered() {
- return false;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if ( ! (o instanceof ParallelSteps)) return false;
- return Objects.equals(steps(), ((ParallelSteps) o).steps());
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(steps());
- }
-
- @Override
- public String toString() {
- return steps().size() + " parallel steps";
+ return steps.size() + " parallel steps";
}
}
diff --git a/config-model-api/src/main/java/com/yahoo/config/application/api/xml/DeploymentSpecXmlReader.java b/config-model-api/src/main/java/com/yahoo/config/application/api/xml/DeploymentSpecXmlReader.java
index c14e6ce5966..bc17ee0cb2b 100644
--- a/config-model-api/src/main/java/com/yahoo/config/application/api/xml/DeploymentSpecXmlReader.java
+++ b/config-model-api/src/main/java/com/yahoo/config/application/api/xml/DeploymentSpecXmlReader.java
@@ -3,12 +3,10 @@ package com.yahoo.config.application.api.xml;
import com.yahoo.config.application.api.DeploymentInstanceSpec;
import com.yahoo.config.application.api.DeploymentSpec;
-import com.yahoo.config.application.api.DeploymentSpec.DeclaredTest;
import com.yahoo.config.application.api.DeploymentSpec.DeclaredZone;
import com.yahoo.config.application.api.DeploymentSpec.Delay;
-import com.yahoo.config.application.api.DeploymentSpec.ParallelSteps;
+import com.yahoo.config.application.api.DeploymentSpec.ParallelZones;
import com.yahoo.config.application.api.DeploymentSpec.Step;
-import com.yahoo.config.application.api.DeploymentSpec.Steps;
import com.yahoo.config.application.api.Endpoint;
import com.yahoo.config.application.api.Notifications;
import com.yahoo.config.application.api.Notifications.Role;
@@ -22,7 +20,6 @@ import com.yahoo.config.provision.RegionName;
import com.yahoo.io.IOUtils;
import com.yahoo.text.XML;
import org.w3c.dom.Element;
-import org.w3c.dom.Node;
import java.io.IOException;
import java.io.Reader;
@@ -35,10 +32,8 @@ import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
-import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
-import java.util.stream.Stream;
/**
* @author bratseth
@@ -55,7 +50,6 @@ public class DeploymentSpecXmlReader {
private static final String regionTag = "region";
private static final String delayTag = "delay";
private static final String parallelTag = "parallel";
- private static final String stepsTag = "steps";
private static final String endpointsTag = "endpoints";
private static final String endpointTag = "endpoint";
private static final String notificationsTag = "notifications";
@@ -124,7 +118,7 @@ public class DeploymentSpecXmlReader {
*
* @param instanceNameString a comma-separated list of the names of the instances this is for
* @param instanceTag the element having the content of this instance
- * @param parentTag the parent of instanceTag (or the same, if this instance is implicitly defined, which means instanceTag is the root)
+ * @param parentTag the parent of instanceTag (or the same, if this instances is implicitly defined which means instanceTag is the root)
* @return the instances specified, one for each instance name element
*/
private List<DeploymentInstanceSpec> readInstanceContent(String instanceNameString,
@@ -175,7 +169,6 @@ public class DeploymentSpecXmlReader {
}
// Consume the given tag as 0-N steps. 0 if it is not a step, >1 if it contains multiple nested steps that should be flattened
- @SuppressWarnings("fallthrough")
private List<Step> readNonInstanceSteps(Element stepTag, MutableOptional<String> globalServiceId, Element parentTag) {
Optional<AthenzService> athenzService = stringAttribute(athenzServiceAttribute, stepTag)
.or(() -> stringAttribute(athenzServiceAttribute, parentTag))
@@ -189,11 +182,7 @@ public class DeploymentSpecXmlReader {
throw new IllegalArgumentException("Attribute 'global-service-id' is only valid on 'prod' tag.");
switch (stepTag.getTagName()) {
- case testTag:
- if (Stream.iterate(stepTag, Objects::nonNull, Node::getParentNode)
- .anyMatch(node -> prodTag.equals(node.getNodeName())))
- return List.of(new DeclaredTest(RegionName.from(XML.getValue(stepTag).trim())));
- case stagingTag:
+ case testTag: case stagingTag:
return List.of(new DeclaredZone(Environment.from(stepTag.getTagName()), Optional.empty(), false, athenzService, testerFlavor));
case prodTag: // regions, delay and parallel may be nested within, but we can flatten them
return XML.getChildren(stepTag).stream()
@@ -204,13 +193,9 @@ public class DeploymentSpecXmlReader {
longAttribute("minutes", stepTag) * 60 +
longAttribute("seconds", stepTag))));
case parallelTag: // regions and instances may be nested within
- return List.of(new ParallelSteps(XML.getChildren(stepTag).stream()
+ return List.of(new ParallelZones(XML.getChildren(stepTag).stream()
.flatMap(child -> readSteps(child, globalServiceId, parentTag).stream())
.collect(Collectors.toList())));
- case stepsTag: // regions and instances may be nested within
- return List.of(new Steps(XML.getChildren(stepTag).stream()
- .flatMap(child -> readSteps(child, globalServiceId, parentTag).stream())
- .collect(Collectors.toList())));
case regionTag:
return List.of(readDeclaredZone(Environment.prod, athenzService, testerFlavor, stepTag));
default:
diff --git a/config-model-api/src/test/java/com/yahoo/config/application/api/DeploymentSpecTest.java b/config-model-api/src/test/java/com/yahoo/config/application/api/DeploymentSpecTest.java
index 584664b6ef1..987e13c0e86 100644
--- a/config-model-api/src/test/java/com/yahoo/config/application/api/DeploymentSpecTest.java
+++ b/config-model-api/src/test/java/com/yahoo/config/application/api/DeploymentSpecTest.java
@@ -3,11 +3,11 @@ package com.yahoo.config.application.api;
import com.google.common.collect.ImmutableSet;
import com.yahoo.config.provision.Environment;
+import com.yahoo.config.provision.InstanceName;
import com.yahoo.config.provision.RegionName;
import org.junit.Test;
import java.io.StringReader;
-import java.time.Duration;
import java.time.Instant;
import java.time.ZoneId;
import java.util.Collections;
@@ -42,11 +42,11 @@ public class DeploymentSpecTest {
assertEquals(specXml, spec.xmlForm());
assertEquals(1, spec.requireInstance("default").steps().size());
assertFalse(spec.majorVersion().isPresent());
- assertTrue(spec.requireInstance("default").steps().get(0).concerns(Environment.test));
- assertTrue(spec.requireInstance("default").deploysTo(Environment.test, Optional.empty()));
- assertFalse(spec.requireInstance("default").deploysTo(Environment.test, Optional.of(RegionName.from("region1"))));
- assertFalse(spec.requireInstance("default").deploysTo(Environment.staging, Optional.empty()));
- assertFalse(spec.requireInstance("default").deploysTo(Environment.prod, Optional.empty()));
+ assertTrue(spec.requireInstance("default").steps().get(0).deploysTo(Environment.test));
+ assertTrue(spec.requireInstance("default").includes(Environment.test, Optional.empty()));
+ assertFalse(spec.requireInstance("default").includes(Environment.test, Optional.of(RegionName.from("region1"))));
+ assertFalse(spec.requireInstance("default").includes(Environment.staging, Optional.empty()));
+ assertFalse(spec.requireInstance("default").includes(Environment.prod, Optional.empty()));
assertFalse(spec.requireInstance("default").globalServiceId().isPresent());
}
@@ -79,11 +79,11 @@ public class DeploymentSpecTest {
DeploymentSpec spec = DeploymentSpec.fromXml(r);
assertEquals(2, spec.steps().size());
assertEquals(1, spec.requireInstance("default").steps().size());
- assertTrue(spec.steps().get(0).concerns(Environment.test));
- assertTrue(spec.requireInstance("default").steps().get(0).concerns(Environment.staging));
- assertFalse(spec.requireInstance("default").deploysTo(Environment.test, Optional.empty()));
- assertTrue(spec.requireInstance("default").deploysTo(Environment.staging, Optional.empty()));
- assertFalse(spec.requireInstance("default").deploysTo(Environment.prod, Optional.empty()));
+ assertTrue(spec.steps().get(0).deploysTo(Environment.test));
+ assertTrue(spec.requireInstance("default").steps().get(0).deploysTo(Environment.staging));
+ assertFalse(spec.requireInstance("default").includes(Environment.test, Optional.empty()));
+ assertTrue(spec.requireInstance("default").includes(Environment.staging, Optional.empty()));
+ assertFalse(spec.requireInstance("default").includes(Environment.prod, Optional.empty()));
assertFalse(spec.requireInstance("default").globalServiceId().isPresent());
}
@@ -104,21 +104,21 @@ public class DeploymentSpecTest {
assertEquals(3, spec.steps().size());
assertEquals(2, spec.requireInstance("default").steps().size());
- assertTrue(spec.steps().get(0).concerns(Environment.test));
+ assertTrue(spec.steps().get(0).deploysTo(Environment.test));
- assertTrue(spec.steps().get(1).concerns(Environment.staging));
+ assertTrue(spec.steps().get(1).deploysTo(Environment.staging));
- assertTrue(spec.requireInstance("default").steps().get(0).concerns(Environment.prod, Optional.of(RegionName.from("us-east1"))));
+ assertTrue(spec.requireInstance("default").steps().get(0).deploysTo(Environment.prod, Optional.of(RegionName.from("us-east1"))));
assertFalse(((DeploymentSpec.DeclaredZone)spec.requireInstance("default").steps().get(0)).active());
- assertTrue(spec.requireInstance("default").steps().get(1).concerns(Environment.prod, Optional.of(RegionName.from("us-west1"))));
+ assertTrue(spec.requireInstance("default").steps().get(1).deploysTo(Environment.prod, Optional.of(RegionName.from("us-west1"))));
assertTrue(((DeploymentSpec.DeclaredZone)spec.requireInstance("default").steps().get(1)).active());
- assertFalse(spec.requireInstance("default").deploysTo(Environment.test, Optional.empty()));
- assertFalse(spec.requireInstance("default").deploysTo(Environment.staging, Optional.empty()));
- assertTrue(spec.requireInstance("default").deploysTo(Environment.prod, Optional.of(RegionName.from("us-east1"))));
- assertTrue(spec.requireInstance("default").deploysTo(Environment.prod, Optional.of(RegionName.from("us-west1"))));
- assertFalse(spec.requireInstance("default").deploysTo(Environment.prod, Optional.of(RegionName.from("no-such-region"))));
+ assertFalse(spec.requireInstance("default").includes(Environment.test, Optional.empty()));
+ assertFalse(spec.requireInstance("default").includes(Environment.staging, Optional.empty()));
+ assertTrue(spec.requireInstance("default").includes(Environment.prod, Optional.of(RegionName.from("us-east1"))));
+ assertTrue(spec.requireInstance("default").includes(Environment.prod, Optional.of(RegionName.from("us-west1"))));
+ assertFalse(spec.requireInstance("default").includes(Environment.prod, Optional.of(RegionName.from("no-such-region"))));
assertFalse(spec.requireInstance("default").globalServiceId().isPresent());
assertEquals(DeploymentSpec.UpgradePolicy.defaultPolicy, spec.requireInstance("default").upgradePolicy());
@@ -145,84 +145,6 @@ public class DeploymentSpecTest {
}
@Test
- public void productionTests() {
- StringReader r = new StringReader(
- "<deployment version='1.0'>" +
- " <instance id='default'>" +
- " <test/>" +
- " <staging/>" +
- " <prod>" +
- " <region active='false'>us-east-1</region>" +
- " <region active='true'>us-west-1</region>" +
- " <delay hours='1' />" +
- " <test>us-west-1</test>" +
- " <test>us-east-1</test>" +
- " </prod>" +
- " </instance>" +
- "</deployment>"
- );
-
- DeploymentSpec spec = DeploymentSpec.fromXml(r);
- List<DeploymentSpec.Step> instanceSteps = spec.steps().get(0).steps();
- assertEquals(7, instanceSteps.size());
- assertEquals("test", instanceSteps.get(0).toString());
- assertEquals("staging", instanceSteps.get(1).toString());
- assertEquals("prod.us-east-1", instanceSteps.get(2).toString());
- assertEquals("prod.us-west-1", instanceSteps.get(3).toString());
- assertEquals("delay PT1H", instanceSteps.get(4).toString());
- assertEquals("tests for prod.us-west-1", instanceSteps.get(5).toString());
- assertEquals("tests for prod.us-east-1", instanceSteps.get(6).toString());
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void duplicateProductionTest() {
- StringReader r = new StringReader(
- "<deployment version='1.0'>" +
- " <instance id='default'>" +
- " <prod>" +
- " <region active='true'>us-east1</region>" +
- " <test>us-east1</test>" +
- " <test>us-east1</test>" +
- " </prod>" +
- " </instance>" +
- "</deployment>"
- );
- DeploymentSpec.fromXml(r);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void productionTestBeforeDeployment() {
- StringReader r = new StringReader(
- "<deployment version='1.0'>" +
- " <instance id='default'>" +
- " <prod>" +
- " <test>us-east1</test>" +
- " <region active='true'>us-east1</region>" +
- " </prod>" +
- " </instance>" +
- "</deployment>"
- );
- DeploymentSpec.fromXml(r);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void productionTestInParallelWithDeployment() {
- StringReader r = new StringReader(
- "<deployment version='1.0'>" +
- " <instance id='default'>" +
- " <prod>" +
- " <parallel>" +
- " <region active='true'>us-east1</region>" +
- " <test>us-east1</test>" +
- " </parallel>" +
- " </prod>" +
- " </instance>" +
- "</deployment>"
- );
- DeploymentSpec.fromXml(r);
- }
-
- @Test
public void maximalProductionSpecMultipleInstances() {
StringReader r = new StringReader(
"<deployment version='1.0'>" +
@@ -251,7 +173,7 @@ public class DeploymentSpecTest {
assertEquals(1, instance2.steps().size());
assertEquals(1, instance2.zones().size());
- assertTrue(instance2.steps().get(0).concerns(Environment.prod, Optional.of(RegionName.from("us-central1"))));
+ assertTrue(instance2.steps().get(0).deploysTo(Environment.prod, Optional.of(RegionName.from("us-central1"))));
}
@Test
@@ -280,25 +202,25 @@ public class DeploymentSpecTest {
assertEquals(5, instance.steps().size());
assertEquals(4, instance.zones().size());
- assertTrue(instance.steps().get(0).concerns(Environment.test));
+ assertTrue(instance.steps().get(0).deploysTo(Environment.test));
- assertTrue(instance.steps().get(1).concerns(Environment.staging));
+ assertTrue(instance.steps().get(1).deploysTo(Environment.staging));
- assertTrue(instance.steps().get(2).concerns(Environment.prod, Optional.of(RegionName.from("us-east1"))));
+ assertTrue(instance.steps().get(2).deploysTo(Environment.prod, Optional.of(RegionName.from("us-east1"))));
assertFalse(((DeploymentSpec.DeclaredZone)instance.steps().get(2)).active());
assertTrue(instance.steps().get(3) instanceof DeploymentSpec.Delay);
assertEquals(3 * 60 * 60 + 30 * 60, instance.steps().get(3).delay().getSeconds());
- assertTrue(instance.steps().get(4).concerns(Environment.prod, Optional.of(RegionName.from("us-west1"))));
+ assertTrue(instance.steps().get(4).deploysTo(Environment.prod, Optional.of(RegionName.from("us-west1"))));
assertTrue(((DeploymentSpec.DeclaredZone)instance.steps().get(4)).active());
- assertTrue(instance.deploysTo(Environment.test, Optional.empty()));
- assertFalse(instance.deploysTo(Environment.test, Optional.of(RegionName.from("region1"))));
- assertTrue(instance.deploysTo(Environment.staging, Optional.empty()));
- assertTrue(instance.deploysTo(Environment.prod, Optional.of(RegionName.from("us-east1"))));
- assertTrue(instance.deploysTo(Environment.prod, Optional.of(RegionName.from("us-west1"))));
- assertFalse(instance.deploysTo(Environment.prod, Optional.of(RegionName.from("no-such-region"))));
+ assertTrue(instance.includes(Environment.test, Optional.empty()));
+ assertFalse(instance.includes(Environment.test, Optional.of(RegionName.from("region1"))));
+ assertTrue(instance.includes(Environment.staging, Optional.empty()));
+ assertTrue(instance.includes(Environment.prod, Optional.of(RegionName.from("us-east1"))));
+ assertTrue(instance.includes(Environment.prod, Optional.of(RegionName.from("us-west1"))));
+ assertFalse(instance.includes(Environment.prod, Optional.of(RegionName.from("no-such-region"))));
assertFalse(instance.globalServiceId().isPresent());
}
@@ -450,10 +372,10 @@ public class DeploymentSpecTest {
"</deployment>"
);
DeploymentSpec spec = DeploymentSpec.fromXml(r);
- DeploymentSpec.ParallelSteps parallelSteps = ((DeploymentSpec.ParallelSteps) spec.requireInstance("default").steps().get(1));
- assertEquals(2, parallelSteps.zones().size());
- assertEquals(RegionName.from("us-central-1"), parallelSteps.zones().get(0).region().get());
- assertEquals(RegionName.from("us-east-3"), parallelSteps.zones().get(1).region().get());
+ DeploymentSpec.ParallelZones parallelZones = ((DeploymentSpec.ParallelZones) spec.requireInstance("default").steps().get(1));
+ assertEquals(2, parallelZones.zones().size());
+ assertEquals(RegionName.from("us-central-1"), parallelZones.zones().get(0).region().get());
+ assertEquals(RegionName.from("us-east-3"), parallelZones.zones().get(1).region().get());
}
@Test
@@ -497,77 +419,6 @@ public class DeploymentSpecTest {
}
@Test
- public void testNestedParallelAndSteps() {
- StringReader r = new StringReader(
- "<deployment athenz-domain='domain'>" +
- " <instance id='instance' athenz-service='in-service'>" +
- " <prod>" +
- " <parallel>" +
- " <region active='true'>us-west-1</region>" +
- " <steps>" +
- " <region active='true'>us-east-3</region>" +
- " <delay hours='2' />" +
- " <region active='true'>eu-west-1</region>" +
- " <delay hours='2' />" +
- " </steps>" +
- " <steps>" +
- " <delay hours='3' />" +
- " <region active='true'>aws-us-east-1a</region>" +
- " <parallel>" +
- " <region active='true' athenz-service='no-service'>ap-northeast-1</region>" +
- " <region active='true'>ap-southeast-2</region>" +
- " </parallel>" +
- " </steps>" +
- " <delay hours='3' minutes='30' />" +
- " </parallel>" +
- " <region active='true'>us-north-7</region>" +
- " </prod>" +
- " </instance>" +
- "</deployment>"
- );
-
- DeploymentSpec spec = DeploymentSpec.fromXml(r);
- List<DeploymentSpec.Step> steps = spec.steps();
- assertEquals(3, steps.size());
- assertEquals("test", steps.get(0).toString());
- assertEquals("staging", steps.get(1).toString());
- assertEquals("instance 'instance'", steps.get(2).toString());
- assertEquals(Duration.ofHours(4), steps.get(2).delay());
-
- List<DeploymentSpec.Step> instanceSteps = steps.get(2).steps();
- assertEquals(2, instanceSteps.size());
- assertEquals("4 parallel steps", instanceSteps.get(0).toString());
- assertEquals("prod.us-north-7", instanceSteps.get(1).toString());
-
- List<DeploymentSpec.Step> parallelSteps = instanceSteps.get(0).steps();
- assertEquals(4, parallelSteps.size());
- assertEquals("prod.us-west-1", parallelSteps.get(0).toString());
- assertEquals("4 steps", parallelSteps.get(1).toString());
- assertEquals("3 steps", parallelSteps.get(2).toString());
- assertEquals("delay PT3H30M", parallelSteps.get(3).toString());
-
- List<DeploymentSpec.Step> firstSerialSteps = parallelSteps.get(1).steps();
- assertEquals(4, firstSerialSteps.size());
- assertEquals("prod.us-east-3", firstSerialSteps.get(0).toString());
- assertEquals("delay PT2H", firstSerialSteps.get(1).toString());
- assertEquals("prod.eu-west-1", firstSerialSteps.get(2).toString());
- assertEquals("delay PT2H", firstSerialSteps.get(3).toString());
-
- List<DeploymentSpec.Step> secondSerialSteps = parallelSteps.get(2).steps();
- assertEquals(3, secondSerialSteps.size());
- assertEquals("delay PT3H", secondSerialSteps.get(0).toString());
- assertEquals("prod.aws-us-east-1a", secondSerialSteps.get(1).toString());
- assertEquals("2 parallel steps", secondSerialSteps.get(2).toString());
-
- List<DeploymentSpec.Step> innerParallelSteps = secondSerialSteps.get(2).steps();
- assertEquals(2, innerParallelSteps.size());
- assertEquals("prod.ap-northeast-1", innerParallelSteps.get(0).toString());
- assertEquals("no-service", spec.requireInstance("instance").athenzService(Environment.prod, RegionName.from("ap-northeast-1")).get().value());
- assertEquals("prod.ap-southeast-2", innerParallelSteps.get(1).toString());
- assertEquals("in-service", spec.requireInstance("instance").athenzService(Environment.prod, RegionName.from("ap-southeast-2")).get().value());
- }
-
- @Test
public void testParallelInstances() {
StringReader r = new StringReader(
"<deployment>" +
@@ -635,8 +486,8 @@ public class DeploymentSpecTest {
" <region active='true'>us-west-1</region>" +
" <parallel>" +
" <region active='true'>us-west-1</region>" +
- " <region active='true'>us-central-1</region>" +
- " <region active='true'>us-east-3</region>" +
+ " <region active='true'>us-central-1</region>" +
+ " <region active='true'>us-east-3</region>" +
" </parallel>" +
" </prod>" +
" </instance>" +
diff --git a/config-model-api/src/test/java/com/yahoo/config/application/api/DeploymentSpecWithoutInstanceTest.java b/config-model-api/src/test/java/com/yahoo/config/application/api/DeploymentSpecWithoutInstanceTest.java
index 13ec7bf1a8b..31a30e5bd83 100644
--- a/config-model-api/src/test/java/com/yahoo/config/application/api/DeploymentSpecWithoutInstanceTest.java
+++ b/config-model-api/src/test/java/com/yahoo/config/application/api/DeploymentSpecWithoutInstanceTest.java
@@ -3,11 +3,11 @@ package com.yahoo.config.application.api;
import com.google.common.collect.ImmutableSet;
import com.yahoo.config.provision.Environment;
+import com.yahoo.config.provision.InstanceName;
import com.yahoo.config.provision.RegionName;
import org.junit.Test;
import java.io.StringReader;
-import java.time.Duration;
import java.time.Instant;
import java.time.ZoneId;
import java.util.Collections;
@@ -40,11 +40,11 @@ public class DeploymentSpecWithoutInstanceTest {
assertEquals(specXml, spec.xmlForm());
assertEquals(1, spec.steps().size());
assertFalse(spec.majorVersion().isPresent());
- assertTrue(spec.steps().get(0).concerns(Environment.test));
- assertTrue(spec.requireInstance("default").deploysTo(Environment.test, Optional.empty()));
- assertFalse(spec.requireInstance("default").deploysTo(Environment.test, Optional.of(RegionName.from("region1"))));
- assertFalse(spec.requireInstance("default").deploysTo(Environment.staging, Optional.empty()));
- assertFalse(spec.requireInstance("default").deploysTo(Environment.prod, Optional.empty()));
+ assertTrue(spec.steps().get(0).deploysTo(Environment.test));
+ assertTrue(spec.requireInstance("default").includes(Environment.test, Optional.empty()));
+ assertFalse(spec.requireInstance("default").includes(Environment.test, Optional.of(RegionName.from("region1"))));
+ assertFalse(spec.requireInstance("default").includes(Environment.staging, Optional.empty()));
+ assertFalse(spec.requireInstance("default").includes(Environment.prod, Optional.empty()));
assertFalse(spec.requireInstance("default").globalServiceId().isPresent());
}
@@ -73,11 +73,11 @@ public class DeploymentSpecWithoutInstanceTest {
DeploymentSpec spec = DeploymentSpec.fromXml(r);
assertEquals(2, spec.steps().size());
assertEquals(1, spec.requireInstance("default").steps().size());
- assertTrue(spec.steps().get(0).concerns(Environment.test));
- assertTrue(spec.requireInstance("default").steps().get(0).concerns(Environment.staging));
- assertFalse(spec.requireInstance("default").deploysTo(Environment.test, Optional.empty()));
- assertTrue(spec.requireInstance("default").deploysTo(Environment.staging, Optional.empty()));
- assertFalse(spec.requireInstance("default").deploysTo(Environment.prod, Optional.empty()));
+ assertTrue(spec.steps().get(0).deploysTo(Environment.test));
+ assertTrue(spec.requireInstance("default").steps().get(0).deploysTo(Environment.staging));
+ assertFalse(spec.requireInstance("default").includes(Environment.test, Optional.empty()));
+ assertTrue(spec.requireInstance("default").includes(Environment.staging, Optional.empty()));
+ assertFalse(spec.requireInstance("default").includes(Environment.prod, Optional.empty()));
assertFalse(spec.requireInstance("default").globalServiceId().isPresent());
}
@@ -96,21 +96,21 @@ public class DeploymentSpecWithoutInstanceTest {
assertEquals(3, spec.steps().size());
assertEquals(2, spec.requireInstance("default").steps().size());
- assertTrue(spec.steps().get(0).concerns(Environment.test));
+ assertTrue(spec.steps().get(0).deploysTo(Environment.test));
- assertTrue(spec.steps().get(1).concerns(Environment.staging));
+ assertTrue(spec.steps().get(1).deploysTo(Environment.staging));
- assertTrue(spec.requireInstance("default").steps().get(0).concerns(Environment.prod, Optional.of(RegionName.from("us-east1"))));
+ assertTrue(spec.requireInstance("default").steps().get(0).deploysTo(Environment.prod, Optional.of(RegionName.from("us-east1"))));
assertFalse(((DeploymentSpec.DeclaredZone)spec.requireInstance("default").steps().get(0)).active());
- assertTrue(spec.requireInstance("default").steps().get(1).concerns(Environment.prod, Optional.of(RegionName.from("us-west1"))));
+ assertTrue(spec.requireInstance("default").steps().get(1).deploysTo(Environment.prod, Optional.of(RegionName.from("us-west1"))));
assertTrue(((DeploymentSpec.DeclaredZone)spec.requireInstance("default").steps().get(1)).active());
- assertFalse(spec.requireInstance("default").deploysTo(Environment.test, Optional.empty()));
- assertFalse(spec.requireInstance("default").deploysTo(Environment.staging, Optional.empty()));
- assertTrue(spec.requireInstance("default").deploysTo(Environment.prod, Optional.of(RegionName.from("us-east1"))));
- assertTrue(spec.requireInstance("default").deploysTo(Environment.prod, Optional.of(RegionName.from("us-west1"))));
- assertFalse(spec.requireInstance("default").deploysTo(Environment.prod, Optional.of(RegionName.from("no-such-region"))));
+ assertFalse(spec.requireInstance("default").includes(Environment.test, Optional.empty()));
+ assertFalse(spec.requireInstance("default").includes(Environment.staging, Optional.empty()));
+ assertTrue(spec.requireInstance("default").includes(Environment.prod, Optional.of(RegionName.from("us-east1"))));
+ assertTrue(spec.requireInstance("default").includes(Environment.prod, Optional.of(RegionName.from("us-west1"))));
+ assertFalse(spec.requireInstance("default").includes(Environment.prod, Optional.of(RegionName.from("no-such-region"))));
assertFalse(spec.requireInstance("default").globalServiceId().isPresent());
assertEquals(DeploymentSpec.UpgradePolicy.defaultPolicy, spec.requireInstance("default").upgradePolicy());
@@ -134,99 +134,29 @@ public class DeploymentSpecWithoutInstanceTest {
assertEquals(5, spec.requireInstance("default").steps().size());
assertEquals(4, spec.requireInstance("default").zones().size());
- assertTrue(spec.requireInstance("default").steps().get(0).concerns(Environment.test));
+ assertTrue(spec.requireInstance("default").steps().get(0).deploysTo(Environment.test));
- assertTrue(spec.requireInstance("default").steps().get(1).concerns(Environment.staging));
+ assertTrue(spec.requireInstance("default").steps().get(1).deploysTo(Environment.staging));
- assertTrue(spec.requireInstance("default").steps().get(2).concerns(Environment.prod, Optional.of(RegionName.from("us-east1"))));
+ assertTrue(spec.requireInstance("default").steps().get(2).deploysTo(Environment.prod, Optional.of(RegionName.from("us-east1"))));
assertFalse(((DeploymentSpec.DeclaredZone)spec.requireInstance("default").steps().get(2)).active());
assertTrue(spec.requireInstance("default").steps().get(3) instanceof DeploymentSpec.Delay);
assertEquals(3 * 60 * 60 + 30 * 60, spec.requireInstance("default").steps().get(3).delay().getSeconds());
- assertTrue(spec.requireInstance("default").steps().get(4).concerns(Environment.prod, Optional.of(RegionName.from("us-west1"))));
+ assertTrue(spec.requireInstance("default").steps().get(4).deploysTo(Environment.prod, Optional.of(RegionName.from("us-west1"))));
assertTrue(((DeploymentSpec.DeclaredZone)spec.requireInstance("default").steps().get(4)).active());
- assertTrue(spec.requireInstance("default").deploysTo(Environment.test, Optional.empty()));
- assertFalse(spec.requireInstance("default").deploysTo(Environment.test, Optional.of(RegionName.from("region1"))));
- assertTrue(spec.requireInstance("default").deploysTo(Environment.staging, Optional.empty()));
- assertTrue(spec.requireInstance("default").deploysTo(Environment.prod, Optional.of(RegionName.from("us-east1"))));
- assertTrue(spec.requireInstance("default").deploysTo(Environment.prod, Optional.of(RegionName.from("us-west1"))));
- assertFalse(spec.requireInstance("default").deploysTo(Environment.prod, Optional.of(RegionName.from("no-such-region"))));
+ assertTrue(spec.requireInstance("default").includes(Environment.test, Optional.empty()));
+ assertFalse(spec.requireInstance("default").includes(Environment.test, Optional.of(RegionName.from("region1"))));
+ assertTrue(spec.requireInstance("default").includes(Environment.staging, Optional.empty()));
+ assertTrue(spec.requireInstance("default").includes(Environment.prod, Optional.of(RegionName.from("us-east1"))));
+ assertTrue(spec.requireInstance("default").includes(Environment.prod, Optional.of(RegionName.from("us-west1"))));
+ assertFalse(spec.requireInstance("default").includes(Environment.prod, Optional.of(RegionName.from("no-such-region"))));
assertFalse(spec.requireInstance("default").globalServiceId().isPresent());
}
@Test
- public void productionTests() {
- StringReader r = new StringReader(
- "<deployment version='1.0'>" +
- " <test/>" +
- " <staging/>" +
- " <prod>" +
- " <region active='false'>us-east-1</region>" +
- " <region active='true'>us-west-1</region>" +
- " <delay hours='1' />" +
- " <test>us-west-1</test>" +
- " <test>us-east-1</test>" +
- " </prod>" +
- "</deployment>"
- );
-
- DeploymentSpec spec = DeploymentSpec.fromXml(r);
- List<DeploymentSpec.Step> instanceSteps = spec.steps().get(0).steps();
- assertEquals(7, instanceSteps.size());
- assertEquals("test", instanceSteps.get(0).toString());
- assertEquals("staging", instanceSteps.get(1).toString());
- assertEquals("prod.us-east-1", instanceSteps.get(2).toString());
- assertEquals("prod.us-west-1", instanceSteps.get(3).toString());
- assertEquals("delay PT1H", instanceSteps.get(4).toString());
- assertEquals("tests for prod.us-west-1", instanceSteps.get(5).toString());
- assertEquals("tests for prod.us-east-1", instanceSteps.get(6).toString());
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void duplicateProductionTests() {
- StringReader r = new StringReader(
- "<deployment version='1.0'>" +
- " <prod>" +
- " <region active='true'>us-east1</region>" +
- " <test>us-east1</test>" +
- " <test>us-east1</test>" +
- " </prod>" +
- "</deployment>"
- );
- DeploymentSpec.fromXml(r);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void productionTestBeforeDeployment() {
- StringReader r = new StringReader(
- "<deployment version='1.0'>" +
- " <prod>" +
- " <test>us-east1</test>" +
- " <region active='true'>us-east1</region>" +
- " </prod>" +
- "</deployment>"
- );
- DeploymentSpec.fromXml(r);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void productionTestInParallelWithDeployment() {
- StringReader r = new StringReader(
- "<deployment version='1.0'>" +
- " <prod>" +
- " <parallel>" +
- " <region active='true'>us-east1</region>" +
- " <test>us-east1</test>" +
- " </parallel>" +
- " </prod>" +
- "</deployment>"
- );
- DeploymentSpec.fromXml(r);
- }
-
- @Test
public void productionSpecWithGlobalServiceId() {
StringReader r = new StringReader(
"<deployment version='1.0'>" +
@@ -342,79 +272,10 @@ public class DeploymentSpecWithoutInstanceTest {
"</deployment>"
);
DeploymentSpec spec = DeploymentSpec.fromXml(r);
- DeploymentSpec.ParallelSteps parallelSteps = ((DeploymentSpec.ParallelSteps) spec.requireInstance("default").steps().get(1));
- assertEquals(2, parallelSteps.zones().size());
- assertEquals(RegionName.from("us-central-1"), parallelSteps.zones().get(0).region().get());
- assertEquals(RegionName.from("us-east-3"), parallelSteps.zones().get(1).region().get());
- }
-
- @Test
- public void testNestedParallelAndSteps() {
- StringReader r = new StringReader(
- "<deployment athenz-domain='domain' athenz-service='service'>" +
- " <prod>" +
- " <parallel>" +
- " <region active='true'>us-west-1</region>" +
- " <steps>" +
- " <region active='true'>us-east-3</region>" +
- " <delay hours='2' />" +
- " <region active='true'>eu-west-1</region>" +
- " <delay hours='2' />" +
- " </steps>" +
- " <steps>" +
- " <delay hours='3' />" +
- " <region active='true'>aws-us-east-1a</region>" +
- " <parallel>" +
- " <region active='true' athenz-service='no-service'>ap-northeast-1</region>" +
- " <region active='true'>ap-southeast-2</region>" +
- " </parallel>" +
- " </steps>" +
- " <delay hours='3' minutes='30' />" +
- " </parallel>" +
- " <region active='true'>us-north-7</region>" +
- " </prod>" +
- "</deployment>"
- );
-
- DeploymentSpec spec = DeploymentSpec.fromXml(r);
- List<DeploymentSpec.Step> steps = spec.steps();
- assertEquals(3, steps.size());
- assertEquals("test", steps.get(0).toString());
- assertEquals("staging", steps.get(1).toString());
- assertEquals("instance 'default'", steps.get(2).toString());
- assertEquals(Duration.ofHours(4), steps.get(2).delay());
-
- List<DeploymentSpec.Step> instanceSteps = steps.get(2).steps();
- assertEquals(2, instanceSteps.size());
- assertEquals("4 parallel steps", instanceSteps.get(0).toString());
- assertEquals("prod.us-north-7", instanceSteps.get(1).toString());
-
- List<DeploymentSpec.Step> parallelSteps = instanceSteps.get(0).steps();
- assertEquals(4, parallelSteps.size());
- assertEquals("prod.us-west-1", parallelSteps.get(0).toString());
- assertEquals("4 steps", parallelSteps.get(1).toString());
- assertEquals("3 steps", parallelSteps.get(2).toString());
- assertEquals("delay PT3H30M", parallelSteps.get(3).toString());
-
- List<DeploymentSpec.Step> firstSerialSteps = parallelSteps.get(1).steps();
- assertEquals(4, firstSerialSteps.size());
- assertEquals("prod.us-east-3", firstSerialSteps.get(0).toString());
- assertEquals("delay PT2H", firstSerialSteps.get(1).toString());
- assertEquals("prod.eu-west-1", firstSerialSteps.get(2).toString());
- assertEquals("delay PT2H", firstSerialSteps.get(3).toString());
-
- List<DeploymentSpec.Step> secondSerialSteps = parallelSteps.get(2).steps();
- assertEquals(3, secondSerialSteps.size());
- assertEquals("delay PT3H", secondSerialSteps.get(0).toString());
- assertEquals("prod.aws-us-east-1a", secondSerialSteps.get(1).toString());
- assertEquals("2 parallel steps", secondSerialSteps.get(2).toString());
-
- List<DeploymentSpec.Step> innerParallelSteps = secondSerialSteps.get(2).steps();
- assertEquals(2, innerParallelSteps.size());
- assertEquals("prod.ap-northeast-1", innerParallelSteps.get(0).toString());
- assertEquals("no-service", spec.requireInstance("default").athenzService(Environment.prod, RegionName.from("ap-northeast-1")).get().value());
- assertEquals("prod.ap-southeast-2", innerParallelSteps.get(1).toString());
- assertEquals("service", spec.requireInstance("default").athenzService(Environment.prod, RegionName.from("ap-southeast-2")).get().value());
+ DeploymentSpec.ParallelZones parallelZones = ((DeploymentSpec.ParallelZones) spec.requireInstance("default").steps().get(1));
+ assertEquals(2, parallelZones.zones().size());
+ assertEquals(RegionName.from("us-central-1"), parallelZones.zones().get(0).region().get());
+ assertEquals(RegionName.from("us-east-3"), parallelZones.zones().get(1).region().get());
}
@Test
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java
index 188a9b4765c..e5e22c3a260 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java
@@ -236,7 +236,7 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> {
Optional<DeploymentInstanceSpec> instance = spec.instance(app.getApplicationId().instance());
if (instance.isEmpty()) return false;
return instance.get().zones().stream()
- .anyMatch(declaredZone -> declaredZone.concerns(zone.environment(), Optional.of(zone.region())) &&
+ .anyMatch(declaredZone -> declaredZone.deploysTo(zone.environment(), Optional.of(zone.region())) &&
declaredZone.active());
}
diff --git a/config-model/src/main/resources/schema/deployment.rnc b/config-model/src/main/resources/schema/deployment.rnc
index 6a8bc8f77b9..1e1d9ad3aa9 100644
--- a/config-model/src/main/resources/schema/deployment.rnc
+++ b/config-model/src/main/resources/schema/deployment.rnc
@@ -25,11 +25,6 @@ StepExceptInstance =
Staging? &
Prod*
-PrimitiveStep =
- Delay* &
- Region* &
- ProdTest*
-
Instance = element instance {
attribute id { xsd:string } &
attribute athenz-domain { xsd:string }? &
@@ -37,14 +32,8 @@ Instance = element instance {
StepExceptInstance
}
-ParallelSteps = element parallel {
- SerialSteps* &
- PrimitiveStep*
-}
-
-SerialSteps = element steps {
- ParallelSteps* &
- PrimitiveStep*
+ParallelRegions = element parallel {
+ Region*
}
ParallelInstances = element parallel {
@@ -92,17 +81,11 @@ Prod = element prod {
attribute tester-flavor { xsd:string }? &
Region* &
Delay* &
- ProdTest* &
- ParallelSteps*
-}
-
-ProdTest = element test {
- text
+ ParallelRegions*
}
Region = element region {
attribute active { xsd:boolean } &
- attribute athenz-service { xsd:string }? &
text
}
diff --git a/config-model/src/test/cfg/application/app_complicated_deployment_spec/deployment.xml b/config-model/src/test/cfg/application/app_complicated_deployment_spec/deployment.xml
deleted file mode 100644
index 36c1d449021..00000000000
--- a/config-model/src/test/cfg/application/app_complicated_deployment_spec/deployment.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<deployment version='1.0' athenz-domain='domain'>
- <staging />
- <parallel>
- <instance id='instance' athenz-service='in-service'>
- <prod>
- <parallel>
- <region active='true'>us-west-1</region>
- <steps>
- <region active='true'>us-east-3</region>
- <delay hours='2' />
- <region active='true'>eu-west-1</region>
- <delay hours='2' />
- </steps>
- <steps>
- <delay hours='3' />
- <region active='true'>aws-us-east-1a</region>
- <parallel>
- <region active='true' athenz-service='no-service'>ap-northeast-1</region>
- <region active='true'>ap-southeast-2</region>
- </parallel>
- </steps>
- <delay hours='3' minutes='30' />
- </parallel>
- <region active='true'>us-north-7</region>
- </prod>
- </instance>
- <instance id='other'>
- <upgrade policy='conservative' />
- <block-change days='sat' hours='10' time-zone='CET' />
- <test />
- <prod>
- <region active='true'>eu-central-2</region>
- </prod>
- <notifications when='failing'>
- <email role='author' />
- <email address='john@dev' when='failing-commit' />
- <email address='jane@dev' />
- </notifications>
- <endpoints>
- <endpoint id='foo' container-id='bar'>
- <region>us-east</region>
- </endpoint>
- <endpoint id='nalle' container-id='frosk' />
- <endpoint container-id='quux' />
- </endpoints>
- </instance>
- </parallel>
-</deployment>
diff --git a/config-model/src/test/cfg/application/app_complicated_deployment_spec/hosts.xml b/config-model/src/test/cfg/application/app_complicated_deployment_spec/hosts.xml
deleted file mode 100644
index a7fc725d377..00000000000
--- a/config-model/src/test/cfg/application/app_complicated_deployment_spec/hosts.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!-- Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
-<hosts>
- <host name="bogusname1">
- <alias>node1</alias>
- </host>
- <host name="bogusname2">
- <alias>node2</alias>
- </host>
- <host name="bogusname3">
- <alias>node3</alias>
- </host>
- <host name="bogusname4">
- <alias>node4</alias>
- </host>
- <host name="bogusname5">
- <alias>node5</alias>
- </host>
-
-</hosts>
-
diff --git a/config-model/src/test/cfg/application/app_complicated_deployment_spec/searchdefinitions/music.sd b/config-model/src/test/cfg/application/app_complicated_deployment_spec/searchdefinitions/music.sd
deleted file mode 100644
index 693afbd308d..00000000000
--- a/config-model/src/test/cfg/application/app_complicated_deployment_spec/searchdefinitions/music.sd
+++ /dev/null
@@ -1,37 +0,0 @@
-# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-# A basic search definition - called music, should be saved to music.sd
-search music {
-
- # It contains one document type only - called music as well
- document music {
-
- field title type string {
- indexing: summary | index # How this field should be indexed
- # index-to: title, default # Create two indexes
- rank-type: about # Type of ranking settings to apply
- }
-
- field artist type string {
- indexing: summary | attribute | index
- # index-to: artist, default
- rank-type:about
- }
-
- field year type int {
- indexing: summary | attribute
- }
-
- # Increase rank score of popular documents regardless of query
- field popularity type int {
- indexing: summary | attribute
- }
-
- field url type uri {
- indexing: summary | index
- }
-
- field cover type raw {}
-
- }
-
-}
diff --git a/config-model/src/test/cfg/application/app_complicated_deployment_spec/services.xml b/config-model/src/test/cfg/application/app_complicated_deployment_spec/services.xml
deleted file mode 100644
index 9ae7f122e81..00000000000
--- a/config-model/src/test/cfg/application/app_complicated_deployment_spec/services.xml
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-<!-- Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
-<services version="1.0">
-
- <service version="1.0" name="myservice" command="mycmd1.sh">
- <config name="a.myconfig">
- <mysetting>bar</mysetting>
- </config>
- <node hostalias="node1">
- <config name="a.myconfig">
- <mysetting>baz</mysetting>
- </config>
- </node>
- <node hostalias="node2"/>
- <node hostalias="node3"/>
- <node hostalias="node3"/>
- </service>
-
- <service version="1.0" name="myotherservice" command="/home/vespa/bin/mycmd2.sh --ytest $FOO_BAR">
- <config name="a.myconfig">
- <mysetting>bar2</mysetting>
- </config>
- <node hostalias="node3">
- <config name="a.myconfig">
- <mysetting>baz2</mysetting>
- </config>
- </node>
- <node hostalias="node4"/>
- <node hostalias="node5"/>
- </service>
-
- <admin version="2.0">
- <adminserver hostalias="node1"/>
- <slobroks>
- <slobrok hostalias="node1"/>
- <slobrok hostalias="node2"/>
- </slobroks>
- </admin>
-
- <container version="1.0">
- <nodes>
- <node hostalias="node1" />
- </nodes>
-
- <search/>
- <document-api/>
- </container>
-
- <content id="music" version="1.0">
- <redundancy>1</redundancy>
- <documents>
- <document type="music" mode="index" />
- </documents>
- <nodes>
- <node hostalias="node1" distribution-key="0" />
- </nodes>
- </content>
-
-</services>
diff --git a/config-model/src/test/cfg/application/invalid_parallel_deployment_xml/deployment.xml b/config-model/src/test/cfg/application/invalid_parallel_deployment_xml/deployment.xml
index 8e13f0abb53..2f6e9b7a1a6 100644
--- a/config-model/src/test/cfg/application/invalid_parallel_deployment_xml/deployment.xml
+++ b/config-model/src/test/cfg/application/invalid_parallel_deployment_xml/deployment.xml
@@ -4,7 +4,9 @@
<staging/>
<prod global-service-id="query">
<parallel>
- <instance id="hello" />
+ <region active="true">us-east-3</region>
+ <delay hours="1"/>
+ <region active="true">us-west-1</region>
</parallel>
</prod>
</deployment>
diff --git a/config-model/src/test/java/com/yahoo/config/model/ApplicationDeployTest.java b/config-model/src/test/java/com/yahoo/config/model/ApplicationDeployTest.java
index cb1577417b4..8a8b23bb0c8 100644
--- a/config-model/src/test/java/com/yahoo/config/model/ApplicationDeployTest.java
+++ b/config-model/src/test/java/com/yahoo/config/model/ApplicationDeployTest.java
@@ -212,14 +212,7 @@ public class ApplicationDeployTest {
}
@Test
- public void testComplicatedDeploymentSpec() throws IOException {
- File tmpDir = tmpFolder.getRoot();
- IOUtils.copyDirectory(new File(TESTDIR, "app_complicated_deployment_spec"), tmpDir);
- ApplicationPackageTester.create(tmpDir.getAbsolutePath());
- }
-
- @Test
- public void testAppWithEmptyProdRegion() throws IOException {
+ public void testThatAppWithIllegalEmptyProdRegion() throws IOException {
File tmpDir = tmpFolder.getRoot();
IOUtils.copyDirectory(new File(TESTDIR, "empty_prod_region_in_deployment_xml"), tmpDir);
ApplicationPackageTester.create(tmpDir.getAbsolutePath());
@@ -233,7 +226,7 @@ public class ApplicationDeployTest {
ApplicationPackageTester.create(tmpDir.getAbsolutePath());
fail("Expected exception");
} catch (IllegalArgumentException e) {
- assertEquals("XML error in deployment.xml: element \"instance\" not allowed here; expected the element end-tag or element \"delay\", \"region\", \"steps\" or \"test\" [7:30], input:\n", e.getMessage());
+ assertEquals("XML error in deployment.xml: element \"delay\" not allowed here; expected the element end-tag or element \"region\" [8:25], input:\n", e.getMessage());
}
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java
index d3505b31d8f..3f985e95a4f 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java
@@ -19,6 +19,9 @@ import com.yahoo.vespa.athenz.api.AthenzPrincipal;
import com.yahoo.vespa.athenz.api.AthenzService;
import com.yahoo.vespa.athenz.api.AthenzUser;
import com.yahoo.vespa.curator.Lock;
+import com.yahoo.vespa.flags.BooleanFlag;
+import com.yahoo.vespa.flags.FetchVector;
+import com.yahoo.vespa.flags.Flags;
import com.yahoo.vespa.hosted.controller.api.ActivateResult;
import com.yahoo.vespa.hosted.controller.api.application.v4.model.DeployOptions;
import com.yahoo.vespa.hosted.controller.api.application.v4.model.EndpointStatus;
@@ -453,7 +456,7 @@ public class ApplicationController {
}
for (InstanceName instance : declaredInstances)
- if (applicationPackage.deploymentSpec().requireInstance(instance).concerns(Environment.prod))
+ if (applicationPackage.deploymentSpec().requireInstance(instance).deploysTo(Environment.prod))
application = withRotation(applicationPackage.deploymentSpec(), application, instance);
store(application);
@@ -613,8 +616,8 @@ public class ApplicationController {
List<ZoneId> deploymentsToRemove = application.get().require(instance).productionDeployments().values().stream()
.map(Deployment::zone)
.filter(zone -> deploymentSpec.instance(instance).isEmpty()
- || ! deploymentSpec.requireInstance(instance).deploysTo(zone.environment(),
- Optional.of(zone.region())))
+ || ! deploymentSpec.requireInstance(instance).includes(zone.environment(),
+ Optional.of(zone.region())))
.collect(Collectors.toList());
if (deploymentsToRemove.isEmpty())
@@ -644,8 +647,7 @@ public class ApplicationController {
for (JobType job : JobList.from(instance).production().mapToList(JobStatus::type)) {
ZoneId zone = job.zone(controller.system());
if (deploymentSpec.instance(instance.name())
- // TODO jonmv: Properly convert to job here.
- .map(spec -> spec.deploysTo(zone.environment(), Optional.of(zone.region())))
+ .map(spec -> spec.includes(zone.environment(), Optional.of(zone.region())))
.orElse(false))
continue;
instance = instance.withoutDeploymentJob(job);
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentSteps.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentSteps.java
index ddfcf17b0be..1b722c80ec1 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentSteps.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentSteps.java
@@ -4,6 +4,7 @@ package com.yahoo.vespa.hosted.controller.deployment;
import com.yahoo.config.application.api.DeploymentInstanceSpec;
import com.yahoo.config.application.api.DeploymentSpec;
import com.yahoo.config.provision.Environment;
+import com.yahoo.config.provision.InstanceName;
import com.yahoo.config.provision.SystemName;
import com.yahoo.config.provision.zone.ZoneId;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.JobType;
@@ -90,7 +91,7 @@ public class DeploymentSteps {
}
private boolean isTest(DeploymentSpec.Step step) {
- return step.concerns(Environment.test) || step.concerns(Environment.staging);
+ return step.deploysTo(Environment.test) || step.deploysTo(Environment.staging);
}
/** Resolve job from deployment zone */
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunner.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunner.java
index a5a7f6940a3..972e96e94f2 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunner.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunner.java
@@ -700,7 +700,7 @@ public class InternalStepRunner implements StepRunner {
private static Optional<String> testerFlavorFor(RunId id, DeploymentSpec spec) {
for (DeploymentSpec.Step step : spec.steps())
- if (step.concerns(id.type().environment()))
+ if (step.deploysTo(id.type().environment()))
return step.zones().get(0).testerFlavor();
throw new IllegalStateException("No step deploys to the zone this run is for!");
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/rotation/RotationRepository.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/rotation/RotationRepository.java
index 8ca8d31b32b..6ea7417dffd 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/rotation/RotationRepository.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/rotation/RotationRepository.java
@@ -83,7 +83,7 @@ public class RotationRepository {
instance.name() + "'");
}
long productionZones = deploymentSpec.requireInstance(instance.name()).zones().stream()
- .filter(zone -> zone.concerns(Environment.prod))
+ .filter(zone -> zone.deploysTo(Environment.prod))
.count();
if (productionZones < 2) {
throw new IllegalArgumentException("global-service-id is set but less than 2 prod zones are defined " +