summaryrefslogtreecommitdiffstats
path: root/config-model-api
diff options
context:
space:
mode:
authorMorten Tokle <mortent@oath.com>2017-11-20 14:12:53 +0100
committerMorten Tokle <mortent@oath.com>2017-11-21 14:04:51 +0100
commit28f6fb192d3ba9d019fa9265b2770cc4325d5240 (patch)
tree5a39cb23602499ece36cb240b443f59e28aa8ed9 /config-model-api
parentef6ad29be045374dbd5a885d036fe12a95c5dc9c (diff)
Move identity configuration services.xml -> deployment.xml
Diffstat (limited to 'config-model-api')
-rw-r--r--config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentSpec.java62
-rw-r--r--config-model-api/src/main/java/com/yahoo/config/application/api/xml/DeploymentSpecXmlReader.java20
-rw-r--r--config-model-api/src/test/java/com/yahoo/config/application/api/DeploymentSpecTest.java52
3 files changed, 125 insertions, 9 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 4d370ba5039..1a2335c82db 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
@@ -39,28 +39,36 @@ public class DeploymentSpec {
UpgradePolicy.defaultPolicy,
Collections.emptyList(),
Collections.emptyList(),
- "<deployment version='1.0'/>");
+ "<deployment version='1.0'/>",
+ Optional.empty(),
+ Optional.empty());
private final Optional<String> globalServiceId;
private final UpgradePolicy upgradePolicy;
private final List<ChangeBlocker> changeBlockers;
private final List<Step> steps;
private final String xmlForm;
+ private final Optional<String> athenzDomain;
+ private final Optional<String> athenzService;
public DeploymentSpec(Optional<String> globalServiceId, UpgradePolicy upgradePolicy,
List<ChangeBlocker> changeBlockers, List<Step> steps) {
- this(globalServiceId, upgradePolicy, changeBlockers, steps, null);
+ this(globalServiceId, upgradePolicy, changeBlockers, steps, null, Optional.empty(), Optional.empty());
}
public DeploymentSpec(Optional<String> globalServiceId, UpgradePolicy upgradePolicy,
- List<ChangeBlocker> changeBlockers, List<Step> steps, String xmlForm) {
+ List<ChangeBlocker> changeBlockers, List<Step> steps, String xmlForm,
+ Optional<String> athenzDomain, Optional<String> athenzService) {
validateTotalDelay(steps);
this.globalServiceId = globalServiceId;
this.upgradePolicy = upgradePolicy;
this.changeBlockers = changeBlockers;
this.steps = ImmutableList.copyOf(completeSteps(new ArrayList<>(steps)));
this.xmlForm = xmlForm;
+ this.athenzDomain = athenzDomain;
+ this.athenzService = athenzService;
validateZones(this.steps);
+ validateAthenz();
}
/** Throw an IllegalArgumentException if the total delay exceeds 24 hours */
@@ -81,7 +89,30 @@ public class DeploymentSpec {
for (DeclaredZone zone : step.zones())
ensureUnique(zone, zones);
}
-
+
+ /*
+ * Throw an IllegalArgumentException if Athenz configuration violates:
+ * domain not configured -> no zone can configure service
+ * domain configured -> all zones must configure service
+ */
+ private void validateAthenz() {
+ // If athenz domain is not set, athenz service cannot be set on any level
+ if (! athenzDomain.isPresent()) {
+ 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 configured, athenz service must be set implicitly or directly on all zones.
+ } else if(! athenzService.isPresent()) {
+ for (DeclaredZone zone : zones()) {
+ if(! zone.athenzService().isPresent()) {
+ throw new IllegalArgumentException("Athenz domain is configured, but Athenz service not configured for zone: " + zone);
+ }
+ }
+ }
+ }
+
private void ensureUnique(DeclaredZone zone, Set<DeclaredZone> zones) {
if ( ! zones.add(zone))
throw new IllegalArgumentException(zone + " is listed twice in deployment.xml");
@@ -212,6 +243,20 @@ public class DeploymentSpec {
return b.toString();
}
+ /** Returns the athenz domain if configured */
+ public Optional<String> athenzDomain() {
+ return athenzDomain;
+ }
+
+ /** Returns the athenz service for environment/region if configured */
+ public Optional<String> athenzService(Environment environment, RegionName region) {
+ return zones().stream()
+ .filter(zone -> zone.deploysTo(environment, Optional.of(region)))
+ .findFirst()
+ .map(DeclaredZone::athenzService)
+ .orElse(athenzService);
+ }
+
/** This may be invoked by a continuous build */
public static void main(String[] args) {
if (args.length != 2 && args.length != 3) {
@@ -276,11 +321,17 @@ public class DeploymentSpec {
private final boolean active;
+ private Optional<String> athenzService;
+
public DeclaredZone(Environment environment) {
this(environment, Optional.empty(), false);
}
public DeclaredZone(Environment environment, Optional<RegionName> region, boolean active) {
+ this(environment, region, active, Optional.empty());
+ }
+
+ public DeclaredZone(Environment environment, Optional<RegionName> region, boolean active, Optional<String> athenzService) {
if (environment != Environment.prod && region.isPresent())
throw new IllegalArgumentException("Non-prod environments cannot specify a region");
if (environment == Environment.prod && ! region.isPresent())
@@ -288,6 +339,7 @@ public class DeploymentSpec {
this.environment = environment;
this.region = region;
this.active = active;
+ this.athenzService = athenzService;
}
public Environment environment() { return environment; }
@@ -298,6 +350,8 @@ public class DeploymentSpec {
/** Returns whether this zone should receive production traffic */
public boolean active() { return active; }
+ public Optional<String> athenzService() { return athenzService; }
+
@Override
public List<DeclaredZone> zones() { return Collections.singletonList(this); }
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 5599b257b16..1a970e53713 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
@@ -72,6 +72,7 @@ public class DeploymentSpecXmlReader {
if (environment == Environment.prod) {
for (Element stepTag : XML.getChildren(environmentTag)) {
+ Optional<String> athenzService = stringAttribute("athenz-service", environmentTag);
if (stepTag.getTagName().equals("delay")) {
steps.add(new Delay(Duration.ofSeconds(longAttribute("hours", stepTag) * 60 * 60 +
longAttribute("minutes", stepTag) * 60 +
@@ -79,11 +80,11 @@ public class DeploymentSpecXmlReader {
} else if (stepTag.getTagName().equals("parallel")) {
List<DeclaredZone> zones = new ArrayList<>();
for (Element regionTag : XML.getChildren(stepTag)) {
- zones.add(readDeclaredZone(environment, regionTag));
+ zones.add(readDeclaredZone(environment, athenzService, regionTag));
}
steps.add(new ParallelZones(zones));
} else { // a region: deploy step
- steps.add(readDeclaredZone(environment, stepTag));
+ steps.add(readDeclaredZone(environment, athenzService, stepTag));
}
}
} else {
@@ -94,8 +95,11 @@ public class DeploymentSpecXmlReader {
globalServiceId = readGlobalServiceId(environmentTag);
else if (readGlobalServiceId(environmentTag).isPresent())
throw new IllegalArgumentException("Attribute 'global-service-id' is only valid on 'prod' tag.");
+
}
- return new DeploymentSpec(globalServiceId, readUpgradePolicy(root), readChangeBlockers(root), steps, xmlForm);
+ Optional<String> athenzDomain = stringAttribute("athenz-domain", root);
+ Optional<String> athenzService = stringAttribute("athenz-service", root);
+ return new DeploymentSpec(globalServiceId, readUpgradePolicy(root), readChangeBlockers(root), steps, xmlForm, athenzDomain, athenzService);
}
/** Imposes some constraints on tag order which are not expressible in the schema */
@@ -132,13 +136,19 @@ public class DeploymentSpecXmlReader {
}
}
+ /** Returns the given attribute as a string, or Optional.empty if it is not present or empty */
+ private Optional<String> stringAttribute(String attributeName, Element tag) {
+ String value = tag.getAttribute(attributeName);
+ return Optional.ofNullable(value).filter(s -> ! s.equals(""));
+ }
+
private boolean isEnvironmentName(String tagName) {
return tagName.equals(testTag) || tagName.equals(stagingTag) || tagName.equals(prodTag);
}
- private DeclaredZone readDeclaredZone(Environment environment, Element regionTag) {
+ private DeclaredZone readDeclaredZone(Environment environment, Optional<String> athenzService, Element regionTag) {
return new DeclaredZone(environment, Optional.of(RegionName.from(XML.getValue(regionTag).trim())),
- readActive(regionTag));
+ readActive(regionTag), athenzService);
}
private Optional<String> readGlobalServiceId(Element environmentTag) {
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 5050f88af31..5dcb3bc1ebe 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
@@ -367,4 +367,56 @@ public class DeploymentSpecTest {
assertTrue(spec.canUpgradeAt(Instant.parse("2017-09-23T10:15:30.00Z")));
}
+ @Test
+ public void deploymentSpecWithAthenzIdentity() {
+ StringReader r = new StringReader(
+ "<deployment athenz-domain='domain' athenz-service='service'>\n" +
+ " <prod>\n" +
+ " <region active='true'>us-west-1</region>\n" +
+ " </prod>\n" +
+ "</deployment>"
+ );
+ DeploymentSpec spec = DeploymentSpec.fromXml(r);
+ assertEquals(spec.athenzDomain().get(), "domain");
+ assertEquals(spec.athenzService(Environment.prod, RegionName.from("us-west-1")).get(), "service");
+ }
+
+ @Test
+ public void deploymentSpecUsesServiceFromEnvironment() {
+ StringReader r = new StringReader(
+ "<deployment athenz-domain='domain' athenz-service='service'>\n" +
+ " <test/>\n" +
+ " <prod athenz-service='prod-service'>\n" +
+ " <region active='true'>us-west-1</region>\n" +
+ " </prod>\n" +
+ "</deployment>"
+ );
+ DeploymentSpec spec = DeploymentSpec.fromXml(r);
+ assertEquals(spec.athenzDomain().get(), "domain");
+ assertEquals(spec.athenzService(Environment.prod, RegionName.from("us-west-1")).get(), "prodservice");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void athenzDomainMissingService() {
+ StringReader r = new StringReader(
+ "<deployment athenz-domain='domain'>\n" +
+ " <prod>\n" +
+ " <region active='true'>us-west-1</region>\n" +
+ " </prod>\n" +
+ "</deployment>"
+ );
+ DeploymentSpec spec = DeploymentSpec.fromXml(r);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void athenzDomainMissingDomain() {
+ StringReader r = new StringReader(
+ "<deployment>\n" +
+ " <prod athenz-service='service'>\n" +
+ " <region active='true'>us-west-1</region>\n" +
+ " </prod>\n" +
+ "</deployment>"
+ );
+ DeploymentSpec spec = DeploymentSpec.fromXml(r);
+ }
}