diff options
4 files changed, 25 insertions, 134 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 f4877fe3494..4c50f9b4ab1 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 @@ -211,9 +211,6 @@ public class DeploymentSpec { // to have environment, instance or region variants on those. public Optional<AthenzService> athenzService() { return this.athenzService; } - // TODO: Remove after November 2019 - public List<Endpoint> endpoints() { return singleInstance().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; } diff --git a/config-model-api/src/test/java/com/yahoo/config/application/api/DeploymentSpecDeprecatedAPITest.java b/config-model-api/src/test/java/com/yahoo/config/application/api/DeploymentSpecDeprecatedAPITest.java index 738e4759b0a..317a4224726 100644 --- a/config-model-api/src/test/java/com/yahoo/config/application/api/DeploymentSpecDeprecatedAPITest.java +++ b/config-model-api/src/test/java/com/yahoo/config/application/api/DeploymentSpecDeprecatedAPITest.java @@ -352,118 +352,4 @@ public class DeploymentSpecDeprecatedAPITest { 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>" + - " <prod>" + - " <region active=\"true\">us-east</region>" + - " </prod>" + - " <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", "default"), - 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(RegionName.from("us-east")), spec.endpoints().get(0).regions()); - } - @Test - public void invalidEndpoints() { - assertInvalid("<endpoint id='FOO' container-id='qrs'/>"); // Uppercase - assertInvalid("<endpoint id='123' container-id='qrs'/>"); // Starting with non-character - assertInvalid("<endpoint id='foo!' container-id='qrs'/>"); // Non-alphanumeric - assertInvalid("<endpoint id='foo.bar' container-id='qrs'/>"); - assertInvalid("<endpoint id='foo--bar' container-id='qrs'/>"); // Multiple consecutive dashes - assertInvalid("<endpoint id='foo-' container-id='qrs'/>"); // Trailing dash - assertInvalid("<endpoint id='foooooooooooo' container-id='qrs'/>"); // Too long - assertInvalid("<endpoint id='foo' container-id='qrs'/><endpoint id='foo' container-id='qrs'/>"); // Duplicate - } - - @Test - public void validEndpoints() { - assertEquals(List.of("default"), endpointIds("<endpoint container-id='qrs'/>")); - assertEquals(List.of("default"), endpointIds("<endpoint id='' container-id='qrs'/>")); - assertEquals(List.of("f"), endpointIds("<endpoint id='f' container-id='qrs'/>")); - assertEquals(List.of("foo"), endpointIds("<endpoint id='foo' container-id='qrs'/>")); - assertEquals(List.of("foo-bar"), endpointIds("<endpoint id='foo-bar' container-id='qrs'/>")); - assertEquals(List.of("foo", "bar"), endpointIds("<endpoint id='foo' container-id='qrs'/><endpoint id='bar' container-id='qrs'/>")); - assertEquals(List.of("fooooooooooo"), endpointIds("<endpoint id='fooooooooooo' container-id='qrs'/>")); - } - - @Test - public void endpointDefaultRegions() { - var spec = DeploymentSpec.fromXml("" + - "<deployment>" + - " <prod>" + - " <region active=\"true\">us-east</region>" + - " <region active=\"true\">us-west</region>" + - " </prod>" + - " <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(Set.of("us-east"), endpointRegions("foo", spec)); - assertEquals(Set.of("us-east", "us-west"), endpointRegions("nalle", spec)); - assertEquals(Set.of("us-east", "us-west"), endpointRegions("default", spec)); - } - - private static void assertInvalid(String endpointTag) { - try { - endpointIds(endpointTag); - fail("Expected exception for input '" + endpointTag + "'"); - } catch (IllegalArgumentException ignored) {} - } - - private static Set<String> endpointRegions(String endpointId, DeploymentSpec spec) { - return spec.endpoints().stream() - .filter(endpoint -> endpoint.endpointId().equals(endpointId)) - .flatMap(endpoint -> endpoint.regions().stream()) - .map(RegionName::value) - .collect(Collectors.toSet()); - } - - private static List<String> endpointIds(String endpointTag) { - var xml = "<deployment>" + - " <prod>" + - " <region active=\"true\">us-east</region>" + - " </prod>" + - " <endpoints>" + - endpointTag + - " </endpoints>" + - "</deployment>"; - - return DeploymentSpec.fromXml(xml).endpoints().stream() - .map(Endpoint::endpointId) - .collect(Collectors.toList()); - } - } diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/RoutingPolicies.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/RoutingPolicies.java index d6080bcda6c..98483763a0d 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/RoutingPolicies.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/RoutingPolicies.java @@ -1,6 +1,7 @@ // Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.maintenance; +import com.yahoo.config.application.api.DeploymentInstanceSpec; import com.yahoo.config.application.api.DeploymentSpec; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.zone.ZoneId; @@ -106,19 +107,21 @@ public class RoutingPolicies { private void storePoliciesOf(AllocatedLoadBalancers loadBalancers, DeploymentSpec spec, @SuppressWarnings("unused") Lock lock) { Set<RoutingPolicy> policies = new LinkedHashSet<>(get(loadBalancers.application)); for (LoadBalancer loadBalancer : loadBalancers.list) { - RoutingPolicy policy = createPolicy(loadBalancers.application, spec, loadBalancers.zone, loadBalancer); - if (!policies.add(policy)) { - policies.remove(policy); - policies.add(policy); - } + spec.instance(loadBalancer.application().instance()).ifPresent(instanceSpec -> { + RoutingPolicy policy = createPolicy(loadBalancers.application, instanceSpec, loadBalancers.zone, loadBalancer); + if (!policies.add(policy)) { + policies.remove(policy); + policies.add(policy); + } + }); } db.writeRoutingPolicies(loadBalancers.application, policies); } /** Create a policy for given load balancer and register a CNAME for it */ - private RoutingPolicy createPolicy(ApplicationId application, DeploymentSpec deploymentSpec, ZoneId zone, + private RoutingPolicy createPolicy(ApplicationId application, DeploymentInstanceSpec instanceSpec, ZoneId zone, LoadBalancer loadBalancer) { - var endpoints = endpointIdsOf(loadBalancer, zone, deploymentSpec); + var endpoints = endpointIdsOf(loadBalancer, zone, instanceSpec); var routingPolicy = new RoutingPolicy(application, loadBalancer.cluster(), zone, loadBalancer.hostname(), loadBalancer.dnsZone(), endpoints); @@ -162,9 +165,11 @@ public class RoutingPolicies { private static Set<RoutingId> routingIdsFrom(AllocatedLoadBalancers loadBalancers, DeploymentSpec spec) { Set<RoutingId> routingIds = new LinkedHashSet<>(); for (var loadBalancer : loadBalancers.list) { - for (var endpointId : endpointIdsOf(loadBalancer, loadBalancers.zone, spec)) { - routingIds.add(new RoutingId(loadBalancer.application(), endpointId)); - } + spec.instance(loadBalancer.application().instance()).ifPresent(instanceSpec -> { + for (var endpointId : endpointIdsOf(loadBalancer, loadBalancers.zone, instanceSpec)) { + routingIds.add(new RoutingId(loadBalancer.application(), endpointId)); + } + }); } return Collections.unmodifiableSet(routingIds); } @@ -183,7 +188,7 @@ public class RoutingPolicies { } /** Compute all endpoint IDs of given load balancer */ - private static Set<EndpointId> endpointIdsOf(LoadBalancer loadBalancer, ZoneId zone, DeploymentSpec spec) { + private static Set<EndpointId> endpointIdsOf(LoadBalancer loadBalancer, ZoneId zone, DeploymentInstanceSpec spec) { return spec.endpoints().stream() .filter(endpoint -> endpoint.containerId().equals(loadBalancer.cluster().value())) .filter(endpoint -> endpoint.regions().contains(zone.region())) diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/ApplicationSerializer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/ApplicationSerializer.java index 356a20f6eba..b67feab3f59 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/ApplicationSerializer.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/ApplicationSerializer.java @@ -2,6 +2,7 @@ package com.yahoo.vespa.hosted.controller.persistence; import com.yahoo.component.Version; +import com.yahoo.config.application.api.DeploymentInstanceSpec; import com.yahoo.config.application.api.DeploymentSpec; import com.yahoo.config.application.api.ValidationOverrides; import com.yahoo.config.provision.ClusterSpec; @@ -386,7 +387,7 @@ public class ApplicationSerializer { InstanceName instanceName = InstanceName.from(object.field(instanceNameField).asString()); List<Deployment> deployments = deploymentsFromSlime(object.field(deploymentsField)); DeploymentJobs deploymentJobs = deploymentJobsFromSlime(object.field(deploymentJobsField)); - List<AssignedRotation> assignedRotations = assignedRotationsFromSlime(deploymentSpec, object); + List<AssignedRotation> assignedRotations = assignedRotationsFromSlime(deploymentSpec, instanceName, object); RotationStatus rotationStatus = rotationStatusFromSlime(object); instances.add(new Instance(id.instance(instanceName), deployments, @@ -570,17 +571,19 @@ public class ApplicationSerializer { Instant.ofEpochMilli(object.field(atField).asLong()))); } - private List<AssignedRotation> assignedRotationsFromSlime(DeploymentSpec deploymentSpec, Inspector root) { + private List<AssignedRotation> assignedRotationsFromSlime(DeploymentSpec deploymentSpec, InstanceName instance, Inspector root) { var assignedRotations = new LinkedHashMap<EndpointId, AssignedRotation>(); root.field(assignedRotationsField).traverse((ArrayTraverser) (idx, inspector) -> { var clusterId = new ClusterSpec.Id(inspector.field(assignedRotationClusterField).asString()); var endpointId = EndpointId.of(inspector.field(assignedRotationEndpointField).asString()); var rotationId = new RotationId(inspector.field(assignedRotationRotationField).asString()); - var regions = deploymentSpec.endpoints().stream() - .filter(endpoint -> endpoint.endpointId().equals(endpointId.id())) - .flatMap(endpoint -> endpoint.regions().stream()) - .collect(Collectors.toSet()); + var regions = deploymentSpec.instance(instance) + .map(spec -> spec.endpoints().stream() + .filter(endpoint -> endpoint.endpointId().equals(endpointId.id())) + .flatMap(endpoint -> endpoint.regions().stream()) + .collect(Collectors.toSet())) + .orElse(Set.of()); assignedRotations.putIfAbsent(endpointId, new AssignedRotation(clusterId, endpointId, rotationId, regions)); }); |