summaryrefslogtreecommitdiffstats
path: root/config-model-api
diff options
context:
space:
mode:
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
commit0875cb2e7f31396a42a2543b3c54ba07cde0ef6a (patch)
tree0d568c4e44f888cf1264a4cc481bbf3af1729e3c /config-model-api
parentc0a5ffd1ca99b92eeabfcd96c561ec1317ee797d (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')
-rw-r--r--config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentSpec.java21
-rw-r--r--config-model-api/src/main/java/com/yahoo/config/application/api/Endpoint.java51
-rw-r--r--config-model-api/src/main/java/com/yahoo/config/application/api/xml/DeploymentSpecXmlReader.java36
-rw-r--r--config-model-api/src/test/java/com/yahoo/config/application/api/DeploymentSpecTest.java42
4 files changed, 140 insertions, 10 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
*/
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 46e6dc457e9..e783ee89729 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
@@ -1,9 +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;
-import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
-import com.yahoo.config.provision.Deployment;
import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.RegionName;
import org.junit.Test;
@@ -11,7 +9,11 @@ import org.junit.Test;
import java.io.StringReader;
import java.time.Instant;
import java.time.ZoneId;
+import java.util.Collections;
+import java.util.List;
import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
import static com.yahoo.config.application.api.Notifications.Role.author;
import static com.yahoo.config.application.api.Notifications.When.failing;
@@ -452,4 +454,40 @@ public class DeploymentSpecTest {
assertEquals(Optional.of("d-2-8-50"), spec.steps().get(2).zones().get(0).testerFlavor());
}
+ @Test
+ public void noEndpoints() {
+ assertEquals(Collections.emptyList(), DeploymentSpec.fromXml("<deployment />").endpoints());
+ }
+
+ @Test
+ public void emptyEndpoints() {
+ final var spec = DeploymentSpec.fromXml("<deployment><endpoints/></deployment>");
+ assertEquals(Collections.emptyList(), spec.endpoints());
+ }
+
+ @Test
+ public void someEndpoints() {
+ final var spec = DeploymentSpec.fromXml("" +
+ "<deployment>" +
+ " <endpoints>" +
+ " <endpoint id=\"foo\" container-id=\"bar\">" +
+ " <region>us-east</region>" +
+ " </endpoint>" +
+ " <endpoint id=\"nalle\" container-id=\"frosk\" />" +
+ " <endpoint container-id=\"quux\" />" +
+ " </endpoints>" +
+ "</deployment>");
+
+ assertEquals(
+ List.of("foo", "nalle", "quux"),
+ spec.endpoints().stream().map(Endpoint::endpointId).collect(Collectors.toList())
+ );
+
+ assertEquals(
+ List.of("bar", "frosk", "quux"),
+ spec.endpoints().stream().map(Endpoint::containerId).collect(Collectors.toList())
+ );
+
+ assertEquals(Set.of("us-east"), spec.endpoints().get(0).regions());
+ }
}