diff options
author | jonmv <venstad@gmail.com> | 2022-11-15 18:16:23 +0100 |
---|---|---|
committer | jonmv <venstad@gmail.com> | 2022-11-16 09:34:36 +0100 |
commit | 18c4b5ec5773ced34eb4700b54799963d74ed0ef (patch) | |
tree | 6cfb3e93dd0beafa7ef73bffa2919ced2a753391 | |
parent | b88c7d56c33166d7f77c68ca2d5d0d9c684c4017 (diff) |
Collapse multiple regions to a single application endpoint
8 files changed, 193 insertions, 141 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 38c06e4dac2..aeefc13b7c4 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 @@ -19,6 +19,7 @@ import com.yahoo.vespa.hosted.controller.api.integration.dns.Record; import com.yahoo.vespa.hosted.controller.api.integration.dns.RecordData; import com.yahoo.vespa.hosted.controller.api.integration.dns.RecordName; import com.yahoo.vespa.hosted.controller.application.Endpoint; +import com.yahoo.vespa.hosted.controller.application.Endpoint.EndpointFactory; import com.yahoo.vespa.hosted.controller.application.Endpoint.Port; import com.yahoo.vespa.hosted.controller.application.EndpointId; import com.yahoo.vespa.hosted.controller.application.EndpointList; @@ -71,6 +72,7 @@ public class RoutingController { private final Controller controller; private final RoutingPolicies routingPolicies; private final RotationRepository rotationRepository; + private final EndpointFactory endpointFactory; public RoutingController(Controller controller, RotationsConfig rotationsConfig) { this.controller = Objects.requireNonNull(controller, "controller must be non-null"); @@ -78,6 +80,7 @@ public class RoutingController { this.rotationRepository = new RotationRepository(Objects.requireNonNull(rotationsConfig, "rotationsConfig must be non-null"), controller.applications(), controller.curator()); + this.endpointFactory = new EndpointFactory(controller.zoneRegistry()); } /** Create a routing context for given deployment */ @@ -115,7 +118,7 @@ public class RoutingController { if (!policy.status().isActive()) continue; RoutingMethod routingMethod = controller.zoneRegistry().routingMethod(policy.id().zone()); endpoints.addAll(policy.zoneEndpointsIn(controller.system(), routingMethod, controller.zoneRegistry())); - endpoints.add(policy.regionEndpointIn(controller.system(), routingMethod)); + endpoints.add(policy.regionEndpointIn(controller.system(), routingMethod, controller.zoneRegistry())); } return EndpointList.copyOf(endpoints); } @@ -158,23 +161,21 @@ public class RoutingController { } // Add application endpoints for (var declaredEndpoint : deploymentSpec.endpoints()) { - Map<ZoneId, Map<DeploymentId, Integer>> deployments = declaredEndpoint.targets().stream() - .collect(groupingBy(t -> ZoneId.from(Environment.prod, t.region()), - toMap(t -> new DeploymentId(application.id().instance(t.instance()), - ZoneId.from(Environment.prod, t.region())), - t -> t.weight()))); - - deployments.forEach((zone, weightedInstances) -> { - // Application endpoints are only supported when using direct routing methods - RoutingMethod routingMethod = usesSharedRouting(zone) ? RoutingMethod.sharedLayer4 : RoutingMethod.exclusive; - endpoints.add(Endpoint.of(application.id()) - .targetApplication(EndpointId.of(declaredEndpoint.endpointId()), - ClusterSpec.Id.from(declaredEndpoint.containerId()), - weightedInstances) - .routingMethod(routingMethod) - .on(Port.fromRoutingMethod(routingMethod)) - .in(controller.system())); - }); + Map<DeploymentId, Integer> deployments = declaredEndpoint.targets().stream() + .collect(toMap(t -> new DeploymentId(application.id().instance(t.instance()), + ZoneId.from(Environment.prod, t.region())), + t -> t.weight())); + + ZoneId zone = deployments.keySet().iterator().next().zoneId(); // Where multiple zones are possible, they all have the same routing method. + // Application endpoints are only supported when using direct routing methods + RoutingMethod routingMethod = usesSharedRouting(zone) ? RoutingMethod.sharedLayer4 : RoutingMethod.exclusive; + endpoints.add(endpointFactory.of(application.id()) + .targetApplication(EndpointId.of(declaredEndpoint.endpointId()), + ClusterSpec.Id.from(declaredEndpoint.containerId()), + deployments) + .routingMethod(routingMethod) + .on(Port.fromRoutingMethod(routingMethod)) + .in(controller.system())); } return EndpointList.copyOf(endpoints); } @@ -207,8 +208,8 @@ public class RoutingController { List<Endpoint.EndpointBuilder> builders = new ArrayList<>(); if (deployment.zoneId().environment().isProduction()) { // Add default and wildcard names for global endpoints - builders.add(Endpoint.of(deployment.applicationId()).target(EndpointId.defaultId())); - builders.add(Endpoint.of(deployment.applicationId()).wildcard()); + builders.add(endpointFactory.of(deployment.applicationId()).target(EndpointId.defaultId())); + builders.add(endpointFactory.of(deployment.applicationId()).wildcard()); // Add default and wildcard names for each region targeted by application endpoints List<DeploymentId> deploymentTargets = deploymentSpec.endpoints().stream() @@ -220,14 +221,14 @@ public class RoutingController { .toList(); TenantAndApplicationId application = TenantAndApplicationId.from(deployment.applicationId()); for (var targetDeployment : deploymentTargets) { - builders.add(Endpoint.of(application).targetApplication(EndpointId.defaultId(), targetDeployment)); - builders.add(Endpoint.of(application).wildcardApplication(targetDeployment)); + builders.add(endpointFactory.of(application).targetApplication(EndpointId.defaultId(), targetDeployment)); + builders.add(endpointFactory.of(application).wildcardApplication(targetDeployment)); } } // Add default and wildcard names for zone endpoints - builders.add(Endpoint.of(deployment.applicationId()).target(ClusterSpec.Id.from("default"), deployment)); - builders.add(Endpoint.of(deployment.applicationId()).wildcard(deployment)); + builders.add(endpointFactory.of(deployment.applicationId()).target(ClusterSpec.Id.from("default"), deployment)); + builders.add(endpointFactory.of(deployment.applicationId()).wildcard(deployment)); // Build all certificate names for (var builder : builders) { @@ -398,11 +399,11 @@ public class RoutingController { throw new IllegalArgumentException("Invalid routing methods for " + routingId + ": Exceeded maximum " + "direct methods"); } - endpoints.add(Endpoint.of(routingId.instance()) - .target(routingId.endpointId(), cluster, deployments) - .on(Port.fromRoutingMethod(method)) - .routingMethod(method) - .in(controller.system())); + endpoints.add(endpointFactory.of(routingId.instance()) + .target(routingId.endpointId(), cluster, deployments) + .on(Port.fromRoutingMethod(method)) + .routingMethod(method) + .in(controller.system())); } return 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 88366466289..2fe234d6902 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 @@ -2,6 +2,7 @@ package com.yahoo.vespa.hosted.controller.application; import com.yahoo.config.provision.ApplicationId; +import com.yahoo.config.provision.CloudName; import com.yahoo.config.provision.ClusterSpec; import com.yahoo.config.provision.InstanceName; import com.yahoo.config.provision.RegionName; @@ -10,19 +11,25 @@ import com.yahoo.config.provision.zone.RoutingMethod; import com.yahoo.config.provision.zone.ZoneId; import com.yahoo.text.Text; import com.yahoo.vespa.hosted.controller.api.identifiers.DeploymentId; +import com.yahoo.vespa.hosted.controller.api.integration.zone.ZoneRegistry; import java.net.URI; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.Set; +import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; import java.util.stream.Stream; +import static java.util.stream.Collectors.toSet; + /** * Represents an application or instance endpoint in hosted Vespa. - * + * <p> * This encapsulates the logic for building URLs and DNS names for applications in all hosted Vespa systems. * * @author mpolden @@ -160,7 +167,8 @@ public class Endpoint { } private static URI createUrl(String name, TenantAndApplicationId application, Optional<InstanceName> instance, - List<Target> targets, Scope scope, SystemName system, Port port, boolean legacy) { + List<Target> targets, Scope scope, SystemName system, Port port, boolean legacy, + boolean includeRegionIfApplicationEndpoint) { String separator = "."; String portPart = port.isDefault() ? "" : ":" + port.port; return URI.create("https://" + @@ -171,7 +179,7 @@ public class Endpoint { separator + sanitize(application.tenant().value()) + "." + - scopePart(scope, targets, system, legacy) + + scopePart(scope, targets, system, legacy, includeRegionIfApplicationEndpoint) + dnsSuffix(system, legacy) + portPart + "/"); @@ -186,9 +194,11 @@ public class Endpoint { return name + separator; } - private static String scopePart(Scope scope, List<Target> targets, SystemName system, boolean legacy) { + private static String scopePart(Scope scope, List<Target> targets, SystemName system, boolean legacy, boolean includeRegionIfApplicationEndpoint) { String scopeSymbol = scopeSymbol(scope, system); + Set<ZoneId> zones = targets.stream().map(target -> target.deployment.zoneId()).collect(toSet()); if (scope == Scope.global) return scopeSymbol; + if (scope == Scope.application && ! includeRegionIfApplicationEndpoint) return scopeSymbol; ZoneId zone = targets.get(0).deployment().zoneId(); String region = zone.region().value(); @@ -414,14 +424,34 @@ public class Endpoint { } - /** Build an endpoint for given instance */ - public static EndpointBuilder of(ApplicationId instance) { - return new EndpointBuilder(TenantAndApplicationId.from(instance), Optional.of(instance.instance())); - } + public static class EndpointFactory { + + private final Function<ZoneId, CloudName> clouds; + + public EndpointFactory(Function<ZoneId, CloudName> clouds) { + this.clouds = clouds; + } + + public EndpointFactory(ZoneRegistry zones) { + this(zone -> findCloud(zone, zones)); + } + + /** Build an endpoint for given instance */ + public EndpointBuilder of(ApplicationId instance) { + return new EndpointBuilder(TenantAndApplicationId.from(instance), Optional.of(instance.instance()), clouds); + } + + /** Build an endpoint for given application */ + public EndpointBuilder of(TenantAndApplicationId application) { + return new EndpointBuilder(application, Optional.empty(), clouds); + } + + private static CloudName findCloud(ZoneId zone, ZoneRegistry zones) { + return zones.zones().all().get(zone) + .orElseThrow(() -> new IllegalArgumentException("unknown zone '" + zone + "'")) + .getCloudName(); + } - /** Build an endpoint for given application */ - public static EndpointBuilder of(TenantAndApplicationId application) { - return new EndpointBuilder(application, Optional.empty()); } /** A target of an endpoint */ @@ -464,6 +494,8 @@ public class Endpoint { private final TenantAndApplicationId application; private final Optional<InstanceName> instance; + private final Function<ZoneId, CloudName> cloudFinder; + private final Set<CloudName> clouds = new HashSet<>(); private Scope scope; private List<Target> targets; private ClusterSpec.Id cluster; @@ -473,9 +505,10 @@ public class Endpoint { private boolean legacy = false; private boolean certificateName = false; - private EndpointBuilder(TenantAndApplicationId application, Optional<InstanceName> instance) { + private EndpointBuilder(TenantAndApplicationId application, Optional<InstanceName> instance, Function<ZoneId, CloudName> cloudFinder) { this.application = Objects.requireNonNull(application); this.instance = Objects.requireNonNull(instance); + this.cloudFinder = Objects.requireNonNull(cloudFinder); } /** Sets the deployment target for this */ @@ -483,6 +516,7 @@ public class Endpoint { this.cluster = cluster; this.scope = requireUnset(Scope.zone); this.targets = List.of(new Target(deployment)); + this.clouds.add(cloudFinder.apply(deployment.zoneId())); return this; } @@ -492,6 +526,7 @@ public class Endpoint { this.cluster = cluster; this.targets = deployments.stream().map(Target::new).toList(); this.scope = requireUnset(Scope.global); + for (DeploymentId deployment : deployments) this.clouds.add(cloudFinder.apply(deployment.zoneId())); return this; } @@ -528,6 +563,7 @@ public class Endpoint { .map(kv -> new Target(kv.getKey(), kv.getValue())) .toList(); this.scope = Scope.application; + for (DeploymentId deploymentId : deployments.keySet()) this.clouds.add(cloudFinder.apply(deploymentId.zoneId())); return this; } @@ -536,6 +572,7 @@ public class Endpoint { this.cluster = cluster; this.scope = requireUnset(Scope.weighted); this.targets = List.of(new Target(new DeploymentId(application.instance(instance.get()), effectiveZone(zone)))); + this.clouds.add(cloudFinder.apply(zone)); return this; } @@ -571,6 +608,7 @@ public class Endpoint { if (routingMethod.isDirect() && !port.isDefault()) { throw new IllegalArgumentException("Routing method " + routingMethod + " can only use default port"); } + boolean includeRegionIfApplicationEndpoint = ! Set.of(CloudName.AWS, CloudName.GCP).containsAll(clouds); URI url = createUrl(endpointOrClusterAsString(endpointId, cluster), Objects.requireNonNull(application, "application must be non-null"), Objects.requireNonNull(instance, "instance must be non-null"), @@ -578,7 +616,8 @@ public class Endpoint { Objects.requireNonNull(scope, "scope must be non-null"), Objects.requireNonNull(system, "system must be non-null"), Objects.requireNonNull(port, "port must be non-null"), - legacy); + legacy, + includeRegionIfApplicationEndpoint); return new Endpoint(application, instance, endpointId, 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 27247c065ed..d3dbfc0f5e9 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 @@ -215,7 +215,7 @@ public class RoutingPolicies { for (var policy : policies) { if (policy.dnsZone().isEmpty() && policy.canonicalName().isPresent()) continue; if (controller.zoneRegistry().routingMethod(policy.id().zone()) != RoutingMethod.exclusive) continue; - Endpoint endpoint = policy.regionEndpointIn(controller.system(), RoutingMethod.exclusive); + Endpoint endpoint = policy.regionEndpointIn(controller.system(), RoutingMethod.exclusive, controller.zoneRegistry()); var zonePolicy = db.readZoneRoutingPolicy(policy.id().zone()); long weight = 1; if (isConfiguredOut(zonePolicy, policy, inactiveZones)) { @@ -289,12 +289,10 @@ public class RoutingPolicies { activeTargets.addAll(inactiveTargets); inactiveTargets.clear(); } + targetsByEndpoint.forEach((applicationEndpoint, targets) -> { - ZoneId targetZone = applicationEndpoint.targets().stream() - .map(Endpoint.Target::deployment) - .map(DeploymentId::zoneId) - .findFirst() - .get(); + // Where multiple zones are permitted, they all have the same routing policy, and nameServiceForwarder (below). + ZoneId targetZone = applicationEndpoint.targets().iterator().next().deployment().zoneId(); Set<AliasTarget> aliasTargets = new LinkedHashSet<>(); Set<DirectTarget> directTargets = new LinkedHashSet<>(); for (Target target : targets) { @@ -312,11 +310,8 @@ public class RoutingPolicies { } }); inactiveTargetsByEndpoint.forEach((applicationEndpoint, targets) -> { - ZoneId targetZone = applicationEndpoint.targets().stream() - .map(Endpoint.Target::deployment) - .map(DeploymentId::zoneId) - .findFirst() - .get(); + // Where multiple zones are permitted, they all have the same routing policy, and nameServiceForwarder (below). + ZoneId targetZone = applicationEndpoint.targets().iterator().next().deployment().zoneId(); targets.forEach(target -> { nameServiceForwarderIn(targetZone).removeRecords(target.type(), RecordName.from(applicationEndpoint.dnsName()), 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 04c32590a4c..269ad0a65fd 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 @@ -9,6 +9,7 @@ import com.yahoo.text.Text; import com.yahoo.vespa.hosted.controller.api.identifiers.DeploymentId; 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.EndpointFactory; import com.yahoo.vespa.hosted.controller.application.Endpoint.Port; import com.yahoo.vespa.hosted.controller.application.EndpointId; @@ -96,12 +97,12 @@ public record RoutingPolicy(RoutingPolicyId id, /** Returns the zone endpoints of this */ public List<Endpoint> zoneEndpointsIn(SystemName system, RoutingMethod routingMethod, ZoneRegistry zoneRegistry) { DeploymentId deployment = new DeploymentId(id.owner(), id.zone()); - return List.of(endpoint(routingMethod).target(id.cluster(), deployment).in(system)); + return List.of(endpoint(routingMethod, zoneRegistry).target(id.cluster(), deployment).in(system)); } /** Returns the region endpoint of this */ - public Endpoint regionEndpointIn(SystemName system, RoutingMethod routingMethod) { - return endpoint(routingMethod).targetRegion(id.cluster(), id.zone()).in(system); + public Endpoint regionEndpointIn(SystemName system, RoutingMethod routingMethod, ZoneRegistry zoneRegistry) { + return endpoint(routingMethod, zoneRegistry).targetRegion(id.cluster(), id.zone()).in(system); } @Override @@ -125,10 +126,10 @@ public record RoutingPolicy(RoutingPolicyId id, id.zone().value()); } - private Endpoint.EndpointBuilder endpoint(RoutingMethod routingMethod) { - return Endpoint.of(id.owner()) - .on(Port.fromRoutingMethod(routingMethod)) - .routingMethod(routingMethod); + private Endpoint.EndpointBuilder endpoint(RoutingMethod routingMethod, ZoneRegistry zones) { + return new EndpointFactory(zones).of(id.owner()) + .on(Port.fromRoutingMethod(routingMethod)) + .routingMethod(routingMethod); } /** The status of a routing policy */ diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java index c87a4e490b9..2cc3cff455c 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java @@ -669,12 +669,12 @@ public class ControllerTest { new DeploymentId(main, east3), Map.of("e.app1.tenant1.us-east-3-r.vespa.oath.cloud", 3), new DeploymentId(beta, west1), Map.of("d.app1.tenant1.us-west-1-r.vespa.oath.cloud", 3), new DeploymentId(main, west1), Map.of("d.app1.tenant1.us-west-1-r.vespa.oath.cloud", 7), - new DeploymentId(beta, east1a), Map.of("a.app1.tenant1.aws-us-east-1a-r.vespa.oath.cloud", 2, - "b.app1.tenant1.aws-us-east-1a-r.vespa.oath.cloud", 1), - new DeploymentId(main, east1a), Map.of("a.app1.tenant1.aws-us-east-1a-r.vespa.oath.cloud", 8, - "b.app1.tenant1.aws-us-east-1a-r.vespa.oath.cloud", 1), - new DeploymentId(beta, east1b), Map.of("c.app1.tenant1.aws-us-east-1b-r.vespa.oath.cloud", 4), - new DeploymentId(main, east1b), Map.of("a.app1.tenant1.aws-us-east-1b-r.vespa.oath.cloud", 1) + new DeploymentId(beta, east1a), Map.of("a.app1.tenant1.r.vespa.oath.cloud", 2, + "b.app1.tenant1.r.vespa.oath.cloud", 1), + new DeploymentId(main, east1a), Map.of("a.app1.tenant1.r.vespa.oath.cloud", 8, + "b.app1.tenant1.r.vespa.oath.cloud", 1), + new DeploymentId(beta, east1b), Map.of("c.app1.tenant1.r.vespa.oath.cloud", 4), + new DeploymentId(main, east1b), Map.of("a.app1.tenant1.r.vespa.oath.cloud", 1) ); deploymentEndpoints.forEach((deployment, endpoints) -> { Set<ContainerEndpoint> expected = endpoints.entrySet().stream() @@ -704,22 +704,22 @@ public class ControllerTest { RecordName.from("main.app1.tenant1.aws-us-east-1b.vespa.oath.cloud"), RecordData.from("lb-0--tenant1.app1.main--prod.aws-us-east-1b.")), new Record(Record.Type.ALIAS, - RecordName.from("a.app1.tenant1.aws-us-east-1a-r.vespa.oath.cloud"), + RecordName.from("a.app1.tenant1.r.vespa.oath.cloud"), RecordData.from("weighted/lb-0--tenant1.app1.beta--prod.aws-us-east-1a/dns-zone-1/prod.aws-us-east-1a/2")), new Record(Record.Type.ALIAS, - RecordName.from("a.app1.tenant1.aws-us-east-1a-r.vespa.oath.cloud"), + RecordName.from("a.app1.tenant1.r.vespa.oath.cloud"), RecordData.from("weighted/lb-0--tenant1.app1.main--prod.aws-us-east-1a/dns-zone-1/prod.aws-us-east-1a/8")), new Record(Record.Type.ALIAS, - RecordName.from("a.app1.tenant1.aws-us-east-1b-r.vespa.oath.cloud"), + RecordName.from("a.app1.tenant1.r.vespa.oath.cloud"), RecordData.from("weighted/lb-0--tenant1.app1.main--prod.aws-us-east-1b/dns-zone-1/prod.aws-us-east-1b/1")), new Record(Record.Type.ALIAS, - RecordName.from("b.app1.tenant1.aws-us-east-1a-r.vespa.oath.cloud"), + RecordName.from("b.app1.tenant1.r.vespa.oath.cloud"), RecordData.from("weighted/lb-0--tenant1.app1.beta--prod.aws-us-east-1a/dns-zone-1/prod.aws-us-east-1a/1")), new Record(Record.Type.ALIAS, - RecordName.from("b.app1.tenant1.aws-us-east-1a-r.vespa.oath.cloud"), + RecordName.from("b.app1.tenant1.r.vespa.oath.cloud"), RecordData.from("weighted/lb-0--tenant1.app1.main--prod.aws-us-east-1a/dns-zone-1/prod.aws-us-east-1a/1")), new Record(Record.Type.ALIAS, - RecordName.from("c.app1.tenant1.aws-us-east-1b-r.vespa.oath.cloud"), + RecordName.from("c.app1.tenant1.r.vespa.oath.cloud"), RecordData.from("weighted/lb-0--tenant1.app1.beta--prod.aws-us-east-1b/dns-zone-1/prod.aws-us-east-1b/4")), new Record(Record.Type.CNAME, RecordName.from("d.app1.tenant1.us-west-1-r.vespa.oath.cloud"), @@ -732,10 +732,9 @@ public class ControllerTest { .scope(Endpoint.Scope.application) .sortedBy(comparing(Endpoint::dnsName)) .mapToList(Endpoint::dnsName); - assertEquals(List.of("a.app1.tenant1.aws-us-east-1a-r.vespa.oath.cloud", - "a.app1.tenant1.aws-us-east-1b-r.vespa.oath.cloud", - "b.app1.tenant1.aws-us-east-1a-r.vespa.oath.cloud", - "c.app1.tenant1.aws-us-east-1b-r.vespa.oath.cloud", + assertEquals(List.of("a.app1.tenant1.r.vespa.oath.cloud", + "b.app1.tenant1.r.vespa.oath.cloud", + "c.app1.tenant1.r.vespa.oath.cloud", "d.app1.tenant1.us-west-1-r.vespa.oath.cloud", "e.app1.tenant1.us-east-3-r.vespa.oath.cloud"), endpointDnsNames); diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/application/EndpointTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/application/EndpointTest.java index f3324e0c1f3..f56b63dd2d9 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/application/EndpointTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/application/EndpointTest.java @@ -2,11 +2,13 @@ package com.yahoo.vespa.hosted.controller.application; import com.yahoo.config.provision.ApplicationId; +import com.yahoo.config.provision.CloudName; import com.yahoo.config.provision.ClusterSpec; import com.yahoo.config.provision.SystemName; import com.yahoo.config.provision.zone.RoutingMethod; import com.yahoo.config.provision.zone.ZoneId; import com.yahoo.vespa.hosted.controller.api.identifiers.DeploymentId; +import com.yahoo.vespa.hosted.controller.application.Endpoint.EndpointFactory; import com.yahoo.vespa.hosted.controller.application.Endpoint.Port; import org.junit.jupiter.api.Test; @@ -24,6 +26,8 @@ public class EndpointTest { private static final ApplicationId instance2 = ApplicationId.from("t2", "a2", "i2"); private static final TenantAndApplicationId app1 = TenantAndApplicationId.from(instance1); private static final TenantAndApplicationId app2 = TenantAndApplicationId.from(instance2); + private static final EndpointFactory defaultFactory = new EndpointFactory(__ -> CloudName.DEFAULT); + private static final EndpointFactory otherFactory = new EndpointFactory(__ -> CloudName.AWS); @Test void global_endpoints() { @@ -35,38 +39,38 @@ public class EndpointTest { Map<String, Endpoint> tests = Map.of( // Main endpoint with direct routing and default TLS port "https://a1.t1.global.vespa.oath.cloud/", - Endpoint.of(instance1).target(endpointId, cluster, List.of(deployment1)).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.main), + defaultFactory.of(instance1).target(endpointId, cluster, List.of(deployment1)).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.main), // Main endpoint with custom rotation name "https://r1.a1.t1.global.vespa.oath.cloud/", - Endpoint.of(instance1).target(EndpointId.of("r1"), cluster, List.of(deployment1)).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.main), + defaultFactory.of(instance1).target(EndpointId.of("r1"), cluster, List.of(deployment1)).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.main), // Main endpoint for custom instance in default rotation "https://i2.a2.t2.global.vespa.oath.cloud/", - Endpoint.of(instance2).target(endpointId, cluster, List.of(deployment2)).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.main), + defaultFactory.of(instance2).target(endpointId, cluster, List.of(deployment2)).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.main), // Main endpoint for custom instance with custom rotation name "https://r2.i2.a2.t2.global.vespa.oath.cloud/", - Endpoint.of(instance2).target(EndpointId.of("r2"), cluster, List.of(deployment2)).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.main), + defaultFactory.of(instance2).target(EndpointId.of("r2"), cluster, List.of(deployment2)).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.main), // Main endpoint in public system "https://a1.t1.g.vespa-app.cloud/", - Endpoint.of(instance1).target(endpointId, cluster, List.of(deployment1)).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.Public) + defaultFactory.of(instance1).target(endpointId, cluster, List.of(deployment1)).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.Public) ); tests.forEach((expected, endpoint) -> assertEquals(expected, endpoint.url().toString())); Map<String, Endpoint> tests2 = Map.of( // Default endpoint in public system "https://a1.t1.g.vespa-app.cloud/", - Endpoint.of(instance1).target(endpointId, cluster, List.of(deployment1)).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.Public), + defaultFactory.of(instance1).target(endpointId, cluster, List.of(deployment1)).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.Public), // Default endpoint in public CD system "https://a1.t1.g.cd.vespa-app.cloud/", - Endpoint.of(instance1).target(endpointId, cluster, List.of(deployment1)).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.PublicCd), + defaultFactory.of(instance1).target(endpointId, cluster, List.of(deployment1)).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.PublicCd), // Custom instance in public system "https://i2.a2.t2.g.vespa-app.cloud/", - Endpoint.of(instance2).target(endpointId, cluster, List.of(deployment2)).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.Public) + defaultFactory.of(instance2).target(endpointId, cluster, List.of(deployment2)).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.Public) ); tests2.forEach((expected, endpoint) -> assertEquals(expected, endpoint.url().toString())); } @@ -81,34 +85,34 @@ public class EndpointTest { Map<String, Endpoint> tests = Map.of( // Main endpoint with direct routing and default TLS port "https://a1.t1.global.vespa.oath.cloud/", - Endpoint.of(instance1).target(endpointId, cluster, List.of(deployment1)).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.main), + defaultFactory.of(instance1).target(endpointId, cluster, List.of(deployment1)).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.main), // Main endpoint with custom rotation name "https://r1.a1.t1.global.vespa.oath.cloud/", - Endpoint.of(instance1).target(EndpointId.of("r1"), cluster, List.of(deployment1)).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.main), + defaultFactory.of(instance1).target(EndpointId.of("r1"), cluster, List.of(deployment1)).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.main), // Main endpoint for custom instance in default rotation "https://i2.a2.t2.global.vespa.oath.cloud/", - Endpoint.of(instance2).target(endpointId, cluster, List.of(deployment2)).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.main), + defaultFactory.of(instance2).target(endpointId, cluster, List.of(deployment2)).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.main), // Main endpoint for custom instance with custom rotation name "https://r2.i2.a2.t2.global.vespa.oath.cloud/", - Endpoint.of(instance2).target(EndpointId.of("r2"), cluster, List.of(deployment2)).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.main), + defaultFactory.of(instance2).target(EndpointId.of("r2"), cluster, List.of(deployment2)).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.main), // Main endpoint in public system "https://a1.t1.g.vespa-app.cloud/", - Endpoint.of(instance1).target(endpointId, cluster, List.of(deployment1)).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.Public) + defaultFactory.of(instance1).target(endpointId, cluster, List.of(deployment1)).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.Public) ); tests.forEach((expected, endpoint) -> assertEquals(expected, endpoint.url().toString())); Map<String, Endpoint> tests2 = Map.of( // Custom endpoint and instance in public CD system) "https://foo.i2.a2.t2.g.cd.vespa-app.cloud/", - Endpoint.of(instance2).target(EndpointId.of("foo"), cluster, List.of(deployment2)).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.PublicCd), + defaultFactory.of(instance2).target(EndpointId.of("foo"), cluster, List.of(deployment2)).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.PublicCd), // Custom endpoint and instance in public system "https://foo.i2.a2.t2.g.vespa-app.cloud/", - Endpoint.of(instance2).target(EndpointId.of("foo"), cluster, List.of(deployment2)).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.Public) + defaultFactory.of(instance2).target(EndpointId.of("foo"), cluster, List.of(deployment2)).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.Public) ); tests2.forEach((expected, endpoint) -> assertEquals(expected, endpoint.url().toString())); } @@ -123,50 +127,50 @@ public class EndpointTest { Map<String, Endpoint> tests = Map.of( // Prod endpoint in main "https://a1.t1.us-north-1.vespa.oath.cloud/", - Endpoint.of(instance1).target(cluster, prodZone).on(Port.tls()).in(SystemName.main), + defaultFactory.of(instance1).target(cluster, prodZone).on(Port.tls()).in(SystemName.main), // Prod endpoint in CD "https://cd.a1.t1.us-north-1.vespa.oath.cloud/", - Endpoint.of(instance1).target(cluster, prodZone).on(Port.tls()).in(SystemName.cd), + defaultFactory.of(instance1).target(cluster, prodZone).on(Port.tls()).in(SystemName.cd), // Test endpoint in main "https://a1.t1.us-north-2.test.vespa.oath.cloud/", - Endpoint.of(instance1).target(cluster, testZone).on(Port.tls()).in(SystemName.main), + defaultFactory.of(instance1).target(cluster, testZone).on(Port.tls()).in(SystemName.main), // Non-default cluster in main "https://c1.a1.t1.us-north-1.vespa.oath.cloud/", - Endpoint.of(instance1).target(ClusterSpec.Id.from("c1"), prodZone).on(Port.tls()).in(SystemName.main), + defaultFactory.of(instance1).target(ClusterSpec.Id.from("c1"), prodZone).on(Port.tls()).in(SystemName.main), // Non-default instance in main "https://i2.a2.t2.us-north-1.vespa.oath.cloud/", - Endpoint.of(instance2).target(cluster, prodZone2).on(Port.tls()).in(SystemName.main), + defaultFactory.of(instance2).target(cluster, prodZone2).on(Port.tls()).in(SystemName.main), // Non-default cluster in public "https://c1.a1.t1.us-north-1.z.vespa-app.cloud/", - Endpoint.of(instance1).target(ClusterSpec.Id.from("c1"), prodZone).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.Public), + defaultFactory.of(instance1).target(ClusterSpec.Id.from("c1"), prodZone).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.Public), // Non-default cluster and instance in public "https://c2.i2.a2.t2.us-north-1.z.vespa-app.cloud/", - Endpoint.of(instance2).target(ClusterSpec.Id.from("c2"), prodZone2).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.Public) + defaultFactory.of(instance2).target(ClusterSpec.Id.from("c2"), prodZone2).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.Public) ); tests.forEach((expected, endpoint) -> assertEquals(expected, endpoint.url().toString())); Map<String, Endpoint> tests2 = Map.of( // Non-default cluster and instance in public CD (legacy) "https://c2.i2.a2.t2.us-north-1.z.cd.vespa-app.cloud/", - Endpoint.of(instance2).target(ClusterSpec.Id.from("c2"), prodZone2).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.PublicCd), + defaultFactory.of(instance2).target(ClusterSpec.Id.from("c2"), prodZone2).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.PublicCd), // Custom cluster name in public "https://c1.a1.t1.us-north-1.z.vespa-app.cloud/", - Endpoint.of(instance1).target(ClusterSpec.Id.from("c1"), prodZone).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.Public), + defaultFactory.of(instance1).target(ClusterSpec.Id.from("c1"), prodZone).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.Public), // Default cluster name in non-production zone in public "https://a1.t1.us-north-2.test.z.vespa-app.cloud/", - Endpoint.of(instance1).target(ClusterSpec.Id.from("default"), testZone).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.Public), + defaultFactory.of(instance1).target(ClusterSpec.Id.from("default"), testZone).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.Public), // Default cluster name in public CD "https://a1.t1.us-north-1.z.cd.vespa-app.cloud/", - Endpoint.of(instance1).target(ClusterSpec.Id.from("default"), prodZone).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.PublicCd) + defaultFactory.of(instance1).target(ClusterSpec.Id.from("default"), prodZone).on(Port.tls()).routingMethod(RoutingMethod.exclusive).in(SystemName.PublicCd) ); tests2.forEach((expected, endpoint) -> assertEquals(expected, endpoint.url().toString())); } @@ -180,7 +184,7 @@ public class EndpointTest { var tests = Map.of( // Default rotation "https://a1.t1.g.vespa-app.cloud/", - Endpoint.of(instance1) + defaultFactory.of(instance1) .target(EndpointId.defaultId()) .certificateName() .routingMethod(RoutingMethod.exclusive) @@ -189,7 +193,7 @@ public class EndpointTest { // Wildcard to match other rotations "https://*.a1.t1.g.vespa-app.cloud/", - Endpoint.of(instance1) + defaultFactory.of(instance1) .wildcard() .certificateName() .routingMethod(RoutingMethod.exclusive) @@ -198,7 +202,7 @@ public class EndpointTest { // Default cluster in zone "https://a1.t1.us-north-1.z.vespa-app.cloud/", - Endpoint.of(instance1) + defaultFactory.of(instance1) .target(defaultCluster, prodZone) .certificateName() .routingMethod(RoutingMethod.exclusive) @@ -207,7 +211,7 @@ public class EndpointTest { // Default cluster in test zone "https://a1.t1.us-north-2.test.z.vespa-app.cloud/", - Endpoint.of(instance1) + defaultFactory.of(instance1) .target(defaultCluster, testZone) .certificateName() .routingMethod(RoutingMethod.exclusive) @@ -216,7 +220,7 @@ public class EndpointTest { // Wildcard to match other clusters in test zone "https://*.a1.t1.us-north-2.test.z.vespa-app.cloud/", - Endpoint.of(instance1) + defaultFactory.of(instance1) .wildcard(testZone) .certificateName() .routingMethod(RoutingMethod.exclusive) @@ -225,7 +229,7 @@ public class EndpointTest { // Wildcard to match other clusters in zone "https://*.a1.t1.us-north-1.z.vespa-app.cloud/", - Endpoint.of(instance1) + defaultFactory.of(instance1) .wildcard(prodZone) .certificateName() .routingMethod(RoutingMethod.exclusive) @@ -242,25 +246,25 @@ public class EndpointTest { var prodZone = ZoneId.from("prod", "us-north-2"); Map<String, Endpoint> tests = Map.of( "https://a1.t1.aws-us-north-1.w.vespa-app.cloud/", - Endpoint.of(instance1) + defaultFactory.of(instance1) .targetRegion(cluster, ZoneId.from("prod", "aws-us-north-1a")) .routingMethod(RoutingMethod.exclusive) .on(Port.tls()) .in(SystemName.Public), "https://a1.t1.gcp-us-south1.w.vespa-app.cloud/", - Endpoint.of(instance1) + defaultFactory.of(instance1) .targetRegion(cluster, ZoneId.from("prod", "gcp-us-south1-c")) .routingMethod(RoutingMethod.exclusive) .on(Port.tls()) .in(SystemName.Public), "https://a1.t1.us-north-2.w.vespa-app.cloud/", - Endpoint.of(instance1) + defaultFactory.of(instance1) .targetRegion(cluster, prodZone) .routingMethod(RoutingMethod.exclusive) .on(Port.tls()) .in(SystemName.Public), "https://c1.a1.t1.us-north-2.w.vespa-app.cloud/", - Endpoint.of(instance1) + defaultFactory.of(instance1) .targetRegion(ClusterSpec.Id.from("c1"), prodZone) .routingMethod(RoutingMethod.exclusive) .on(Port.tls()) @@ -279,29 +283,29 @@ public class EndpointTest { @Test void application_endpoints() { Map<String, Endpoint> tests = Map.of( - "https://weighted.a1.t1.us-west-1.r.vespa-app.cloud/", - Endpoint.of(app1) + "https://weighted.a1.t1.r.vespa-app.cloud/", + otherFactory.of(app1) .targetApplication(EndpointId.of("weighted"), ClusterSpec.Id.from("qrs"), Map.of(new DeploymentId(app1.instance("i1"), ZoneId.from("prod", "us-west-1")), 1)) .routingMethod(RoutingMethod.exclusive) .on(Port.tls()) .in(SystemName.Public), "https://weighted.a1.t1.us-west-1.r.cd.vespa-app.cloud/", - Endpoint.of(app1) + defaultFactory.of(app1) .targetApplication(EndpointId.of("weighted"), ClusterSpec.Id.from("qrs"), Map.of(new DeploymentId(app1.instance("i1"), ZoneId.from("prod", "us-west-1")), 1)) .routingMethod(RoutingMethod.exclusive) .on(Port.tls()) .in(SystemName.PublicCd), - "https://a2.t2.us-east-3-r.vespa.oath.cloud/", - Endpoint.of(app2) + "https://a2.t2.r.vespa.oath.cloud/", + otherFactory.of(app2) .targetApplication(EndpointId.defaultId(), ClusterSpec.Id.from("qrs"), Map.of(new DeploymentId(app2.instance("i1"), ZoneId.from("prod", "us-east-3")), 1)) .routingMethod(RoutingMethod.exclusive) .on(Port.tls()) .in(SystemName.main), "https://cd.a2.t2.us-east-3-r.vespa.oath.cloud/", - Endpoint.of(app2) + defaultFactory.of(app2) .targetApplication(EndpointId.defaultId(), ClusterSpec.Id.from("qrs"), Map.of(new DeploymentId(app2.instance("i1"), ZoneId.from("prod", "us-east-3")), 1)) .routingMethod(RoutingMethod.exclusive) @@ -318,15 +322,15 @@ public class EndpointTest { var tests1 = Map.of( // With default cluster "a1.t1.us-north-1.prod", - Endpoint.of(instance1).target(EndpointId.defaultId(), ClusterSpec.Id.from("default"), List.of(zone)).on(Port.tls()).in(SystemName.main), + defaultFactory.of(instance1).target(EndpointId.defaultId(), ClusterSpec.Id.from("default"), List.of(zone)).on(Port.tls()).in(SystemName.main), // With non-default cluster "c1.a1.t1.us-north-1.prod", - Endpoint.of(instance1).target(EndpointId.of("ignored1"), ClusterSpec.Id.from("c1"), List.of(zone)).on(Port.tls()).in(SystemName.main), + defaultFactory.of(instance1).target(EndpointId.of("ignored1"), ClusterSpec.Id.from("c1"), List.of(zone)).on(Port.tls()).in(SystemName.main), // With application endpoint "c2.a1.t1.us-north-1.prod", - Endpoint.of(app1).targetApplication(EndpointId.defaultId(), ClusterSpec.Id.from("c2"), Map.of(new DeploymentId(app1.instance("i1"), zone.zoneId()), 1)) + defaultFactory.of(app1).targetApplication(EndpointId.defaultId(), ClusterSpec.Id.from("c2"), Map.of(new DeploymentId(app1.instance("i1"), zone.zoneId()), 1)) .routingMethod(RoutingMethod.sharedLayer4) .on(Port.tls()) .in(SystemName.main) @@ -334,11 +338,11 @@ public class EndpointTest { var tests2 = Map.of( // With non-default instance and default cluster "i2.a2.t2.us-north-1.prod", - Endpoint.of(instance2).target(EndpointId.defaultId(), ClusterSpec.Id.from("default"), List.of(zone2)).on(Port.tls()).in(SystemName.main), + defaultFactory.of(instance2).target(EndpointId.defaultId(), ClusterSpec.Id.from("default"), List.of(zone2)).on(Port.tls()).in(SystemName.main), // With non-default instance and cluster "c2.i2.a2.t2.us-north-1.prod", - Endpoint.of(instance2).target(EndpointId.of("ignored2"), ClusterSpec.Id.from("c2"), List.of(zone2)).on(Port.tls()).in(SystemName.main) + defaultFactory.of(instance2).target(EndpointId.of("ignored2"), ClusterSpec.Id.from("c2"), List.of(zone2)).on(Port.tls()).in(SystemName.main) ); tests1.forEach((expected, endpoint) -> assertEquals(expected, endpoint.upstreamName(zone))); tests2.forEach((expected, endpoint) -> assertEquals(expected, endpoint.upstreamName(zone2))); diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/certificate/EndpointCertificatesTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/certificate/EndpointCertificatesTest.java index b06b4eb0cfa..6be6aa84319 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/certificate/EndpointCertificatesTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/certificate/EndpointCertificatesTest.java @@ -4,6 +4,7 @@ package com.yahoo.vespa.hosted.controller.certificate; import com.yahoo.config.application.api.DeploymentSpec; import com.yahoo.config.application.api.xml.DeploymentSpecXmlReader; import com.yahoo.config.provision.ApplicationId; +import com.yahoo.config.provision.CloudName; import com.yahoo.config.provision.Environment; import com.yahoo.config.provision.InstanceName; import com.yahoo.config.provision.RegionName; @@ -25,6 +26,7 @@ import com.yahoo.vespa.hosted.controller.api.integration.certificates.EndpointCe import com.yahoo.vespa.hosted.controller.application.pkg.ApplicationPackage; import com.yahoo.vespa.hosted.controller.deployment.ApplicationPackageBuilder; import com.yahoo.vespa.hosted.controller.integration.SecretStoreMock; +import com.yahoo.vespa.hosted.controller.integration.ZoneApiMock; import com.yahoo.vespa.hosted.controller.persistence.CuratorDb; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -136,9 +138,15 @@ public class EndpointCertificatesTest { assertEquals(expectedSans, endpointCertificateMetadata.get().requestedDnsSans()); } + private ControllerTester publicTester() { + ControllerTester publicTester = new ControllerTester(SystemName.Public); + publicTester.zoneRegistry().setZones(tester.zoneRegistry().zones().all().zones()); + return publicTester; + } + @Test void provisions_new_certificate_in_public_prod() { - ControllerTester tester = new ControllerTester(SystemName.Public); + ControllerTester tester = publicTester(); EndpointCertificateValidatorImpl endpointCertificateValidator = new EndpointCertificateValidatorImpl(secretStore, clock); EndpointCertificates endpointCertificates = new EndpointCertificates(tester.controller(), endpointCertificateMock, endpointCertificateValidator); List<String> expectedSans = List.of( @@ -238,6 +246,9 @@ public class EndpointCertificatesTest { Instance instance = new Instance(ApplicationId.from("t1", "a1", "default"), Tags.empty()); ZoneId zone1 = ZoneId.from(Environment.prod, RegionName.from("aws-us-east-1c")); ZoneId zone2 = ZoneId.from(Environment.prod, RegionName.from("aws-us-west-2a")); + ControllerTester tester = publicTester(); + tester.zoneRegistry().addZones(ZoneApiMock.newBuilder().with(CloudName.DEFAULT).with(zone1).build(), + ZoneApiMock.newBuilder().with(CloudName.AWS).with(zone2).build()); ApplicationPackage applicationPackage = new ApplicationPackageBuilder() .instances("beta,main") .region(zone1.region()) @@ -251,15 +262,14 @@ public class EndpointCertificatesTest { InstanceName.from("main"), 6), zone2.region().value(), Map.of(InstanceName.from("main"), 2))) .build(); - ControllerTester tester = new ControllerTester(SystemName.Public); EndpointCertificateValidatorImpl endpointCertificateValidator = new EndpointCertificateValidatorImpl(secretStore, clock); EndpointCertificates endpointCertificates = new EndpointCertificates(tester.controller(), endpointCertificateMock, endpointCertificateValidator); List<String> expectedSans = List.of( "vlfms2wpoa4nyrka2s5lktucypjtxkqhv.internal.vespa-app.cloud", "a1.t1.g.vespa-app.cloud", "*.a1.t1.g.vespa-app.cloud", - "a1.t1.aws-us-west-2a.r.vespa-app.cloud", - "*.a1.t1.aws-us-west-2a.r.vespa-app.cloud", + "a1.t1.r.vespa-app.cloud", + "*.a1.t1.r.vespa-app.cloud", "a1.t1.aws-us-east-1c.r.vespa-app.cloud", "*.a1.t1.aws-us-east-1c.r.vespa-app.cloud", "a1.t1.aws-us-east-1c.z.vespa-app.cloud", diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/TestConfigSerializerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/TestConfigSerializerTest.java index 6493eafcde5..ba05cdf2fd5 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/TestConfigSerializerTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/TestConfigSerializerTest.java @@ -3,6 +3,7 @@ package com.yahoo.vespa.hosted.controller.deployment; import com.yahoo.component.Version; import com.yahoo.config.provision.ApplicationId; +import com.yahoo.config.provision.CloudName; import com.yahoo.config.provision.ClusterSpec; import com.yahoo.config.provision.SystemName; import com.yahoo.config.provision.zone.ZoneId; @@ -10,6 +11,7 @@ import com.yahoo.slime.SlimeUtils; import com.yahoo.vespa.hosted.controller.api.identifiers.DeploymentId; import com.yahoo.vespa.hosted.controller.api.integration.deployment.RevisionId; import com.yahoo.vespa.hosted.controller.application.Endpoint; +import com.yahoo.vespa.hosted.controller.application.Endpoint.EndpointFactory; import com.yahoo.vespa.hosted.controller.application.EndpointId; import org.junit.jupiter.api.Test; @@ -31,22 +33,23 @@ public class TestConfigSerializerTest { @Test void testConfig() throws IOException { ZoneId zone = DeploymentContext.systemTest.zone(); - byte[] json = new TestConfigSerializer(SystemName.PublicCd).configJson(instanceId, - DeploymentContext.systemTest, - true, - Version.fromString("1.2.3"), - RevisionId.forProduction(321), - Instant.ofEpochMilli(222), - Map.of(zone, List.of(Endpoint.of(ApplicationId.defaultId()) - .target(EndpointId.of("ai"), ClusterSpec.Id.from("qrs"), - List.of(new DeploymentId(ApplicationId.defaultId(), - ZoneId.defaultId()))) - .on(Endpoint.Port.tls()) - .in(SystemName.main))), - Map.of(zone, List.of("facts"))); + byte[] json = new TestConfigSerializer(SystemName.PublicCd) + .configJson(instanceId, + DeploymentContext.systemTest, + true, + Version.fromString("1.2.3"), + RevisionId.forProduction(321), + Instant.ofEpochMilli(222), + Map.of(zone, List.of(new EndpointFactory(__ -> CloudName.DEFAULT).of(ApplicationId.defaultId()) + .target(EndpointId.of("ai"), ClusterSpec.Id.from("qrs"), + List.of(new DeploymentId(ApplicationId.defaultId(), + ZoneId.defaultId()))) + .on(Endpoint.Port.tls()) + .in(SystemName.main))), + Map.of(zone, List.of("facts"))); byte[] expected = Files.readAllBytes(Paths.get("src/test/resources/testConfig.json")); assertEquals(new String(SlimeUtils.toJsonBytes(SlimeUtils.jsonToSlime(expected))), - new String(json)); + new String(json)); } } |