diff options
author | Martin Polden <mpolden@mpolden.no> | 2023-10-02 14:42:38 +0200 |
---|---|---|
committer | Martin Polden <mpolden@mpolden.no> | 2023-10-03 13:16:30 +0200 |
commit | abf4038a8a7c9ccbd659a886d48a9a7ab266e495 (patch) | |
tree | 49b36900c1b231e17fb32cfd7db02bf4cf9d3c2e | |
parent | c96c5dd1b6c50d89c5df73a0e36b1c9f7b003e7c (diff) |
Mark old endpoints as legacy if generated exist
6 files changed, 48 insertions, 19 deletions
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/RoutingController.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/RoutingController.java index b1ffce65852..90c4a506f10 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/RoutingController.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/RoutingController.java @@ -197,19 +197,22 @@ public class RoutingController { /** Returns the zone- and region-scoped endpoints of given deployment */ public EndpointList endpointsOf(DeploymentId deployment, ClusterSpec.Id cluster, GeneratedEndpointList generatedEndpoints) { requireGeneratedEndpoints(generatedEndpoints, false); + boolean generatedEndpointsAvailable = !generatedEndpoints.isEmpty(); boolean tokenSupported = !generatedEndpoints.authMethod(AuthMethod.token).isEmpty(); - RoutingMethod routingMethod = controller.zoneRegistry().routingMethod(deployment.zoneId()); boolean isProduction = deployment.zoneId().environment().isProduction(); + RoutingMethod routingMethod = controller.zoneRegistry().routingMethod(deployment.zoneId()); List<Endpoint> endpoints = new ArrayList<>(); Endpoint.EndpointBuilder zoneEndpoint = Endpoint.of(deployment.applicationId()) .routingMethod(routingMethod) .on(Port.fromRoutingMethod(routingMethod)) + .legacy(generatedEndpointsAvailable) .target(cluster, deployment); endpoints.add(zoneEndpoint.in(controller.system())); ZoneApi zone = controller.zoneRegistry().zones().all().get(deployment.zoneId()).get(); Endpoint.EndpointBuilder regionEndpoint = Endpoint.of(deployment.applicationId()) .routingMethod(routingMethod) .on(Port.fromRoutingMethod(routingMethod)) + .legacy(generatedEndpointsAvailable) .targetRegion(cluster, zone.getCloudNativeRegionName(), zone.getCloudName()); @@ -226,12 +229,14 @@ public class RoutingController { }; if (include) { endpoints.add(zoneEndpoint.generatedFrom(generatedEndpoint) + .legacy(false) .authMethod(generatedEndpoint.authMethod()) .in(controller.system())); // Only a single region endpoint is needed, not one per auth method if (isProduction && generatedEndpoint.authMethod() == AuthMethod.mtls) { GeneratedEndpoint weightedGeneratedEndpoint = generatedEndpoint.withClusterPart(weightedClusterPart(cluster, deployment)); endpoints.add(regionEndpoint.generatedFrom(weightedGeneratedEndpoint) + .legacy(false) .authMethod(AuthMethod.none) .in(controller.system())); } @@ -257,6 +262,7 @@ public class RoutingController { var endpoints = new ArrayList<Endpoint>(); var directMethods = 0; var availableRoutingMethods = routingMethodsOfAll(deployments); + boolean generatedEndpointsAvailable = !generatedEndpoints.isEmpty(); for (var method : availableRoutingMethods) { if (method.isDirect() && ++directMethods > 1) { throw new IllegalArgumentException("Invalid routing methods for " + routingId + ": Exceeded maximum " + @@ -265,10 +271,11 @@ public class RoutingController { Endpoint.EndpointBuilder builder = Endpoint.of(routingId.instance()) .target(routingId.endpointId(), cluster, deployments) .on(Port.fromRoutingMethod(method)) + .legacy(generatedEndpointsAvailable) .routingMethod(method); endpoints.add(builder.in(controller.system())); for (var ge : generatedEndpoints) { - endpoints.add(builder.generatedFrom(ge).authMethod(ge.authMethod()).in(controller.system())); + endpoints.add(builder.generatedFrom(ge).legacy(false).authMethod(ge.authMethod()).in(controller.system())); } } return filterEndpoints(routingId.instance(), EndpointList.copyOf(endpoints)); @@ -280,16 +287,18 @@ public class RoutingController { requireGeneratedEndpoints(generatedEndpoints, true); ZoneId zone = deployments.keySet().iterator().next().zoneId(); // Where multiple zones are possible, they all have the same routing method. RoutingMethod routingMethod = usesSharedRouting(zone) ? RoutingMethod.sharedLayer4 : RoutingMethod.exclusive; + boolean generatedEndpointsAvailable = !generatedEndpoints.isEmpty(); Endpoint.EndpointBuilder builder = Endpoint.of(application) .targetApplication(endpoint, cluster, deployments) .routingMethod(routingMethod) + .legacy(generatedEndpointsAvailable) .on(Port.fromRoutingMethod(routingMethod)); List<Endpoint> endpoints = new ArrayList<>(); endpoints.add(builder.in(controller.system())); for (var ge : generatedEndpoints) { - endpoints.add(builder.generatedFrom(ge).authMethod(ge.authMethod()).in(controller.system())); + endpoints.add(builder.generatedFrom(ge).legacy(false).authMethod(ge.authMethod()).in(controller.system())); } return EndpointList.copyOf(endpoints); } diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/Endpoint.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/Endpoint.java index 5c6611f80c3..2c13a7ddb11 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/Endpoint.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/Endpoint.java @@ -122,7 +122,7 @@ public class Endpoint { return scope; } - /** Returns whether this is considered a legacy DNS name that is due for removal */ + /** Returns whether this is considered a legacy DNS name intended to be removed at some point */ public boolean legacy() { return legacy; } @@ -557,9 +557,9 @@ public class Endpoint { return this; } - /** Marks this as a legacy endpoint */ - public EndpointBuilder legacy() { - this.legacy = true; + /** Set whether this is a legacy endpoint */ + public EndpointBuilder legacy(boolean legacy) { + this.legacy = legacy; return this; } diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/EndpointList.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/EndpointList.java index 310a78e45f0..6e8cd16336a 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/EndpointList.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/EndpointList.java @@ -28,11 +28,6 @@ public class EndpointList extends AbstractFilteringList<Endpoint, EndpointList> } } - /** Returns the primary (non-legacy) endpoint, if any */ - public Optional<Endpoint> primary() { - return not().legacy().asList().stream().findFirst(); - } - /** Returns the subset of endpoints named according to given ID and scope */ public EndpointList named(EndpointId id, Endpoint.Scope scope) { return matching(endpoint -> endpoint.scope() == scope && // ID is only unique within a scope diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java index 577cc737691..5809cc9b7c6 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java @@ -2237,7 +2237,7 @@ public class ApplicationApiHandler extends AuditLoggingRequestHandler { Cursor array = slime.setObject().setArray("globalrotationoverride"); Optional<Endpoint> primaryEndpoint = controller.routing().readDeclaredEndpointsOf(deploymentId.applicationId()) .requiresRotation() - .primary(); + .first(); if (primaryEndpoint.isPresent()) { DeploymentRoutingContext context = controller.routing().of(deploymentId); RoutingStatus status = context.routingStatus(); diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/routing/RoutingPoliciesTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/routing/RoutingPoliciesTest.java index b2b34441219..22523103208 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/routing/RoutingPoliciesTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/routing/RoutingPoliciesTest.java @@ -141,6 +141,13 @@ public class RoutingPoliciesTest { assertEquals(numberOfDeployments * clustersPerZone, tester.policiesOf(context1.instance().id()).size(), "Routing policy count is equal to cluster count"); + assertEquals(List.of(), + tester.controllerTester().controller().routing() + .readDeclaredEndpointsOf(context1.instanceId()) + .scope(Endpoint.Scope.zone) + .legacy() + .asList(), + "No endpoints marked as legacy"); // Applications gains a new deployment ApplicationPackage applicationPackage2 = applicationPackageBuilder() @@ -305,6 +312,13 @@ public class RoutingPoliciesTest { ); assertEquals(expectedRecords, tester.recordNames()); assertEquals(4, tester.policiesOf(context1.instanceId()).size()); + assertEquals(List.of(), + tester.controllerTester().controller().routing() + .readEndpointsOf(context1.deploymentIdIn(zone1)) + .scope(Endpoint.Scope.zone) + .legacy() + .asList(), + "No endpoints marked as legacy"); // Next deploy does nothing context1.submit(applicationPackage).deferLoadBalancerProvisioningIn(Environment.prod).deploy(); @@ -1107,16 +1121,27 @@ public class RoutingPoliciesTest { assertEquals(6, tester.policiesOf(context.instanceId()).size()); ClusterSpec.Id cluster0 = ClusterSpec.Id.from("c0"); ClusterSpec.Id cluster1 = ClusterSpec.Id.from("c1"); + // The expected number of endpoints are created for (var zone : List.of(zone1, zone2)) { - EndpointList generated = tester.controllerTester().controller().routing() - .readEndpointsOf(context.deploymentIdIn(zone)) - .scope(Endpoint.Scope.zone) - .generated(); + EndpointList zoneEndpoints = tester.controllerTester().controller().routing() + .readEndpointsOf(context.deploymentIdIn(zone)) + .scope(Endpoint.Scope.zone); + EndpointList generated = zoneEndpoints.generated(); assertEquals(1, generated.cluster(cluster0).size()); assertEquals(0, generated.cluster(cluster0).authMethod(AuthMethod.token).size()); assertEquals(2, generated.cluster(cluster1).size()); assertEquals(1, generated.cluster(cluster1).authMethod(AuthMethod.token).size()); + EndpointList legacy = zoneEndpoints.legacy(); + assertEquals(1, legacy.cluster(cluster0).size()); + assertEquals(0, legacy.cluster(cluster0).authMethod(AuthMethod.token).size()); + assertEquals(1, legacy.cluster(cluster1).size()); + assertEquals(0, legacy.cluster(cluster1).authMethod(AuthMethod.token).size()); } + EndpointList declaredEndpoints = tester.controllerTester().controller().routing().readDeclaredEndpointsOf(context.application()); + assertEquals(1, declaredEndpoints.scope(Endpoint.Scope.global).generated().size()); + assertEquals(1, declaredEndpoints.scope(Endpoint.Scope.global).legacy().size()); + assertEquals(1, declaredEndpoints.scope(Endpoint.Scope.application).generated().size()); + assertEquals(1, declaredEndpoints.scope(Endpoint.Scope.application).legacy().size()); Map<DeploymentId, Set<ContainerEndpoint>> containerEndpointsInProd = tester.containerEndpoints(Environment.prod); // Ordinary endpoints point to expected targets @@ -1555,7 +1580,7 @@ public class RoutingPoliciesTest { } else { global = global.not().generated(); } - String globalEndpoint = global.primary() + String globalEndpoint = global.first() .map(Endpoint::dnsName) .orElse("<none>"); assertEquals(latencyTargets, Set.copyOf(aliasDataOf(globalEndpoint)), "Global endpoint " + globalEndpoint + " points to expected latency targets"); diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/routing/rotation/RotationRepositoryTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/routing/rotation/RotationRepositoryTest.java index 6190680d098..e053e432862 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/routing/rotation/RotationRepositoryTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/routing/rotation/RotationRepositoryTest.java @@ -146,7 +146,7 @@ public class RotationRepositoryTest { application2.submit(applicationPackage).deploy(); assertEquals(List.of(new RotationId("foo-1")), rotationIds(application2.instance().rotations())); assertEquals("https://cd.app2.tenant2.global.cd.vespa.oath.cloud/", - tester.controller().routing().readDeclaredEndpointsOf(application2.instanceId()).primary().get().url().toString()); + tester.controller().routing().readDeclaredEndpointsOf(application2.instanceId()).first().get().url().toString()); } @Test |