diff options
author | Øyvind Grønnesby <oyving@verizonmedia.com> | 2019-05-29 15:47:09 +0200 |
---|---|---|
committer | Øyvind Grønnesby <oyving@verizonmedia.com> | 2019-05-29 15:47:09 +0200 |
commit | 0875cb2e7f31396a42a2543b3c54ba07cde0ef6a (patch) | |
tree | 0d568c4e44f888cf1264a4cc481bbf3af1729e3c /config-model-api/src/main/java | |
parent | c0a5ffd1ca99b92eeabfcd96c561ec1317ee797d (diff) |
Add endpoints to deployment specification
Endpoints are now part of the DeploymentSpec and understood by the
DeploymentSpecXmlReader classes.
Diffstat (limited to 'config-model-api/src/main/java')
3 files changed, 100 insertions, 8 deletions
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 66111b91aa0..05f5f667287 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 @@ -46,7 +46,8 @@ public class DeploymentSpec { "<deployment version='1.0'/>", Optional.empty(), Optional.empty(), - Notifications.none()); + Notifications.none(), + Collections.emptyList()); private final Optional<String> globalServiceId; private final UpgradePolicy upgradePolicy; @@ -57,10 +58,12 @@ public class DeploymentSpec { private final Optional<AthenzDomain> athenzDomain; private final Optional<AthenzService> athenzService; private final Notifications notifications; + private final List<Endpoint> endpoints; public DeploymentSpec(Optional<String> globalServiceId, UpgradePolicy upgradePolicy, Optional<Integer> majorVersion, List<ChangeBlocker> changeBlockers, List<Step> steps, String xmlForm, - Optional<AthenzDomain> athenzDomain, Optional<AthenzService> athenzService, Notifications notifications) { + Optional<AthenzDomain> athenzDomain, Optional<AthenzService> athenzService, Notifications notifications, + List<Endpoint> endpoints) { validateTotalDelay(steps); this.globalServiceId = globalServiceId; this.upgradePolicy = upgradePolicy; @@ -71,6 +74,7 @@ public class DeploymentSpec { this.athenzDomain = athenzDomain; this.athenzService = athenzService; this.notifications = notifications; + this.endpoints = Objects.requireNonNull(endpoints, "Missing endpoints parameter"); validateZones(this.steps); validateAthenz(); } @@ -101,16 +105,16 @@ public class DeploymentSpec { */ private void validateAthenz() { // If athenz domain is not set, athenz service cannot be set on any level - if (! athenzDomain.isPresent()) { + if (athenzDomain.isEmpty()) { for (DeclaredZone zone : zones()) { if(zone.athenzService().isPresent()) { throw new IllegalArgumentException("Athenz service configured for zone: " + zone + ", but Athenz domain is not configured"); } } // if athenz domain is not set, athenz service must be set implicitly or directly on all zones. - } else if(! athenzService.isPresent()) { + } else if (athenzService.isEmpty()) { for (DeclaredZone zone : zones()) { - if(! zone.athenzService().isPresent()) { + if (zone.athenzService().isEmpty()) { throw new IllegalArgumentException("Athenz domain is configured, but Athenz service not configured for zone: " + zone); } } @@ -199,6 +203,9 @@ public class DeploymentSpec { /** Returns the notification configuration */ public Notifications notifications() { return notifications; } + /** Returns the rotations configuration */ + public List<Endpoint> endpoints() { return Collections.unmodifiableList(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; } @@ -369,7 +376,7 @@ public class DeploymentSpec { Optional<AthenzService> athenzService, Optional<String> testerFlavor) { if (environment != Environment.prod && region.isPresent()) throw new IllegalArgumentException("Non-prod environments cannot specify a region"); - if (environment == Environment.prod && ! region.isPresent()) + if (environment == Environment.prod && region.isEmpty()) throw new IllegalArgumentException("Prod environments must be specified with a region"); this.environment = environment; this.region = region; @@ -417,7 +424,7 @@ public class DeploymentSpec { @Override public String toString() { - return environment + ( region.isPresent() ? "." + region.get() : ""); + return environment + (region.map(regionName -> "." + regionName).orElse("")); } } diff --git a/config-model-api/src/main/java/com/yahoo/config/application/api/Endpoint.java b/config-model-api/src/main/java/com/yahoo/config/application/api/Endpoint.java new file mode 100644 index 00000000000..b505bf72faf --- /dev/null +++ b/config-model-api/src/main/java/com/yahoo/config/application/api/Endpoint.java @@ -0,0 +1,51 @@ +package com.yahoo.config.application.api; + +import java.util.Objects; +import java.util.Optional; +import java.util.Set; + +/** + * Represents a (global) endpoint in 'deployments.xml'. It contains the name of the + * endpoint (endpointId) and the name of the container cluster that the endpoint + * should point to. + * + * If the endpointId is not set, it will default to the same as the containerId. + */ +public class Endpoint { + private final Optional<String> endpointId; + private final String containerId; + private final Set<String> regions; + + public Endpoint(Optional<String> endpointId, String containerId, Set<String> regions) { + this.endpointId = endpointId; + this.containerId = containerId; + this.regions = Set.copyOf(regions); + } + + public String endpointId() { + return endpointId.orElse(containerId); + } + + public String containerId() { + return containerId; + } + + public Set<String> regions() { + return regions; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Endpoint endpoint = (Endpoint) o; + return Objects.equals(endpointId, endpoint.endpointId) && + Objects.equals(containerId, endpoint.containerId) && + Objects.equals(regions, endpoint.regions); + } + + @Override + public int hashCode() { + return Objects.hash(endpointId, containerId, regions); + } +} 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 8e899b28a06..1078317e0d2 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 @@ -6,6 +6,7 @@ import com.yahoo.config.application.api.DeploymentSpec.DeclaredZone; import com.yahoo.config.application.api.DeploymentSpec.Delay; import com.yahoo.config.application.api.DeploymentSpec.ParallelZones; import com.yahoo.config.application.api.DeploymentSpec.Step; +import com.yahoo.config.application.api.Endpoint; import com.yahoo.config.application.api.Notifications; import com.yahoo.config.application.api.Notifications.Role; import com.yahoo.config.application.api.Notifications.When; @@ -25,6 +26,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Optional; @@ -40,6 +42,8 @@ public class DeploymentSpecXmlReader { private static final String stagingTag = "staging"; private static final String blockChangeTag = "block-change"; private static final String prodTag = "prod"; + private static final String endpointsTag = "endpoints"; + private static final String endpointTag = "endpoint"; private final boolean validate; @@ -123,7 +127,8 @@ public class DeploymentSpecXmlReader { xmlForm, athenzDomain, athenzService, - readNotifications(root)); + readNotifications(root), + readEndpoints(root)); } private Notifications readNotifications(Element root) { @@ -152,6 +157,35 @@ public class DeploymentSpecXmlReader { return Notifications.of(emailAddresses, emailRoles); } + private List<Endpoint> readEndpoints(Element root) { + final var endpointsElement = XML.getChild(root, endpointsTag); + if (endpointsElement == null) { return Collections.emptyList(); } + + final var endpoints = new ArrayList<Endpoint>(); + + for (var endpointElement : XML.getChildren(endpointsElement, endpointTag)) { + final Optional<String> rotationId = stringAttribute("id", endpointElement); + final Optional<String> containerId = stringAttribute("container-id", endpointElement); + final var regions = new HashSet<String>(); + + if (containerId.isEmpty()) { + throw new IllegalArgumentException("Missing 'container-id' from 'endpoint' tag."); + } + + for (var regionElement : XML.getChildren(endpointElement, "region")) { + var region = regionElement.getTextContent(); + if (region == null || region.isEmpty() || region.isBlank()) { + throw new IllegalArgumentException("Empty 'region' element in 'endpoint' tag."); + } + regions.add(regionElement.getTextContent()); + } + + endpoints.add(new Endpoint(rotationId, containerId.get(), regions)); + } + + return endpoints; + } + /** * Imposes some constraints on tag order which are not expressible in the schema */ |