diff options
author | Morten Tokle <mortent@verizonmedia.com> | 2021-11-26 14:44:45 +0100 |
---|---|---|
committer | Morten Tokle <mortent@verizonmedia.com> | 2021-11-26 14:44:45 +0100 |
commit | 693fc5f9ec179eb0d4b7b3cb749aff15403c0c75 (patch) | |
tree | 7666151e2af47b2149d3f2f80b8da749390a939c | |
parent | 59850885588f1f4e75a3eaf115da9a3c0d02c9eb (diff) |
Use routingMethod from controller
6 files changed, 74 insertions, 27 deletions
diff --git a/config-model-api/src/main/java/com/yahoo/config/model/api/ApplicationClusterEndpoint.java b/config-model-api/src/main/java/com/yahoo/config/model/api/ApplicationClusterEndpoint.java index f6583468322..10effd47707 100644 --- a/config-model-api/src/main/java/com/yahoo/config/model/api/ApplicationClusterEndpoint.java +++ b/config-model-api/src/main/java/com/yahoo/config/model/api/ApplicationClusterEndpoint.java @@ -112,6 +112,11 @@ public class ApplicationClusterEndpoint { return this; } + public Builder routingMethod(RoutingMethod routingMethod) { + this.routingMethod = routingMethod; + return this; + } + public Builder weight(int weigth) { this.weigth = weigth; return this; diff --git a/config-model-api/src/main/java/com/yahoo/config/model/api/ContainerEndpoint.java b/config-model-api/src/main/java/com/yahoo/config/model/api/ContainerEndpoint.java index cd31eb2a49a..78da750fb5b 100644 --- a/config-model-api/src/main/java/com/yahoo/config/model/api/ContainerEndpoint.java +++ b/config-model-api/src/main/java/com/yahoo/config/model/api/ContainerEndpoint.java @@ -20,16 +20,22 @@ public class ContainerEndpoint { private final ApplicationClusterEndpoint.Scope scope; private final List<String> names; private final OptionalInt weight; + private final ApplicationClusterEndpoint.RoutingMethod routingMethod; public ContainerEndpoint(String clusterId, ApplicationClusterEndpoint.Scope scope, List<String> names) { this(clusterId, scope, names, OptionalInt.empty()); } public ContainerEndpoint(String clusterId, ApplicationClusterEndpoint.Scope scope, List<String> names, OptionalInt weight) { + this(clusterId, scope, names, weight, ApplicationClusterEndpoint.RoutingMethod.sharedLayer4); + } + + public ContainerEndpoint(String clusterId, ApplicationClusterEndpoint.Scope scope, List<String> names, OptionalInt weight, ApplicationClusterEndpoint.RoutingMethod routingMethod) { this.clusterId = Objects.requireNonNull(clusterId); this.scope = Objects.requireNonNull(scope); this.names = List.copyOf(Objects.requireNonNull(names)); this.weight = weight; + this.routingMethod = routingMethod; } public String clusterId() { @@ -48,6 +54,10 @@ public class ContainerEndpoint { return weight; } + public ApplicationClusterEndpoint.RoutingMethod routingMethod() { + return routingMethod; + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -55,17 +65,18 @@ public class ContainerEndpoint { ContainerEndpoint that = (ContainerEndpoint) o; return Objects.equals(clusterId, that.clusterId) && Objects.equals(scope, that.scope) && - Objects.equals(names, that.names); + Objects.equals(names, that.names) && + Objects.equals(weight, that.weight) && + Objects.equals(routingMethod, that.routingMethod); } @Override public int hashCode() { - return Objects.hash(clusterId, names, scope); + return Objects.hash(clusterId, names, scope, weight, routingMethod); } @Override public String toString() { - return String.format("container endpoint %s -> %s [scope=%s]", clusterId, names, scope); + return String.format("container endpoint %s -> %s [scope=%s, weight=%s, routingMetod=%s]", clusterId, names, scope, weight, routingMethod); } - } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/ApplicationContainerCluster.java b/config-model/src/main/java/com/yahoo/vespa/model/container/ApplicationContainerCluster.java index f6a0eb9ce8d..d47cddcdf96 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/ApplicationContainerCluster.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/ApplicationContainerCluster.java @@ -237,7 +237,7 @@ public final class ApplicationContainerCluster extends ContainerCluster<Applicat .build()); } - // Then get all endpoints provided by controller. Can be created with L4 routing only + // Then get all endpoints provided by controller. Set<ContainerEndpoint> endpointsFromController = deployState.getEndpoints(); endpointsFromController.stream() .filter(ce -> ce.clusterId().equals(getName())) @@ -245,7 +245,7 @@ public final class ApplicationContainerCluster extends ContainerCluster<Applicat name -> endpoints.add(ApplicationClusterEndpoint.builder() .scope(ce.scope()) .weight(Long.valueOf(ce.weight().orElse(1)).intValue()) // Default to weight=1 if not set - .sharedL4Routing() + .routingMethod(ce.routingMethod()) .dnsName(ApplicationClusterEndpoint.DnsName.from(name)) .hosts(hosts) .clusterId(getName()) 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 87dd91a8a11..a4bfba9e657 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 @@ -44,6 +44,10 @@ import java.util.OptionalLong; import java.util.Set; import java.util.stream.Collectors; +import static com.yahoo.config.model.api.ApplicationClusterEndpoint.RoutingMethod.shared; +import static com.yahoo.config.model.api.ApplicationClusterEndpoint.RoutingMethod.sharedLayer4; +import static com.yahoo.config.model.api.ApplicationClusterEndpoint.Scope.application; +import static com.yahoo.config.model.api.ApplicationClusterEndpoint.Scope.global; import static com.yahoo.config.provision.SystemName.cd; import static com.yahoo.config.provision.SystemName.main; import static org.hamcrest.Matchers.containsInAnyOrder; @@ -366,59 +370,70 @@ public class ContainerClusterTest { assertNames(main, ApplicationId.from("t1", "a1", "i1"), Set.of(), - List.of("search-cluster.i1.a1.t1.endpoint.suffix", "search-cluster--i1--a1--t1.endpoint.suffix")); + List.of("search-cluster.i1.a1.t1.endpoint.suffix"), + List.of("search-cluster--i1--a1--t1.endpoint.suffix")); assertNames(main, ApplicationId.from("t1", "a1", "default"), Set.of(), - List.of("search-cluster.a1.t1.endpoint.suffix", "search-cluster--a1--t1.endpoint.suffix")); + List.of("search-cluster.a1.t1.endpoint.suffix"), + List.of("search-cluster--a1--t1.endpoint.suffix")); assertNames(main, ApplicationId.from("t1", "default", "default"), Set.of(), - List.of("search-cluster.default.t1.endpoint.suffix", "search-cluster--default--t1.endpoint.suffix")); + List.of("search-cluster.default.t1.endpoint.suffix"), + List.of("search-cluster--default--t1.endpoint.suffix")); assertNames(main, ApplicationId.from("t1", "a1", "default"), - Set.of(new ContainerEndpoint("not-in-this-cluster", ApplicationClusterEndpoint.Scope.global, List.of("foo", "bar"))), - List.of("search-cluster.a1.t1.endpoint.suffix", "search-cluster--a1--t1.endpoint.suffix")); + Set.of(new ContainerEndpoint("not-in-this-cluster", global, List.of("foo", "bar"))), + List.of("search-cluster.a1.t1.endpoint.suffix"), + List.of("search-cluster--a1--t1.endpoint.suffix")); assertNames(main, ApplicationId.from("t1", "a1", "default"), - Set.of(new ContainerEndpoint("search-cluster", ApplicationClusterEndpoint.Scope.global, List.of("rotation-1.x.y.z", "rotation-2.x.y.z")), - new ContainerEndpoint("search-cluster", ApplicationClusterEndpoint.Scope.application, List.of("app-rotation.x.y.z"), OptionalInt.of(3))), - List.of("search-cluster.a1.t1.endpoint.suffix", "search-cluster--a1--t1.endpoint.suffix", "rotation-1.x.y.z", "rotation-2.x.y.z", "app-rotation.x.y.z")); + Set.of(new ContainerEndpoint("search-cluster", global, List.of("rotation-1.x.y.z", "rotation-2.x.y.z"), OptionalInt.empty(), sharedLayer4), + new ContainerEndpoint("search-cluster", application, List.of("app-rotation.x.y.z"), OptionalInt.of(3), sharedLayer4)), + List.of("search-cluster.a1.t1.endpoint.suffix", "rotation-1.x.y.z", "rotation-2.x.y.z", "app-rotation.x.y.z"), + List.of("search-cluster--a1--t1.endpoint.suffix")); // cd system: assertNames(cd, ApplicationId.from("t1", "a1", "i1"), Set.of(), - List.of("search-cluster.cd.i1.a1.t1.endpoint.suffix", "search-cluster--cd--i1--a1--t1.endpoint.suffix")); + List.of("search-cluster.cd.i1.a1.t1.endpoint.suffix"), + List.of("search-cluster--cd--i1--a1--t1.endpoint.suffix")); assertNames(cd, ApplicationId.from("t1", "a1", "default"), Set.of(), - List.of("search-cluster.cd.a1.t1.endpoint.suffix", "search-cluster--cd--a1--t1.endpoint.suffix")); + List.of("search-cluster.cd.a1.t1.endpoint.suffix"), + List.of("search-cluster--cd--a1--t1.endpoint.suffix")); assertNames(cd, ApplicationId.from("t1", "default", "default"), Set.of(), - List.of("search-cluster.cd.default.t1.endpoint.suffix", "search-cluster--cd--default--t1.endpoint.suffix")); + List.of("search-cluster.cd.default.t1.endpoint.suffix"), + List.of("search-cluster--cd--default--t1.endpoint.suffix")); assertNames(cd, ApplicationId.from("t1", "a1", "default"), - Set.of(new ContainerEndpoint("not-in-this-cluster", ApplicationClusterEndpoint.Scope.global, List.of("foo", "bar"))), - List.of("search-cluster.cd.a1.t1.endpoint.suffix", "search-cluster--cd--a1--t1.endpoint.suffix")); + Set.of(new ContainerEndpoint("not-in-this-cluster", global, List.of("foo", "bar"))), + List.of("search-cluster.cd.a1.t1.endpoint.suffix"), + List.of("search-cluster--cd--a1--t1.endpoint.suffix")); assertNames(cd, ApplicationId.from("t1", "a1", "default"), - Set.of(new ContainerEndpoint("search-cluster", ApplicationClusterEndpoint.Scope.global, List.of("rotation-1.x.y.z", "rotation-2.x.y.z")), - new ContainerEndpoint("search-cluster", ApplicationClusterEndpoint.Scope.application, List.of("app-rotation.x.y.z"), OptionalInt.of(3))), - List.of("search-cluster.cd.a1.t1.endpoint.suffix", "search-cluster--cd--a1--t1.endpoint.suffix", "rotation-1.x.y.z", "rotation-2.x.y.z", "app-rotation.x.y.z")); + Set.of(new ContainerEndpoint("search-cluster", global, List.of("rotation-1.x.y.z", "rotation-2.x.y.z"), OptionalInt.empty(), sharedLayer4), + new ContainerEndpoint("search-cluster", global, List.of("a--b.x.y.z", "rotation-2.x.y.z"), OptionalInt.empty(), shared), + new ContainerEndpoint("search-cluster", application, List.of("app-rotation.x.y.z"), OptionalInt.of(3), sharedLayer4)), + List.of("search-cluster.cd.a1.t1.endpoint.suffix", "rotation-1.x.y.z", "rotation-2.x.y.z", "app-rotation.x.y.z"), + List.of("search-cluster--cd--a1--t1.endpoint.suffix", "a--b.x.y.z", "rotation-2.x.y.z")); } - private void assertNames(SystemName systemName, ApplicationId appId, Set<ContainerEndpoint> globalEndpoints, List<String> expectedNames) { + private void assertNames(SystemName systemName, ApplicationId appId, Set<ContainerEndpoint> globalEndpoints, List<String> expectedSharedL4Names, List<String> expectedSharedNames) { Zone zone = new Zone(systemName, Environment.defaultEnvironment(), RegionName.defaultName()); DeployState state = new DeployState.Builder() .zone(zone) @@ -433,8 +448,9 @@ public class ContainerClusterTest { addContainer(root, cluster, "c1", "host-c1"); cluster.doPrepare(state); List<ApplicationClusterEndpoint> endpoints = cluster.endpoints(); - assertEquals(expectedNames.size(), endpoints.size()); - expectedNames.forEach(expected -> assertTrue("Endpoint not matched " + expected + " was: " + endpoints, endpoints.stream().anyMatch(e -> Objects.equals(e.dnsName().value(), expected)))); + + assertNames(expectedSharedNames, endpoints.stream().filter(e -> e.routingMethod() == shared).collect(Collectors.toList())); + assertNames(expectedSharedL4Names, endpoints.stream().filter(e -> e.routingMethod() == sharedLayer4).collect(Collectors.toList())); List<ContainerEndpoint> endpointsWithWeight = globalEndpoints.stream().filter(endpoint -> endpoint.weight().isPresent()).collect(Collectors.toList()); @@ -443,6 +459,11 @@ public class ContainerClusterTest { .forEach(ce -> assertTrue(endpointsMatch(ce, endpoints))); } + private void assertNames(List<String> expectedNames, List<ApplicationClusterEndpoint> endpoints) { + assertEquals(expectedNames.size(), endpoints.size()); + expectedNames.forEach(expected -> assertTrue("Endpoint not matched " + expected + " was: " + endpoints, endpoints.stream().anyMatch(e -> Objects.equals(e.dnsName().value(), expected)))); + } + private boolean endpointsMatch(ContainerEndpoint configuredEndpoint, List<ApplicationClusterEndpoint> clusterEndpoints) { return clusterEndpoints.stream().anyMatch(e -> configuredEndpoint.names().contains(e.dnsName().value()) && diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/ContainerEndpointSerializer.java b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/ContainerEndpointSerializer.java index 121f4397129..b813d56b345 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/ContainerEndpointSerializer.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/ContainerEndpointSerializer.java @@ -31,6 +31,7 @@ public class ContainerEndpointSerializer { private static final String scopeField = "scope"; private static final String namesField = "names"; private static final String weightField = "weight"; + private static final String routingMethodField = "routingMethod"; private ContainerEndpointSerializer() {} @@ -39,6 +40,9 @@ public class ContainerEndpointSerializer { final var scope = inspector.field(scopeField).asString(); final var namesInspector = inspector.field(namesField); final var weight = SlimeUtils.optionalInteger(inspector.field(weightField)); + // assign default routingmethod. Remove when 7.507 is latest version + // Cannot be used before all endpoints are assigned explicit routingmethod (from controller) + final var routingMethod = SlimeUtils.optionalString(inspector.field(routingMethodField)).orElse(ApplicationClusterEndpoint.RoutingMethod.sharedLayer4.name()); if (clusterId.isEmpty()) { throw new IllegalStateException("'clusterId' missing on serialized ContainerEndpoint"); } @@ -51,6 +55,10 @@ public class ContainerEndpointSerializer { throw new IllegalStateException("'names' missing on serialized ContainerEndpoint"); } + if(routingMethod.isEmpty()) { + throw new IllegalStateException("'routingMethod' missing on serialized ContainerEndpoint"); + } + final var names = new ArrayList<String>(); namesInspector.traverse((ArrayTraverser) (idx, nameInspector) -> { @@ -58,7 +66,8 @@ public class ContainerEndpointSerializer { names.add(containerName); }); - return new ContainerEndpoint(clusterId, ApplicationClusterEndpoint.Scope.valueOf(scope), names, weight); + return new ContainerEndpoint(clusterId, ApplicationClusterEndpoint.Scope.valueOf(scope), names, weight, + ApplicationClusterEndpoint.RoutingMethod.valueOf(routingMethod)); } public static List<ContainerEndpoint> endpointListFromSlime(Slime slime) { @@ -83,6 +92,7 @@ public class ContainerEndpointSerializer { endpoint.weight().ifPresent(w -> cursor.setLong(weightField, w)); final var namesInspector = cursor.setArray(namesField); endpoint.names().forEach(namesInspector::addString); + cursor.setString(routingMethodField, endpoint.routingMethod().name()); } public static Slime endpointListToSlime(List<ContainerEndpoint> endpoints) { diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/ContainerEndpointSerializerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/ContainerEndpointSerializerTest.java index 2b746a9c1c6..9f52559e04b 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/ContainerEndpointSerializerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/ContainerEndpointSerializerTest.java @@ -62,7 +62,7 @@ public class ContainerEndpointSerializerTest { @Test public void writeReadEndpoints() { - final var endpoints = List.of(new ContainerEndpoint("foo", ApplicationClusterEndpoint.Scope.global, List.of("a", "b"))); + final var endpoints = List.of(new ContainerEndpoint("foo", ApplicationClusterEndpoint.Scope.global, List.of("a", "b"), OptionalInt.of(3), ApplicationClusterEndpoint.RoutingMethod.shared)); final var serialized = ContainerEndpointSerializer.endpointListToSlime(endpoints); final var deserialized = ContainerEndpointSerializer.endpointListFromSlime(serialized); |