summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMorten Tokle <morten.tokle@gmail.com>2017-11-23 12:11:14 +0100
committerGitHub <noreply@github.com>2017-11-23 12:11:14 +0100
commit26116eedb3c553a7387a1abd7dc67ceeeee2b078 (patch)
tree6fbd920ac99dc7d22084a8b3dc49a3198c44f8c7
parentb46c7c42a0aca18b8c7c54e2fa07bc08bcfecd12 (diff)
parent1e23ba499b681f05f5c19c09e26e4488b4d31121 (diff)
Merge pull request #4203 from vespa-engine/mortent/identity-in-deployment
Move identity configuration services.xml -> deployment.xml
-rw-r--r--config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentSpec.java65
-rw-r--r--config-model-api/src/main/java/com/yahoo/config/application/api/xml/DeploymentSpecXmlReader.java22
-rw-r--r--config-model-api/src/test/java/com/yahoo/config/application/api/DeploymentSpecTest.java52
-rwxr-xr-xconfig-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java55
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/container/IdentityProvider.java (renamed from config-model/src/main/java/com/yahoo/vespa/model/container/Identity.java)14
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java85
-rw-r--r--config-model/src/main/resources/schema/containercluster.rnc8
-rw-r--r--config-model/src/main/resources/schema/deployment.rnc9
-rwxr-xr-xconfig-model/src/test/java/com/yahoo/vespa/model/container/ContainerClusterTest.java45
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java2
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/container/xml/IdentityBuilderTest.java29
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/container/xml/RoutingBuilderTest.java78
-rw-r--r--config-model/src/test/schema-test-files/deployment.xml4
-rw-r--r--config-model/src/test/schema-test-files/services.xml4
-rw-r--r--config-provisioning/src/main/java/com/yahoo/config/provision/AthenzDomain.java42
-rw-r--r--config-provisioning/src/main/java/com/yahoo/config/provision/AthenzService.java42
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/http/CompressedApplicationInputStreamTest.java27
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionCreateHandlerTest.java27
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/model/LbServicesProducerTest.java5
-rw-r--r--configserver/src/test/resources/deploy/advancedapp/deployment.xml1
-rw-r--r--configserver/src/test/resources/deploy/app/deployment.xml1
-rw-r--r--configserver/src/test/resources/deploy/validapp/deployment.xml1
22 files changed, 430 insertions, 188 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..64e986abf9b 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
@@ -3,6 +3,8 @@ package com.yahoo.config.application.api;
import com.google.common.collect.ImmutableList;
import com.yahoo.config.application.api.xml.DeploymentSpecXmlReader;
+import com.yahoo.config.provision.AthenzDomain;
+import com.yahoo.config.provision.AthenzService;
import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.RegionName;
@@ -39,28 +41,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<AthenzDomain> athenzDomain;
+ private final Optional<AthenzService> 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<AthenzDomain> athenzDomain, Optional<AthenzService> 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 +91,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 not set, 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 +245,21 @@ public class DeploymentSpec {
return b.toString();
}
+ /** 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) {
+ AthenzService athenzService = zones().stream()
+ .filter(zone -> zone.deploysTo(environment, Optional.of(region)))
+ .findFirst()
+ .flatMap(DeclaredZone::athenzService)
+ .orElse(this.athenzService.orElse(null));
+ return Optional.ofNullable(athenzService);
+ }
+
/** This may be invoked by a continuous build */
public static void main(String[] args) {
if (args.length != 2 && args.length != 3) {
@@ -276,11 +324,17 @@ public class DeploymentSpec {
private final boolean active;
+ private Optional<AthenzService> 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<AthenzService> 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 +342,7 @@ public class DeploymentSpec {
this.environment = environment;
this.region = region;
this.active = active;
+ this.athenzService = athenzService;
}
public Environment environment() { return environment; }
@@ -298,6 +353,8 @@ public class DeploymentSpec {
/** Returns whether this zone should receive production traffic */
public boolean active() { return active; }
+ public Optional<AthenzService> 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..8bc4e0026a6 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
@@ -7,6 +7,8 @@ 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.TimeWindow;
+import com.yahoo.config.provision.AthenzDomain;
+import com.yahoo.config.provision.AthenzService;
import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.RegionName;
import com.yahoo.io.IOUtils;
@@ -72,6 +74,7 @@ public class DeploymentSpecXmlReader {
if (environment == Environment.prod) {
for (Element stepTag : XML.getChildren(environmentTag)) {
+ Optional<AthenzService> athenzService = stringAttribute("athenz-service", environmentTag).map(AthenzService::from);
if (stepTag.getTagName().equals("delay")) {
steps.add(new Delay(Duration.ofSeconds(longAttribute("hours", stepTag) * 60 * 60 +
longAttribute("minutes", stepTag) * 60 +
@@ -79,11 +82,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 +97,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<AthenzDomain> athenzDomain = stringAttribute("athenz-domain", root).map(AthenzDomain::from);
+ Optional<AthenzService> athenzService = stringAttribute("athenz-service", root).map(AthenzService::from);
+ 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 +138,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<AthenzService> 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..103724744de 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 athenz_config_is_read_from_deployment() {
+ 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().value(), "domain");
+ assertEquals(spec.athenzService(Environment.prod, RegionName.from("us-west-1")).get().value(), "service");
+ }
+
+ @Test
+ public void athenz_service_is_overridden_from_environment() {
+ 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().value(), "domain");
+ assertEquals(spec.athenzService(Environment.prod, RegionName.from("us-west-1")).get().value(), "prod-service");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void it_fails_when_athenz_service_is_not_defined() {
+ 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 it_fails_when_athenz_service_is_configured_but_not_athenz_domain() {
+ 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);
+ }
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java b/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java
index 91d5b7fe267..4383e55e45d 100755
--- a/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java
@@ -9,13 +9,10 @@ import com.yahoo.component.ComponentSpecification;
import com.yahoo.config.FileReference;
import com.yahoo.config.application.api.ApplicationMetaData;
import com.yahoo.config.application.api.ComponentInfo;
-import com.yahoo.config.application.api.DeploymentSpec;
import com.yahoo.config.docproc.DocprocConfig;
import com.yahoo.config.docproc.SchemamappingConfig;
import com.yahoo.config.model.ApplicationConfigProducerRoot;
import com.yahoo.config.model.producer.AbstractConfigProducer;
-import com.yahoo.config.model.producer.AbstractConfigProducerRoot;
-import com.yahoo.config.provision.Rotation;
import com.yahoo.config.provision.Zone;
import com.yahoo.container.BundlesConfig;
import com.yahoo.container.ComponentsConfig;
@@ -85,7 +82,6 @@ import com.yahoo.vespaclient.config.FeederConfig;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
-import java.io.Reader;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
@@ -382,8 +378,6 @@ public final class ContainerCluster
container.setClusterName(name);
container.setProp("clustername", name)
.setProp("index", this.containers.size());
- setRotations(container, getRotations(), getGlobalServiceId(), name);
- container.setProp("activeRotation", Boolean.toString(getActiveRotation()));
containers.add(container);
}
@@ -393,55 +387,6 @@ public final class ContainerCluster
}
}
- private Optional<String> getGlobalServiceId() {
- Optional<DeploymentSpec> deploymentSpec = getDeploymentSpec();
- if (deploymentSpec.isPresent()) return deploymentSpec.get().globalServiceId();
- return Optional.empty();
- }
-
- private Set<Rotation> getRotations() {
- return Optional.ofNullable(getRoot())
- .map(root -> root.getDeployState().getRotations())
- .orElse(Collections.emptySet());
- }
-
- private boolean getActiveRotation() {
- return Optional.ofNullable(getRoot())
- .map(root -> root.getDeployState().getProperties().zone())
- .map(this::zoneHasActiveRotation)
- .orElse(false);
- }
-
- private boolean zoneHasActiveRotation(Zone zone) {
- Optional<DeploymentSpec> spec = getDeploymentSpec();
- if (!spec.isPresent()) {
- return false;
- }
- return spec.get().zones().stream()
- .anyMatch(declaredZone -> declaredZone.deploysTo(zone.environment(), Optional.of(zone.region())) &&
- declaredZone.active());
- }
-
- private Optional<DeploymentSpec> getDeploymentSpec() {
- Optional<DeploymentSpec> deploymentSpec = Optional.empty();
- AbstractConfigProducerRoot root = getRoot();
- if (root != null) {
- final Optional<Reader> deployment = root.getDeployState().getApplicationPackage().getDeployment();
- if (deployment.isPresent()) {
- deploymentSpec = Optional.of(DeploymentSpec.fromXml(deployment.get()));
- }
- }
- return deploymentSpec;
- }
-
- private void setRotations(Container container, Set<Rotation> rotations, Optional<String> globalServiceId, String containerClusterName) {
- if ( ! rotations.isEmpty() && globalServiceId.isPresent()) {
- if (containerClusterName.equals(globalServiceId.get())) {
- container.setProp("rotations", rotations.stream().map(Rotation::getId).collect(Collectors.joining(",")));
- }
- }
- }
-
public void setProcessingChains(ProcessingChains processingChains, String... serverBindings) {
if (this.processingChains != null)
throw new IllegalStateException("ProcessingChains should only be set once.");
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/Identity.java b/config-model/src/main/java/com/yahoo/vespa/model/container/IdentityProvider.java
index bc7a6e20361..0368f7eaf3e 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/container/Identity.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/container/IdentityProvider.java
@@ -1,6 +1,8 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.model.container;
+import com.yahoo.config.provision.AthenzDomain;
+import com.yahoo.config.provision.AthenzService;
import com.yahoo.config.provision.HostName;
import com.yahoo.container.core.identity.IdentityConfig;
import com.yahoo.container.jdisc.athenz.impl.AthenzIdentityProviderImpl;
@@ -9,14 +11,14 @@ import com.yahoo.vespa.model.container.component.SimpleComponent;
/**
* @author mortent
*/
-public class Identity extends SimpleComponent implements IdentityConfig.Producer {
+public class IdentityProvider extends SimpleComponent implements IdentityConfig.Producer {
public static final String CLASS = AthenzIdentityProviderImpl.class.getName();
- private final String domain;
- private final String service;
+ private final AthenzDomain domain;
+ private final AthenzService service;
private final HostName loadBalancerName;
- public Identity(String domain, String service, HostName loadBalancerName) {
+ public IdentityProvider(AthenzDomain domain, AthenzService service, HostName loadBalancerName) {
super(CLASS);
this.domain = domain;
this.service = service;
@@ -25,8 +27,8 @@ public class Identity extends SimpleComponent implements IdentityConfig.Producer
@Override
public void getConfig(IdentityConfig.Builder builder) {
- builder.domain(domain);
- builder.service(service);
+ builder.domain(domain.value());
+ builder.service(service.value());
// Current interpretation of loadbalancer address is: hostname.
// Config should be renamed or send the uri
builder.loadBalancerAddress(loadBalancerName.value());
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 d59846cd5e2..81fc464327e 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
@@ -6,18 +6,22 @@ import com.yahoo.component.Version;
import com.yahoo.config.application.Xml;
import com.yahoo.config.application.api.ApplicationPackage;
import com.yahoo.config.application.api.DeployLogger;
+import com.yahoo.config.application.api.DeploymentSpec;
import com.yahoo.config.model.ConfigModelContext;
import com.yahoo.config.model.api.ConfigServerSpec;
import com.yahoo.config.model.application.provider.IncludeDirs;
import com.yahoo.config.model.builder.xml.ConfigModelBuilder;
import com.yahoo.config.model.builder.xml.ConfigModelId;
import com.yahoo.config.model.producer.AbstractConfigProducer;
+import com.yahoo.config.provision.AthenzService;
import com.yahoo.config.provision.Capacity;
import com.yahoo.config.provision.ClusterMembership;
import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.HostName;
import com.yahoo.config.provision.NodeType;
+import com.yahoo.config.provision.Rotation;
+import com.yahoo.config.provision.Zone;
import com.yahoo.container.jdisc.config.MetricDefaultsConfig;
import com.yahoo.search.rendering.RendererRegistry;
import com.yahoo.text.XML;
@@ -39,7 +43,7 @@ import com.yahoo.vespa.model.clients.ContainerDocumentApi;
import com.yahoo.vespa.model.container.Container;
import com.yahoo.vespa.model.container.ContainerCluster;
import com.yahoo.vespa.model.container.ContainerModel;
-import com.yahoo.vespa.model.container.Identity;
+import com.yahoo.vespa.model.container.IdentityProvider;
import com.yahoo.vespa.model.container.component.Component;
import com.yahoo.vespa.model.container.component.FileStatusHandlerComponent;
import com.yahoo.vespa.model.container.component.chain.ProcessingHandler;
@@ -64,6 +68,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
+import java.util.Set;
import java.util.function.Consumer;
import java.util.logging.Logger;
import java.util.stream.Collectors;
@@ -167,14 +172,42 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> {
// Athenz copper argos
// NOTE: Must be done after addNodes()
- addIdentity(spec,
- cluster,
- context.getDeployState().getProperties().configServerSpecs(),
- context.getDeployState().getProperties().loadBalancerName());
+ app.getDeployment().map(DeploymentSpec::fromXml)
+ .ifPresent(deploymentSpec -> {
+ addIdentityProvider(cluster,
+ context.getDeployState().getProperties().configServerSpecs(),
+ context.getDeployState().getProperties().loadBalancerName(),
+ context.getDeployState().zone(),
+ deploymentSpec);
+
+ addRotationProperties(cluster, context.getDeployState().zone(), context.getDeployState().getRotations(), deploymentSpec);
+ });
//TODO: overview handler, see DomQrserverClusterBuilder
}
+ private void addRotationProperties(ContainerCluster cluster, Zone zone, Set<Rotation> rotations, DeploymentSpec spec) {
+ cluster.getContainers().forEach(container -> {
+ setRotations(container, rotations, spec.globalServiceId(), cluster.getName());
+ container.setProp("activeRotation", Boolean.toString(zoneHasActiveRotation(zone, spec)));
+ });
+ }
+
+ private boolean zoneHasActiveRotation(Zone zone, DeploymentSpec spec) {
+ return spec.zones().stream()
+ .anyMatch(declaredZone -> declaredZone.deploysTo(zone.environment(), Optional.of(zone.region())) &&
+ declaredZone.active());
+ }
+
+ private void setRotations(Container container, Set<Rotation> rotations, Optional<String> globalServiceId, String containerClusterName) {
+
+ if ( ! rotations.isEmpty() && globalServiceId.isPresent()) {
+ if (containerClusterName.equals(globalServiceId.get())) {
+ container.setProp("rotations", rotations.stream().map(Rotation::getId).collect(Collectors.joining(",")));
+ }
+ }
+ }
+
private void addRoutingAliases(ContainerCluster cluster, Element spec, Environment environment) {
if (environment != Environment.prod) return;
@@ -698,31 +731,33 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> {
}
}
- private void addIdentity(Element element, ContainerCluster cluster, List<ConfigServerSpec> configServerSpecs, HostName loadBalancerName) {
- Element identityElement = XML.getChild(element, "identity");
- if(identityElement != null) {
- String domain = XML.getValue(XML.getChild(identityElement, "domain"));
- String service = XML.getValue(XML.getChild(identityElement, "service"));
-
- // Set lbaddress, or use first hostname if not specified.
- HostName lbName = Optional.ofNullable(loadBalancerName)
- .orElseGet(
- () -> HostName.from(configServerSpecs.stream()
- .findFirst()
- .map(ConfigServerSpec::getHostName)
- .orElse("unknown") // Currently unable to test this, hence the unknown
- ));
-
- Identity identity = new Identity(domain.trim(), service.trim(), lbName);
- cluster.addComponent(identity);
+ private void addIdentityProvider(ContainerCluster cluster, List<ConfigServerSpec> configServerSpecs, HostName loadBalancerName, Zone zone, DeploymentSpec spec) {
+ spec.athenzDomain().ifPresent(domain -> {
+ AthenzService service = spec.athenzService(zone.environment(), zone.region())
+ .orElseThrow(() -> new RuntimeException("Missing Athenz service configuration"));
+ IdentityProvider identityProvider = new IdentityProvider(domain, service, getLoadBalancerName(loadBalancerName, configServerSpecs));
+ cluster.addComponent(identityProvider);
cluster.getContainers().forEach(container -> {
- container.setProp("identity.domain", domain);
- container.setProp("identity.service", service);
+ container.setProp("identity.domain", domain.value());
+ container.setProp("identity.service", service.value());
});
- }
+ });
+ }
+
+ private HostName getLoadBalancerName(HostName loadbalancerName, List<ConfigServerSpec> configServerSpecs) {
+ // Set lbaddress, or use first hostname if not specified.
+ // TODO: Remove this method and use the loadbalancerName directly
+ return Optional.ofNullable(loadbalancerName)
+ .orElseGet(
+ () -> HostName.from(configServerSpecs.stream()
+ .findFirst()
+ .map(ConfigServerSpec::getHostName)
+ .orElse("unknown") // Currently unable to test this, hence the unknown
+ ));
}
+
/**
* Disallow renderers named "DefaultRenderer" or "JsonRenderer"
*/
diff --git a/config-model/src/main/resources/schema/containercluster.rnc b/config-model/src/main/resources/schema/containercluster.rnc
index 47cf0638d72..6a90bef7bb2 100644
--- a/config-model/src/main/resources/schema/containercluster.rnc
+++ b/config-model/src/main/resources/schema/containercluster.rnc
@@ -7,8 +7,7 @@ ContainerCluster = element container | jdisc {
ContainerServices &
DocumentBinding* &
Aliases? &
- NodesOfContainerCluster? &
- Identity?
+ NodesOfContainerCluster?
}
ContainerServices =
@@ -226,8 +225,3 @@ DocumentBinding = element document {
attribute class { xsd:NCName } &
attribute bundle { xsd:NCName }
}
-
-Identity = element identity {
- element domain { xsd:NCName } &
- element service { xsd:NCName }
-}
diff --git a/config-model/src/main/resources/schema/deployment.rnc b/config-model/src/main/resources/schema/deployment.rnc
index 90bff8e31b3..2ecfa781876 100644
--- a/config-model/src/main/resources/schema/deployment.rnc
+++ b/config-model/src/main/resources/schema/deployment.rnc
@@ -4,6 +4,8 @@
start = element deployment {
attribute version { "1.0" } &
+ attribute athenz-domain { xsd:string }? &
+ attribute athenz-service { xsd:string }? &
Upgrade? &
BlockChange* &
Test? &
@@ -31,15 +33,18 @@ BlockUpgrade = element block-upgrade { # Legacy name - remove on Vespa 7
}
Test = element test {
- text
+ attribute athenz-service { xsd:string }? &
+ text
}
Staging = element staging {
- text
+ attribute athenz-service { xsd:string }? &
+ text
}
Prod = element prod {
attribute global-service-id { text }? &
+ attribute athenz-service { xsd:string }? &
Region* &
Delay* &
Parallel*
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/container/ContainerClusterTest.java b/config-model/src/test/java/com/yahoo/vespa/model/container/ContainerClusterTest.java
index af846f10ffe..d9c151480fe 100755
--- a/config-model/src/test/java/com/yahoo/vespa/model/container/ContainerClusterTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/container/ContainerClusterTest.java
@@ -18,15 +18,14 @@ import com.yahoo.container.jdisc.config.MetricDefaultsConfig;
import com.yahoo.search.config.QrStartConfig;
import com.yahoo.vespa.model.Host;
import com.yahoo.vespa.model.HostResource;
-import com.yahoo.vespa.model.admin.clustercontroller.ClusterControllerContainer;
import com.yahoo.vespa.model.admin.clustercontroller.ClusterControllerClusterVerifier;
+import com.yahoo.vespa.model.admin.clustercontroller.ClusterControllerContainer;
import com.yahoo.vespa.model.container.component.Component;
import com.yahoo.vespa.model.container.docproc.ContainerDocproc;
import com.yahoo.vespa.model.container.search.ContainerSearch;
import com.yahoo.vespa.model.container.search.searchchain.SearchChains;
import org.junit.Test;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.Optional;
@@ -266,48 +265,6 @@ public class ContainerClusterTest {
assertEquals(0, cluster.getAllComponents().stream().map(c -> c.getClassId().getName()).filter(c -> c.equals("com.yahoo.jdisc.http.filter.security.RoutingConfigProvider")).count());
}
- @Test
- public void setsRotationActiveAccordingToDeploymentSpec() {
- String deploymentSpec = "<deployment>\n" +
- " <prod> \n" +
- " <region active='true'>us-north-1</region>\n" +
- " <parallel>\n" +
- " <region active='false'>us-north-2</region>\n" +
- " <region active='true'>us-north-3</region>\n" +
- " </parallel>\n" +
- " <region active='false'>us-north-4</region>\n" +
- " </prod>\n" +
- "</deployment>";
- for (String region : Arrays.asList("us-north-1", "us-north-3")) {
- Container container = containerIn(region, deploymentSpec);
- assertEquals("Region " + region + " is active", "true",
- container.getServicePropertyString("activeRotation"));
- }
- for (String region : Arrays.asList("us-north-2", "us-north-4")) {
- Container container = containerIn(region, deploymentSpec);
- assertEquals("Region " + region + " is inactive", "false",
- container.getServicePropertyString("activeRotation"));
- }
- Container container = containerIn("unknown", deploymentSpec);
- assertEquals("Unknown region is inactive", "false",
- container.getServicePropertyString("activeRotation"));
- }
-
- private static Container containerIn(String regionName, String deploymentSpec) {
- ApplicationPackage applicationPackage = new MockApplicationPackage.Builder()
- .withDeploymentSpec(deploymentSpec)
- .build();
- DeployState state = new DeployState.Builder()
- .applicationPackage(applicationPackage)
- .properties(new DeployProperties.Builder().hostedVespa(true).zone(
- new Zone(Environment.prod, RegionName.from(regionName))).build()
- )
- .build();
- MockRoot root = new MockRoot("foo", state);
- ContainerCluster cluster = new ContainerCluster(root, "container0", "container1");
- addContainer(cluster, "c1", "c1.domain");
- return cluster.getContainers().get(0);
- }
private static void addContainer(ContainerCluster cluster, String name, String hostName) {
Container container = new Container(cluster, name, 0);
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java
index 0e6bce73867..d09211aea45 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java
@@ -26,7 +26,6 @@ import com.yahoo.container.servlet.ServletConfigConfig;
import com.yahoo.container.usability.BindingsOverviewHandler;
import com.yahoo.jdisc.http.ServletPathsConfig;
import com.yahoo.prelude.cluster.QrMonitorConfig;
-import static com.yahoo.vespa.defaults.Defaults.getDefaults;
import com.yahoo.vespa.model.AbstractService;
import com.yahoo.vespa.model.VespaModel;
import com.yahoo.vespa.model.container.Container;
@@ -46,6 +45,7 @@ import java.util.Map;
import java.util.logging.Level;
import static com.yahoo.test.LinePatternMatcher.containsLineWithPattern;
+import static com.yahoo.vespa.defaults.Defaults.getDefaults;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.nullValue;
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/IdentityBuilderTest.java b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/IdentityBuilderTest.java
index df118b0e349..d3ad2ccc721 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/IdentityBuilderTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/IdentityBuilderTest.java
@@ -1,9 +1,12 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.model.container.xml;
+import com.yahoo.config.application.api.ApplicationPackage;
import com.yahoo.config.model.builder.xml.test.DomBuilderTest;
+import com.yahoo.config.model.deploy.DeployState;
+import com.yahoo.config.model.test.MockApplicationPackage;
import com.yahoo.container.core.identity.IdentityConfig;
-import com.yahoo.vespa.model.container.Identity;
+import com.yahoo.vespa.model.container.IdentityProvider;
import org.junit.Test;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
@@ -17,17 +20,23 @@ import static org.junit.Assert.assertEquals;
*/
public class IdentityBuilderTest extends ContainerModelBuilderTestBase {
@Test
- public void identity_config_produced() throws IOException, SAXException {
+ public void identity_config_produced_from_deployment_spec() throws IOException, SAXException {
Element clusterElem = DomBuilderTest.parse(
- "<jdisc id='default' version='1.0'>",
- " <identity>",
- " <domain>domain</domain>",
- " <service>service</service>",
- " </identity>",
- "</jdisc>");
+ "<jdisc id='default' version='1.0'><search /></jdisc>");
+ String deploymentXml = "<deployment version='1.0' athenz-domain='domain' athenz-service='service'>\n" +
+ " <test/>\n" +
+ " <prod>\n" +
+ " <region active='true'>default</region>\n" +
+ " </prod>\n" +
+ "</deployment>\n";
- createModel(root, clusterElem);
- IdentityConfig identityConfig = root.getConfig(IdentityConfig.class, "default/component/" + Identity.CLASS);
+ ApplicationPackage applicationPackage = new MockApplicationPackage.Builder()
+ .withDeploymentSpec(deploymentXml)
+ .build();
+
+ createModel(root, DeployState.createTestState(applicationPackage), clusterElem);
+
+ IdentityConfig identityConfig = root.getConfig(IdentityConfig.class, "default/component/" + IdentityProvider.CLASS);
assertEquals("domain", identityConfig.domain());
assertEquals("service", identityConfig.service());
}
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/RoutingBuilderTest.java b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/RoutingBuilderTest.java
new file mode 100644
index 00000000000..a2f32694340
--- /dev/null
+++ b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/RoutingBuilderTest.java
@@ -0,0 +1,78 @@
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.model.container.xml;
+
+import com.yahoo.config.application.api.ApplicationPackage;
+import com.yahoo.config.model.builder.xml.test.DomBuilderTest;
+import com.yahoo.config.model.deploy.DeployState;
+import com.yahoo.config.model.test.MockApplicationPackage;
+import com.yahoo.config.model.test.MockRoot;
+import com.yahoo.config.provision.Environment;
+import com.yahoo.config.provision.RegionName;
+import com.yahoo.config.provision.Zone;
+import com.yahoo.vespa.model.container.Container;
+import com.yahoo.vespa.model.container.ContainerCluster;
+import org.junit.Test;
+import org.w3c.dom.Element;
+import org.xml.sax.SAXException;
+
+import java.io.IOException;
+import java.util.Arrays;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author mortent
+ */
+public class RoutingBuilderTest extends ContainerModelBuilderTestBase {
+
+ @Test
+ public void setsRotationActiveAccordingToDeploymentSpec() throws IOException, SAXException {
+ Element clusterElem = DomBuilderTest.parse(
+ "<jdisc id='default' version='1.0'><search /></jdisc>");
+
+ String deploymentSpec = "<deployment>\n" +
+ " <prod> \n" +
+ " <region active='true'>us-north-1</region>\n" +
+ " <parallel>\n" +
+ " <region active='false'>us-north-2</region>\n" +
+ " <region active='true'>us-north-3</region>\n" +
+ " </parallel>\n" +
+ " <region active='false'>us-north-4</region>\n" +
+ " </prod>\n" +
+ "</deployment>";
+
+ ApplicationPackage applicationPackage = new MockApplicationPackage.Builder()
+ .withDeploymentSpec(deploymentSpec)
+ .build();
+ //root = new MockRoot("root", applicationPackage);
+ for (String region : Arrays.asList("us-north-1", "us-north-3")) {
+ Container container = getContainer(applicationPackage, region, clusterElem);
+
+ assertEquals("Region " + region + " is active", "true",
+ container.getServicePropertyString("activeRotation"));
+ }
+ for (String region : Arrays.asList("us-north-2", "us-north-4")) {
+ Container container = getContainer(applicationPackage, region, clusterElem);
+
+ assertEquals("Region " + region + " is inactive", "false",
+ container.getServicePropertyString("activeRotation"));
+ }
+ Container container = getContainer(applicationPackage, "unknown", clusterElem);
+ assertEquals("Unknown region is inactive", "false",
+ container.getServicePropertyString("activeRotation"));
+ }
+
+
+ private Container getContainer(ApplicationPackage applicationPackage, String region, Element clusterElem) throws IOException, SAXException {
+ DeployState deployState = new DeployState.Builder()
+ .applicationPackage(applicationPackage)
+ .zone(new Zone(Environment.prod, RegionName.from(region)))
+ .build();
+
+ root = new MockRoot("root", deployState);
+ createModel(root, deployState, clusterElem);
+ ContainerCluster cluster = getContainerCluster("default");
+ return cluster.getContainers().get(0);
+
+ }
+}
diff --git a/config-model/src/test/schema-test-files/deployment.xml b/config-model/src/test/schema-test-files/deployment.xml
index f469d22b6f0..f9a62eb648f 100644
--- a/config-model/src/test/schema-test-files/deployment.xml
+++ b/config-model/src/test/schema-test-files/deployment.xml
@@ -1,12 +1,12 @@
<!-- Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
-<deployment version='1.0'>
+<deployment version='1.0' athenz-domain='vespa' athenz-service='service'>
<upgrade policy='canary'/>
<test/>
<staging/>
<block-change revision='true' version='false' days="mon,tue" hours="14,15"/>
<block-change days="mon,tue" hours="14,15" time-zone="CET"/>
<block-upgrade days="wed" hours="16" time-zone="CET"/><!-- Tests legacy name. Remove in Vespa 7 -->
- <prod global-service-id='qrs'>
+ <prod global-service-id='qrs' athenz-service='other-service'>
<region active='true'>us-west-1</region>
<delay hours='3'/>
<region active='true'>us-central-1</region>
diff --git a/config-model/src/test/schema-test-files/services.xml b/config-model/src/test/schema-test-files/services.xml
index 98637c03020..a02346193cc 100644
--- a/config-model/src/test/schema-test-files/services.xml
+++ b/config-model/src/test/schema-test-files/services.xml
@@ -35,10 +35,6 @@
</config>
<jdisc id='qrsCluster_1' version='1.0'>
- <identity>
- <domain>mydomain</domain>
- <service>myservice</service>
- </identity>
<rest-api path="jersey1">
<components bundle="my-bundle" />
<components bundle="other-bundle">
diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/AthenzDomain.java b/config-provisioning/src/main/java/com/yahoo/config/provision/AthenzDomain.java
new file mode 100644
index 00000000000..193a02ccf26
--- /dev/null
+++ b/config-provisioning/src/main/java/com/yahoo/config/provision/AthenzDomain.java
@@ -0,0 +1,42 @@
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.config.provision;
+
+/**
+ * @author mortent
+ */
+public class AthenzDomain {
+
+ private final String name;
+
+ private AthenzDomain(String name) {
+ this.name = name;
+ }
+
+ public static AthenzDomain from(String value) {
+ return new AthenzDomain(value);
+ }
+
+ public String value() { return name; }
+
+ @Override
+ public String toString() {
+ return "AthenzDomain{" +
+ "name='" + name + '\'' +
+ '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ AthenzDomain that = (AthenzDomain) o;
+
+ return name != null ? name.equals(that.name) : that.name == null;
+ }
+
+ @Override
+ public int hashCode() {
+ return name != null ? name.hashCode() : 0;
+ }
+}
diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/AthenzService.java b/config-provisioning/src/main/java/com/yahoo/config/provision/AthenzService.java
new file mode 100644
index 00000000000..54f2889d95c
--- /dev/null
+++ b/config-provisioning/src/main/java/com/yahoo/config/provision/AthenzService.java
@@ -0,0 +1,42 @@
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.config.provision;
+
+/**
+ * @author mortent
+ */
+public class AthenzService {
+
+ private final String name;
+
+ private AthenzService(String name) {
+ this.name = name;
+ }
+
+ public String value() { return name; }
+
+ public static AthenzService from(String value) {
+ return new AthenzService(value);
+ }
+
+ @Override
+ public String toString() {
+ return "AthenzService{" +
+ "name='" + name + '\'' +
+ '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ AthenzService that = (AthenzService) o;
+
+ return name != null ? name.equals(that.name) : that.name == null;
+ }
+
+ @Override
+ public int hashCode() {
+ return name != null ? name.hashCode() : 0;
+ }
+}
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/CompressedApplicationInputStreamTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/CompressedApplicationInputStreamTest.java
index 5d23f1a4556..ddd29f96695 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/CompressedApplicationInputStreamTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/CompressedApplicationInputStreamTest.java
@@ -1,8 +1,8 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.config.server.http;
+import com.google.common.collect.ImmutableList;
import com.google.common.io.ByteStreams;
-import com.yahoo.vespa.config.server.http.CompressedApplicationInputStream;
import org.apache.commons.compress.archivers.ArchiveOutputStream;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
@@ -10,16 +10,19 @@ import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.junit.Test;
-import java.io.*;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
/**
* @author lulf
@@ -37,6 +40,7 @@ public class CompressedApplicationInputStreamTest {
File app = new File("src/test/resources/deploy/validapp");
writeFileToTar(taos, new File(app, "services.xml"));
writeFileToTar(taos, new File(app, "hosts.xml"));
+ writeFileToTar(taos, new File(app, "deployment.xml"));
taos.close();
return outFile;
}
@@ -55,14 +59,8 @@ public class CompressedApplicationInputStreamTest {
void assertTestApp(File outApp) {
String [] files = outApp.list();
- assertThat(files.length, is(2));
- if ("hosts.xml".equals(files[0])) {
- assertThat(files[1], is("services.xml"));
- } else if ("hosts.xml".equals(files[1])) {
- assertThat(files[0], is("services.xml"));
- } else {
- fail("Both services.xml and hosts.xml should be contained in the unpacked application");
- }
+ assertThat(files.length, is(3));
+ assertThat(Arrays.asList(files), containsInAnyOrder(ImmutableList.of(is("hosts.xml"), is("services.xml"), is("deployment.xml"))));
}
@Test
@@ -88,6 +86,10 @@ public class CompressedApplicationInputStreamTest {
archiveOutputStream.putArchiveEntry(archiveOutputStream.createArchiveEntry(file, "application/" + file.getName()));
ByteStreams.copy(new FileInputStream(file), archiveOutputStream);
archiveOutputStream.closeArchiveEntry();
+ file = new File(app, "deployment.xml");
+ archiveOutputStream.putArchiveEntry(archiveOutputStream.createArchiveEntry(file, "application/" + file.getName()));
+ ByteStreams.copy(new FileInputStream(file), archiveOutputStream);
+ archiveOutputStream.closeArchiveEntry();
archiveOutputStream.close();
@@ -134,9 +136,10 @@ public class CompressedApplicationInputStreamTest {
new TarArchiveInputStream(new GZIPInputStream(new FileInputStream(gzFile))));
File outApp = unpacked.decompress();
List<File> files = Arrays.asList(outApp.listFiles());
- assertThat(files.size(), is(4));
+ assertThat(files.size(), is(5));
assertTrue(files.contains(new File(outApp, "services.xml")));
assertTrue(files.contains(new File(outApp, "hosts.xml")));
+ assertTrue(files.contains(new File(outApp, "deployment.xml")));
assertTrue(files.contains(new File(outApp, "searchdefinitions")));
assertTrue(files.contains(new File(outApp, "external")));
File sd = files.get(files.indexOf(new File(outApp, "searchdefinitions")));
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionCreateHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionCreateHandlerTest.java
index 7fe7b350734..310342e81f1 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionCreateHandlerTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionCreateHandlerTest.java
@@ -3,11 +3,11 @@ package com.yahoo.vespa.config.server.http.v2;
import com.yahoo.cloud.config.ConfigserverConfig;
import com.yahoo.config.model.application.provider.FilesApplicationPackage;
+import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.TenantName;
import com.yahoo.container.jdisc.HttpRequest;
import com.yahoo.container.jdisc.HttpResponse;
import com.yahoo.container.logging.AccessLog;
-import com.yahoo.config.provision.ApplicationId;
import com.yahoo.vespa.config.server.ApplicationRepository;
import com.yahoo.vespa.config.server.application.MemoryTenantApplications;
import com.yahoo.vespa.config.server.application.TenantApplications;
@@ -15,24 +15,33 @@ import com.yahoo.vespa.config.server.http.CompressedApplicationInputStreamTest;
import com.yahoo.vespa.config.server.http.HandlerTest;
import com.yahoo.vespa.config.server.http.HttpErrorResponse;
import com.yahoo.vespa.config.server.http.SessionHandlerTest;
-import com.yahoo.vespa.config.server.session.*;
+import com.yahoo.vespa.config.server.session.LocalSessionRepo;
+import com.yahoo.vespa.config.server.session.SessionFactory;
import com.yahoo.vespa.config.server.tenant.Tenants;
-import com.yahoo.vespa.curator.mock.MockCurator;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
-import java.io.*;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
import java.time.Clock;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
-import static com.yahoo.jdisc.Response.Status.*;
+import static com.yahoo.jdisc.Response.Status.BAD_REQUEST;
+import static com.yahoo.jdisc.Response.Status.INTERNAL_SERVER_ERROR;
+import static com.yahoo.jdisc.Response.Status.METHOD_NOT_ALLOWED;
+import static com.yahoo.jdisc.Response.Status.OK;
+import static com.yahoo.jdisc.http.HttpRequest.Method.GET;
+import static com.yahoo.jdisc.http.HttpRequest.Method.POST;
import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.*;
-
-import static com.yahoo.jdisc.http.HttpRequest.Method.*;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
/**
* @author hmusum
@@ -168,7 +177,7 @@ public class SessionCreateHandlerTest extends SessionHandlerTest {
assertTrue(applicationPackage.exists());
final File[] files = applicationPackage.listFiles();
assertNotNull(files);
- assertThat(files.length, is(2));
+ assertThat(files.length, is(3));
}
@Test
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/model/LbServicesProducerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/model/LbServicesProducerTest.java
index 474b93f6972..df8ed405fe3 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/model/LbServicesProducerTest.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/model/LbServicesProducerTest.java
@@ -88,8 +88,9 @@ public class LbServicesProducerTest {
private LbServicesConfig createModelAndGetLbServicesConfig(RegionName regionName) throws IOException, SAXException {
final Zone zone = new Zone(Environment.prod, regionName);
- Map<TenantName, Map<ApplicationId, ApplicationInfo>> testModel = createTestModel(new DeployState.Builder().
- properties(new DeployProperties.Builder().zone(zone).build()));
+ Map<TenantName, Map<ApplicationId, ApplicationInfo>> testModel = createTestModel(new DeployState.Builder()
+ .properties(new DeployProperties.Builder().zone(zone).build())
+ .zone(zone));
return getLbServicesConfig(new Zone(Environment.prod, regionName), testModel);
}
diff --git a/configserver/src/test/resources/deploy/advancedapp/deployment.xml b/configserver/src/test/resources/deploy/advancedapp/deployment.xml
new file mode 100644
index 00000000000..fa1d1388e67
--- /dev/null
+++ b/configserver/src/test/resources/deploy/advancedapp/deployment.xml
@@ -0,0 +1 @@
+<deployment version='1.0'/> \ No newline at end of file
diff --git a/configserver/src/test/resources/deploy/app/deployment.xml b/configserver/src/test/resources/deploy/app/deployment.xml
new file mode 100644
index 00000000000..fa1d1388e67
--- /dev/null
+++ b/configserver/src/test/resources/deploy/app/deployment.xml
@@ -0,0 +1 @@
+<deployment version='1.0'/> \ No newline at end of file
diff --git a/configserver/src/test/resources/deploy/validapp/deployment.xml b/configserver/src/test/resources/deploy/validapp/deployment.xml
new file mode 100644
index 00000000000..fa1d1388e67
--- /dev/null
+++ b/configserver/src/test/resources/deploy/validapp/deployment.xml
@@ -0,0 +1 @@
+<deployment version='1.0'/> \ No newline at end of file