diff options
Diffstat (limited to 'config-model-api/src/main')
-rw-r--r-- | config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentInstanceSpec.java (renamed from config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentInstancesSpec.java) | 34 | ||||
-rw-r--r-- | config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentSpec.java | 89 | ||||
-rw-r--r-- | config-model-api/src/main/java/com/yahoo/config/application/api/xml/DeploymentSpecXmlReader.java | 50 |
3 files changed, 97 insertions, 76 deletions
diff --git a/config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentInstancesSpec.java b/config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentInstanceSpec.java index 344f3438804..1fc3a8af2eb 100644 --- a/config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentInstancesSpec.java +++ b/config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentInstanceSpec.java @@ -18,14 +18,14 @@ import java.util.Set; import java.util.stream.Collectors; /** - * The deployment spec for some specified application instances + * The deployment spec for an application instance * * @author bratseth */ -public class DeploymentInstancesSpec extends DeploymentSpec.Step { +public class DeploymentInstanceSpec extends DeploymentSpec.Step { - /** The instances deployed in this step */ - private final List<InstanceName> ids; + /** The name of the instance this step deploys */ + private final InstanceName name; private final List<DeploymentSpec.Step> steps; private final DeploymentSpec.UpgradePolicy upgradePolicy; @@ -36,16 +36,16 @@ public class DeploymentInstancesSpec extends DeploymentSpec.Step { private final Notifications notifications; private final List<Endpoint> endpoints; - public DeploymentInstancesSpec(List<InstanceName> ids, - List<DeploymentSpec.Step> steps, - DeploymentSpec.UpgradePolicy upgradePolicy, - List<DeploymentSpec.ChangeBlocker> changeBlockers, - Optional<String> globalServiceId, - Optional<AthenzDomain> athenzDomain, - Optional<AthenzService> athenzService, - Notifications notifications, - List<Endpoint> endpoints) { - this.ids = List.copyOf(ids); + public DeploymentInstanceSpec(InstanceName name, + List<DeploymentSpec.Step> steps, + DeploymentSpec.UpgradePolicy upgradePolicy, + List<DeploymentSpec.ChangeBlocker> changeBlockers, + Optional<String> globalServiceId, + Optional<AthenzDomain> athenzDomain, + Optional<AthenzService> athenzService, + Notifications notifications, + List<Endpoint> endpoints) { + this.name = name; this.steps = List.copyOf(completeSteps(new ArrayList<>(steps))); this.upgradePolicy = upgradePolicy; this.changeBlockers = changeBlockers; @@ -59,7 +59,7 @@ public class DeploymentInstancesSpec extends DeploymentSpec.Step { validateAthenz(); } - public List<InstanceName> names() { return ids; } + public InstanceName name() { return name; } /** Adds missing required steps and reorders steps to a permissible order */ private static List<DeploymentSpec.Step> completeSteps(List<DeploymentSpec.Step> steps) { @@ -255,7 +255,7 @@ public class DeploymentInstancesSpec extends DeploymentSpec.Step { public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - DeploymentInstancesSpec other = (DeploymentInstancesSpec) o; + DeploymentInstanceSpec other = (DeploymentInstanceSpec) o; return globalServiceId.equals(other.globalServiceId) && upgradePolicy == other.upgradePolicy && changeBlockers.equals(other.changeBlockers) && @@ -273,7 +273,7 @@ public class DeploymentInstancesSpec extends DeploymentSpec.Step { @Override public String toString() { - return "instance" + ( ids.size() < 1 ? " " : "s " ) + ids; + return "instance '" + name + "'"; } } 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 e54371e714d..db383a1bea5 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,13 +13,10 @@ import java.io.FileReader; import java.io.Reader; import java.time.Duration; import java.time.Instant; -import java.util.ArrayList; import java.util.Collections; -import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Optional; -import java.util.Set; import java.util.stream.Collectors; /** @@ -67,15 +64,15 @@ public class DeploymentSpec { Optional<AthenzDomain> athenzDomain, Optional<AthenzService> athenzService, Notifications notifications, List<Endpoint> endpoints) { - this(List.of(new DeploymentInstancesSpec(List.of(InstanceName.from("default")), - steps, - upgradePolicy, - changeBlockers, - globalServiceId, - athenzDomain, - athenzService, - notifications, - endpoints)), + this(List.of(new DeploymentInstanceSpec(InstanceName.from("default"), + steps, + upgradePolicy, + changeBlockers, + globalServiceId, + athenzDomain, + athenzService, + notifications, + endpoints)), majorVersion, xmlForm); } @@ -89,18 +86,11 @@ public class DeploymentSpec { } // TODO: Remove after October 2019 - private DeploymentInstancesSpec defaultInstance() { - if (hasDefaultInstanceStepOnly()) return (DeploymentInstancesSpec)steps.get(0); + private DeploymentInstanceSpec defaultInstance() { + if (instances().size() == 1) return (DeploymentInstanceSpec)steps.get(0); throw new IllegalArgumentException("This deployment spec does not support the legacy API " + - "as it does not consist only of a default instance. Content: " + - steps.stream().map(Step::toString).collect(Collectors.joining(","))); - } - - // TODO: Remove after October 2019 - private boolean hasDefaultInstanceStepOnly() { - return steps.size() == 1 - && (steps.get(0) instanceof DeploymentInstancesSpec) - && ((DeploymentInstancesSpec)steps.get(0)).names().equals(List.of(InstanceName.from("default"))); + "as it has multiple instances: " + + instances().stream().map(Step::toString).collect(Collectors.joining(","))); } // TODO: Remove after October 2019 @@ -112,61 +102,86 @@ public class DeploymentSpec { /** Returns the major version this application is pinned to, or empty (default) to allow all major versions */ public Optional<Integer> majorVersion() { return majorVersion; } - // TODO: Remove after October 2019 + // TODO: Remove after November 2019 public boolean canUpgradeAt(Instant instant) { return defaultInstance().canUpgradeAt(instant); } - // TODO: Remove after October 2019 + // TODO: Remove after November 2019 public boolean canChangeRevisionAt(Instant instant) { return defaultInstance().canChangeRevisionAt(instant); } - // TODO: Remove after October 2019 + // TODO: Remove after November 2019 public List<ChangeBlocker> changeBlocker() { return defaultInstance().changeBlocker(); } /** Returns the deployment steps of this in the order they will be performed */ public List<Step> steps() { - if (hasDefaultInstanceStepOnly()) return defaultInstance().steps(); // TODO: Remove line after October 2019 + if (steps.size() == 1) return defaultInstance().steps(); // TODO: Remove line after November 2019 return steps; } - // TODO: Remove after October 2019 + // TODO: Remove after November 2019 public List<DeclaredZone> zones() { return defaultInstance().steps().stream() .flatMap(step -> step.zones().stream()) .collect(Collectors.toList()); } - // TODO: Remove after October 2019 + // TODO: Remove after November 2019 public Optional<AthenzDomain> athenzDomain() { return defaultInstance().athenzDomain(); } - // TODO: Remove after October 2019 + // TODO: Remove after November 2019 public Optional<AthenzService> athenzService(Environment environment, RegionName region) { return defaultInstance().athenzService(environment, region); } - // TODO: Remove after October 2019 + // TODO: Remove after November 2019 public Notifications notifications() { return defaultInstance().notifications(); } - // TODO: Remove after October 2019 + // TODO: Remove after November 2019 public List<Endpoint> endpoints() { return defaultInstance().endpoints(); } /** Returns the XML form of this spec, or null if it was not created by fromXml, nor is empty */ public String xmlForm() { return xmlForm; } - // TODO: Remove after October 2019 + // TODO: Remove after November 2019 public boolean includes(Environment environment, Optional<RegionName> region) { return defaultInstance().deploysTo(environment, region); } /** Returns the instance step containing the given instance name, or null if not present */ - public DeploymentInstancesSpec instance(String name) { + public DeploymentInstanceSpec instance(String name) { + return instance(InstanceName.from(name)); + } + + /** Returns the instance step containing the given instance name, or null if not present */ + public DeploymentInstanceSpec instance(InstanceName name) { for (Step step : steps) { - if ( ! (step instanceof DeploymentInstancesSpec)) continue; - DeploymentInstancesSpec instanceStep = (DeploymentInstancesSpec)step; - if (instanceStep.names().contains(InstanceName.from(name))) + if ( ! (step instanceof DeploymentInstanceSpec)) continue; + DeploymentInstanceSpec instanceStep = (DeploymentInstanceSpec)step; + if (instanceStep.name().equals(name)) return instanceStep; } return null; } + /** Returns the instance step containing the given instance name, or throws an IllegalArgumentException if not present */ + public DeploymentInstanceSpec requireInstance(String name) { + return requireInstance(InstanceName.from(name)); + } + + public DeploymentInstanceSpec requireInstance(InstanceName name) { + DeploymentInstanceSpec instance = instance(name); + if (instance == null) + throw new IllegalArgumentException("No instance '" + name + "' in deployment.xml'. Instances: " + + instances().stream().map(spec -> spec.name().toString()).collect(Collectors.joining(","))); + return instance; + } + + /** Returns the steps of this which are instances */ + public List<DeploymentInstanceSpec> instances() { + return steps.stream() + .filter(step -> step instanceof DeploymentInstanceSpec).map(DeploymentInstanceSpec.class::cast) + .collect(Collectors.toList()); + } + /** * Creates a deployment spec from XML. * 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 acecb320b83..4d6495482ea 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 @@ -1,7 +1,7 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.config.application.api.xml; -import com.yahoo.config.application.api.DeploymentInstancesSpec; +import com.yahoo.config.application.api.DeploymentInstanceSpec; import com.yahoo.config.application.api.DeploymentSpec; import com.yahoo.config.application.api.DeploymentSpec.DeclaredZone; import com.yahoo.config.application.api.DeploymentSpec.Delay; @@ -53,6 +53,7 @@ public class DeploymentSpecXmlReader { private static final String endpointTag = "endpoint"; private static final String athenzServiceAttribute = "athenz-service"; + private static final String athenzDomainAttribute = "athenz-domain"; private static final String testerFlavorAttribute = "tester-flavor"; private final boolean validate; @@ -86,7 +87,7 @@ public class DeploymentSpecXmlReader { List<Step> steps = new ArrayList<>(); if ( ! hasChildTag(instanceTag, root)) { // deployment spec skipping explicit instance -> "default" instance - steps.add(readInstanceContent("default", root)); + steps.addAll(readInstanceContent("default", root, root)); } else { if (hasChildTag(prodTag, root)) @@ -96,7 +97,7 @@ public class DeploymentSpecXmlReader { for (Element topLevelTag : XML.getChildren(root)) { if (topLevelTag.getTagName().equals(instanceTag)) - steps.add(readInstanceContent(topLevelTag.getAttribute("id"), topLevelTag)); + steps.addAll(readInstanceContent(topLevelTag.getAttribute("id"), topLevelTag, root)); else steps.addAll(readNonInstanceSteps(topLevelTag, new MutableOptional<>(), topLevelTag)); // (No global service id here) } @@ -110,33 +111,38 @@ public class DeploymentSpecXmlReader { /** * Reads the content of an (implicit or explicit) instance tag producing an instances step * - * @param instanceIdString a comma-separated list of the ids of the instance id(s) this is for - * @param instanceElement the element having the content of this instance + * @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 instances is implicitly defined which means instanceTag is the root) + * @return the instances specified, one for each instance name element */ - private DeploymentInstancesSpec readInstanceContent(String instanceIdString, Element instanceElement) { + private List<DeploymentInstanceSpec> readInstanceContent(String instanceNameString, Element instanceTag, Element parentTag) { if (validate) - validateTagOrder(instanceElement); + validateTagOrder(instanceTag); - List<InstanceName> instanceNames = Arrays.stream(instanceIdString.split("'")) - .map(InstanceName::from) - .collect(Collectors.toList()); MutableOptional<String> globalServiceId = new MutableOptional<>(); // Deprecated: Set of prod, but belongs to instance - Optional<AthenzDomain> athenzDomain = stringAttribute("athenz-domain", instanceElement).map(AthenzDomain::from); - Optional<AthenzService> athenzService = stringAttribute("athenz-service", instanceElement).map(AthenzService::from); + Optional<AthenzDomain> athenzDomain = stringAttribute(athenzDomainAttribute, instanceTag) + .or(() -> stringAttribute(athenzDomainAttribute, parentTag)) + .map(AthenzDomain::from); + Optional<AthenzService> athenzService = stringAttribute(athenzServiceAttribute, instanceTag) + .or(() -> stringAttribute(athenzServiceAttribute, parentTag)) + .map(AthenzService::from); List<Step> steps = new ArrayList<>(); - for (Element instanceChild : XML.getChildren(instanceElement)) + for (Element instanceChild : XML.getChildren(instanceTag)) steps.addAll(readNonInstanceSteps(instanceChild, globalServiceId, instanceChild)); - return new DeploymentInstancesSpec(instanceNames, - steps, - readUpgradePolicy(instanceElement), - readChangeBlockers(instanceElement), - globalServiceId.asOptional(), - athenzDomain, - athenzService, - readNotifications(instanceElement), - readEndpoints(instanceElement)); + return Arrays.stream(instanceNameString.split("'")) + .map(name -> new DeploymentInstanceSpec(InstanceName.from(name), + steps, + readUpgradePolicy(instanceTag), + readChangeBlockers(instanceTag), + globalServiceId.asOptional(), + athenzDomain, + athenzService, + readNotifications(instanceTag), + readEndpoints(instanceTag))) + .collect(Collectors.toList()); } // Consume the give tag as 0-N steps. 0 if it is not a step, >1 if it contains multiple nested steps that should be flattened |