diff options
author | Martin Polden <mpolden@mpolden.no> | 2020-06-15 11:36:18 +0200 |
---|---|---|
committer | Martin Polden <mpolden@mpolden.no> | 2020-06-15 13:58:59 +0200 |
commit | f34efe30c2a17ba6fc9b4b80fabd1c612d958bee (patch) | |
tree | 788c3fb2efce219b563e0c10e9d0be6891a3c91e /controller-server | |
parent | f23863f6f7698d4fc34392c59977447988a86754 (diff) |
Add support for config server routing policy
Diffstat (limited to 'controller-server')
6 files changed, 70 insertions, 10 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 463ffb58460..c441188b1be 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 @@ -23,6 +23,7 @@ import com.yahoo.vespa.hosted.controller.application.Deployment; import com.yahoo.vespa.hosted.controller.application.Endpoint; import com.yahoo.vespa.hosted.controller.application.Endpoint.Port; import com.yahoo.vespa.hosted.controller.application.EndpointList; +import com.yahoo.vespa.hosted.controller.application.SystemApplication; import com.yahoo.vespa.hosted.controller.application.TenantAndApplicationId; import com.yahoo.vespa.hosted.controller.dns.NameServiceQueue.Priority; import com.yahoo.vespa.hosted.controller.rotation.RotationLock; @@ -84,13 +85,14 @@ public class RoutingController { /** Returns zone-scoped endpoints for given deployment */ public EndpointList endpointsOf(DeploymentId deployment) { var endpoints = new LinkedHashSet<Endpoint>(); + boolean isSystemApplication = SystemApplication.matching(deployment.applicationId()).isPresent(); // Avoid reading application more than once per call to this var application = Suppliers.memoize(() -> controller.applications().requireApplication(TenantAndApplicationId.from(deployment.applicationId()))); for (var policy : routingPolicies.get(deployment).values()) { if (!policy.status().isActive()) continue; for (var routingMethod : controller.zoneRegistry().routingMethods(policy.id().zone())) { - if (routingMethod.isDirect() && !canRouteDirectlyTo(deployment, application.get())) continue; - endpoints.add(policy.endpointIn(controller.system(), routingMethod)); + if (routingMethod.isDirect() && !isSystemApplication && !canRouteDirectlyTo(deployment, application.get())) continue; + endpoints.add(policy.endpointIn(controller.system(), routingMethod, controller.zoneRegistry())); } } return EndpointList.copyOf(endpoints); @@ -98,6 +100,7 @@ public class RoutingController { /** Returns global-scoped endpoints for given instance */ public EndpointList endpointsOf(ApplicationId instance) { + if (SystemApplication.matching(instance).isPresent()) return EndpointList.copyOf(List.of()); return endpointsOf(controller.applications().requireApplication(TenantAndApplicationId.from(instance)), instance.instance()); } 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 ed5add8b98a..f8982c96637 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 @@ -36,20 +36,18 @@ public class Endpoint { private final RoutingMethod routingMethod; private final boolean tls; - private Endpoint(String name, ApplicationId application, List<ZoneId> zones, Scope scope, SystemName system, - Port port, boolean legacy, RoutingMethod routingMethod) { + private Endpoint(String name, URI url, List<ZoneId> zones, Scope scope, Port port, boolean legacy, + RoutingMethod routingMethod) { Objects.requireNonNull(name, "name must be non-null"); - Objects.requireNonNull(application, "application must be non-null"); Objects.requireNonNull(zones, "zones must be non-null"); Objects.requireNonNull(scope, "scope must be non-null"); - Objects.requireNonNull(system, "system must be non-null"); Objects.requireNonNull(port, "port must be non-null"); Objects.requireNonNull(routingMethod, "routingMethod must be non-null"); if (scope == Scope.zone && zones.size() != 1) { throw new IllegalArgumentException("A single zone must be given for zone-scoped endpoints"); } this.name = name; - this.url = createUrl(name, application, zones, scope, system, port, legacy, routingMethod); + this.url = url; this.zones = List.copyOf(zones); this.scope = scope; this.legacy = legacy; @@ -57,6 +55,20 @@ public class Endpoint { this.tls = port.tls; } + private Endpoint(String name, ApplicationId application, List<ZoneId> zones, Scope scope, SystemName system, + Port port, boolean legacy, RoutingMethod routingMethod) { + this(name, + createUrl(name, + Objects.requireNonNull(application, "application must be non-null"), + zones, + scope, + Objects.requireNonNull(system, "system must be non-null"), + port, + legacy, + routingMethod), + zones, scope, port, legacy, routingMethod); + } + /** * Returns the name of this endpoint (the first component of the DNS name). Depending on the endpoint type, this * can be one of the following: @@ -286,6 +298,14 @@ public class Endpoint { return new EndpointBuilder(application); } + /** Create an endpoint for given system application */ + public static Endpoint of(SystemApplication systemApplication, ZoneId zone, URI url) { + if (!systemApplication.hasEndpoint()) throw new IllegalArgumentException(systemApplication + " has no endpoint"); + RoutingMethod routingMethod = RoutingMethod.exclusive; + Port port = url.getPort() == -1 ? Port.tls() : Port.tls(url.getPort()); // System application endpoints are always TLS + return new Endpoint("", url, List.of(zone), Scope.zone, port, false, routingMethod); + } + public static class EndpointBuilder { private final ApplicationId application; diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/SystemApplication.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/SystemApplication.java index 243bca8c027..e1acf867744 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/SystemApplication.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/SystemApplication.java @@ -8,7 +8,9 @@ import com.yahoo.config.provision.zone.ZoneId; import com.yahoo.vespa.hosted.controller.Controller; import com.yahoo.vespa.hosted.controller.api.identifiers.DeploymentId; import com.yahoo.vespa.hosted.controller.api.integration.configserver.ServiceConvergence; +import com.yahoo.vespa.hosted.controller.api.integration.zone.ZoneRegistry; +import java.util.Arrays; import java.util.List; import java.util.Optional; @@ -71,11 +73,27 @@ public enum SystemApplication { return nodeType.isDockerHost(); } + /** Returns whether this has an endpoint */ + public boolean hasEndpoint() { + return this == configServer; + } + + /** Returns the endpoint of this, if any */ + public Optional<Endpoint> endpointIn(ZoneId zone, ZoneRegistry zoneRegistry) { + if (!hasEndpoint()) return Optional.empty(); + return Optional.of(Endpoint.of(this, zone, zoneRegistry.getConfigServerVipUri(zone))); + } + /** All known system applications */ public static List<SystemApplication> all() { return List.of(values()); } + /** Returns the system application matching given id, if any */ + public static Optional<SystemApplication> matching(ApplicationId id) { + return Arrays.stream(values()).filter(app -> app.id().equals(id)).findFirst(); + } + @Override public String toString() { return String.format("system application %s of type %s", id, nodeType); diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/routing/RoutingPolicies.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/routing/RoutingPolicies.java index 7d7803915be..abd4770ea0d 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/routing/RoutingPolicies.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/routing/RoutingPolicies.java @@ -175,7 +175,8 @@ public class RoutingPolicies { /** Update zone DNS record for given policy */ private void updateZoneDnsOf(RoutingPolicy policy) { - var name = RecordName.from(policy.endpointIn(controller.system(), RoutingMethod.exclusive).dnsName()); + var name = RecordName.from(policy.endpointIn(controller.system(), RoutingMethod.exclusive, controller.zoneRegistry()) + .dnsName()); var data = RecordData.fqdn(policy.canonicalName().value()); nameUpdaterIn(policy.id().zone()).createCname(name, data); } @@ -190,7 +191,7 @@ public class RoutingPolicies { if (activeIds.contains(policy.id()) || !policy.id().zone().equals(allocation.deployment.zoneId())) continue; - var dnsName = policy.endpointIn(controller.system(), RoutingMethod.exclusive).dnsName(); + var dnsName = policy.endpointIn(controller.system(), RoutingMethod.exclusive, controller.zoneRegistry()).dnsName(); nameUpdaterIn(allocation.deployment.zoneId()).removeRecords(Record.Type.CNAME, RecordName.from(dnsName)); newPolicies.remove(policy.id()); } diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/routing/RoutingPolicy.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/routing/RoutingPolicy.java index 37027e8a8c9..c56a5f0bd66 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/routing/RoutingPolicy.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/routing/RoutingPolicy.java @@ -5,9 +5,11 @@ import com.google.common.collect.ImmutableSortedSet; import com.yahoo.config.provision.HostName; import com.yahoo.config.provision.SystemName; import com.yahoo.config.provision.zone.RoutingMethod; +import com.yahoo.vespa.hosted.controller.api.integration.zone.ZoneRegistry; import com.yahoo.vespa.hosted.controller.application.Endpoint; import com.yahoo.vespa.hosted.controller.application.Endpoint.Port; import com.yahoo.vespa.hosted.controller.application.EndpointId; +import com.yahoo.vespa.hosted.controller.application.SystemApplication; import java.util.Objects; import java.util.Optional; @@ -68,7 +70,10 @@ public class RoutingPolicy { } /** Returns the endpoint of this */ - public Endpoint endpointIn(SystemName system, RoutingMethod routingMethod) { + public Endpoint endpointIn(SystemName system, RoutingMethod routingMethod, ZoneRegistry zoneRegistry) { + Optional<Endpoint> infraEndpoint = SystemApplication.matching(id.owner()) + .flatMap(app -> app.endpointIn(id.zone(), zoneRegistry)); + if (infraEndpoint.isPresent()) return infraEndpoint.get(); return Endpoint.of(id.owner()) .target(id.cluster(), id.zone()) .on(Port.fromRoutingMethod(routingMethod)) 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 19e684aa175..56fb7194e4e 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 @@ -32,6 +32,7 @@ import com.yahoo.vespa.hosted.controller.deployment.DeploymentContext; import com.yahoo.vespa.hosted.controller.deployment.DeploymentTester; import com.yahoo.vespa.hosted.controller.integration.ServiceRegistryMock; import com.yahoo.vespa.hosted.controller.integration.ZoneApiMock; +import com.yahoo.vespa.hosted.controller.maintenance.NameServiceDispatcher; import com.yahoo.vespa.hosted.rotation.config.RotationsConfig; import org.junit.Test; @@ -579,6 +580,18 @@ public class RoutingPoliciesTest { tester.assertTargets(context.instanceId(), EndpointId.of("r0"), 0, zone1, zone2); } + @Test + public void config_server_routing_policy() { + var tester = new RoutingPoliciesTester(); + var app = SystemApplication.configServer.id(); + + tester.provisionLoadBalancers(1, app, zone1); + tester.routingPolicies().refresh(app, DeploymentSpec.empty, zone1); + new NameServiceDispatcher(tester.tester.controller(), Duration.ofDays(1), Integer.MAX_VALUE).run(); + + assertEquals(Set.of("cfg.prod.us-west-1.test.vip"), tester.recordNames()); + } + /** Returns an application package builder that satisfies requirements for a directly routed endpoint */ private static ApplicationPackageBuilder applicationPackageBuilder() { return new ApplicationPackageBuilder() |