aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Polden <mpolden@mpolden.no>2023-10-02 14:42:38 +0200
committerMartin Polden <mpolden@mpolden.no>2023-10-03 13:16:30 +0200
commitabf4038a8a7c9ccbd659a886d48a9a7ab266e495 (patch)
tree49b36900c1b231e17fb32cfd7db02bf4cf9d3c2e
parentc96c5dd1b6c50d89c5df73a0e36b1c9f7b003e7c (diff)
Mark old endpoints as legacy if generated exist
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/RoutingController.java15
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/Endpoint.java8
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/EndpointList.java5
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java2
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/routing/RoutingPoliciesTest.java35
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/routing/rotation/RotationRepositoryTest.java2
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