summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Polden <mpolden@mpolden.no>2020-03-11 15:28:09 +0100
committerMartin Polden <mpolden@mpolden.no>2020-03-12 12:12:20 +0100
commit58df1263e48ff6a089ee722d62715a2c9820169c (patch)
treea6e93908d4dbe13f731133e198807ce845789660
parent3da641f5e5295f0f67ebf062618464327c2d7f40 (diff)
Restrict directly routed zone endpoints to qualified deployments
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/RoutingController.java49
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java46
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/ApplicationPackageBuilder.java15
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentContext.java5
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTriggerTest.java2
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunnerTest.java16
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java3
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/routing/RoutingApiTest.java5
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/routing/RoutingPoliciesTest.java41
-rw-r--r--flags/src/main/java/com/yahoo/vespa/flags/Flags.java6
10 files changed, 159 insertions, 29 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 1c22a37af8d..c8f936c2147 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
@@ -1,23 +1,30 @@
// Copyright 2020 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller;
+import com.google.common.base.Suppliers;
+import com.yahoo.component.Version;
import com.yahoo.config.application.api.DeploymentInstanceSpec;
import com.yahoo.config.application.api.DeploymentSpec;
import com.yahoo.config.provision.ApplicationId;
-import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.InstanceName;
import com.yahoo.config.provision.zone.RoutingMethod;
import com.yahoo.config.provision.zone.ZoneId;
+import com.yahoo.vespa.flags.BooleanFlag;
+import com.yahoo.vespa.flags.FetchVector;
+import com.yahoo.vespa.flags.Flags;
import com.yahoo.vespa.hosted.controller.api.application.v4.model.EndpointStatus;
import com.yahoo.vespa.hosted.controller.api.identifiers.DeploymentId;
import com.yahoo.vespa.hosted.controller.api.integration.configserver.ContainerEndpoint;
+import com.yahoo.vespa.hosted.controller.api.integration.deployment.ApplicationVersion;
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.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.TenantAndApplicationId;
import com.yahoo.vespa.hosted.controller.dns.NameServiceQueue.Priority;
import com.yahoo.vespa.hosted.controller.rotation.RotationLock;
import com.yahoo.vespa.hosted.controller.rotation.RotationRepository;
@@ -25,7 +32,6 @@ import com.yahoo.vespa.hosted.controller.routing.RoutingId;
import com.yahoo.vespa.hosted.controller.routing.RoutingPolicies;
import com.yahoo.vespa.hosted.rotation.config.RotationsConfig;
-import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -37,9 +43,9 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.Optional;
import java.util.Set;
import java.util.TreeMap;
-import java.util.function.Function;
import java.util.stream.Collectors;
/**
@@ -52,15 +58,21 @@ import java.util.stream.Collectors;
*/
public class RoutingController {
+ /** The minimum Vespa version that supports directly routed endpoints */
+ public static final Version DIRECT_ROUTING_MIN_VERSION = new Version(Integer.MAX_VALUE, Integer.MAX_VALUE,
+ Integer.MAX_VALUE);
+
private final Controller controller;
private final RoutingPolicies routingPolicies;
private final RotationRepository rotationRepository;
+ private final BooleanFlag allowDirectRouting;
public RoutingController(Controller controller, RotationsConfig rotationsConfig) {
this.controller = Objects.requireNonNull(controller, "controller must be non-null");
this.routingPolicies = new RoutingPolicies(controller);
this.rotationRepository = new RotationRepository(rotationsConfig, controller.applications(),
controller.curator());
+ this.allowDirectRouting = Flags.ALLOW_DIRECT_ROUTING.bindTo(controller.flagSource());
}
public RoutingPolicies policies() {
@@ -83,9 +95,12 @@ public class RoutingController {
.on(Port.fromRoutingMethod(RoutingMethod.shared))
.in(controller.system())));
boolean hasSharedEndpoint = !endpoints.isEmpty();
+ // 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;
if (hasSharedEndpoint && routingMethod == RoutingMethod.shared) continue;
endpoints.add(policy.endpointIn(controller.system(), routingMethod));
}
@@ -113,7 +128,7 @@ public class RoutingController {
.requiresRotation()
.forEach(endpoints::add);
}
- // Add global endpoints provided by routing policices
+ // Add global endpoints provided by routing policies
var zonesByRoutingId = new LinkedHashMap<RoutingId, List<ZoneId>>();
for (var policy : routingPolicies.get(instance.id()).values()) {
if (!policy.status().isActive()) continue;
@@ -249,4 +264,30 @@ public class RoutingController {
return Collections.unmodifiableList(routingMethods);
}
+ /** Returns whether traffic can be directly routed to given deployment */
+ private boolean canRouteDirectlyTo(DeploymentId deploymentId, Application application) {
+ if (controller.system().isPublic()) return true; // Public always supports direct routing
+
+ // Check Athenz service presence. The test framework uses this identity when sending requests to the
+ // deployment's container(s).
+ var athenzService = application.deploymentSpec().instance(deploymentId.applicationId().instance())
+ .flatMap(instance -> instance.athenzService(deploymentId.zoneId().environment(),
+ deploymentId.zoneId().region()));
+ if (athenzService.isEmpty()) return false;
+
+ // Check minimum required compile-version
+ var instance = application.require(deploymentId.applicationId().instance());
+ var compileVersion = Optional.ofNullable(instance.deployments().get(deploymentId.zoneId()))
+ .map(Deployment::applicationVersion)
+ .flatMap(ApplicationVersion::compileVersion);
+ if (compileVersion.isEmpty()) return false;
+ if (compileVersion.get().isBefore(DIRECT_ROUTING_MIN_VERSION)) return false;
+
+ // Check feature flag
+ // TODO(mpolden): Remove once we make this default
+ return this.allowDirectRouting.with(FetchVector.Dimension.APPLICATION_ID,
+ deploymentId.applicationId().serializedForm())
+ .value();
+ }
+
}
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 b58dd0dd08e..06cf13fe7db 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
@@ -6,6 +6,8 @@ import com.yahoo.component.Version;
import com.yahoo.config.application.api.DeploymentSpec;
import com.yahoo.config.application.api.ValidationId;
import com.yahoo.config.application.api.ValidationOverrides;
+import com.yahoo.config.provision.AthenzDomain;
+import com.yahoo.config.provision.AthenzService;
import com.yahoo.config.provision.CloudName;
import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.RegionName;
@@ -13,6 +15,8 @@ import com.yahoo.config.provision.SystemName;
import com.yahoo.config.provision.TenantName;
import com.yahoo.config.provision.zone.RoutingMethod;
import com.yahoo.config.provision.zone.ZoneId;
+import com.yahoo.vespa.flags.Flags;
+import com.yahoo.vespa.flags.InMemoryFlagSource;
import com.yahoo.vespa.hosted.controller.api.application.v4.model.DeployOptions;
import com.yahoo.vespa.hosted.controller.api.application.v4.model.EndpointStatus;
import com.yahoo.vespa.hosted.controller.api.identifiers.DeploymentId;
@@ -26,6 +30,7 @@ import com.yahoo.vespa.hosted.controller.application.ApplicationPackage;
import com.yahoo.vespa.hosted.controller.application.AssignedRotation;
import com.yahoo.vespa.hosted.controller.application.Deployment;
import com.yahoo.vespa.hosted.controller.application.DeploymentMetrics;
+import com.yahoo.vespa.hosted.controller.application.Endpoint;
import com.yahoo.vespa.hosted.controller.application.SystemApplication;
import com.yahoo.vespa.hosted.controller.deployment.ApplicationPackageBuilder;
import com.yahoo.vespa.hosted.controller.deployment.DeploymentContext;
@@ -42,6 +47,7 @@ import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
+import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -697,7 +703,9 @@ public class ControllerTest {
var context1 = tester.newDeploymentContext("tenant1", "app1", "default");
var prodZone = ZoneId.from("prod", "us-west-1");
tester.controllerTester().zoneRegistry().exclusiveRoutingIn(ZoneApiMock.from(prodZone));
- var applicationPackage = new ApplicationPackageBuilder().environment(prodZone.environment())
+ var applicationPackage = new ApplicationPackageBuilder().athenzIdentity(AthenzDomain.from("domain"), AthenzService.from("service"))
+ .compileVersion(RoutingController.DIRECT_ROUTING_MIN_VERSION)
+ .environment(prodZone.environment())
.region(prodZone.region())
.build();
// Deploy app1 in production
@@ -847,4 +855,40 @@ public class ControllerTest {
assertEquals(expectedRecords, List.copyOf(tester.controllerTester().nameService().records()));
}
+ @Test
+ public void testDirectRoutingSupport() {
+ var context = tester.newDeploymentContext();
+ var zone = ZoneId.from("prod", "us-west-1");
+ var applicationPackageBuilder = new ApplicationPackageBuilder()
+ .region(zone.region());
+ tester.controllerTester().zoneRegistry().setRoutingMethod(ZoneApiMock.from(zone), RoutingMethod.shared, RoutingMethod.sharedLayer4);
+ Supplier<Set<RoutingMethod>> routingMethods = () -> tester.controller().routing().endpointsOf(context.deploymentIdIn(zone))
+ .asList()
+ .stream()
+ .map(Endpoint::routingMethod)
+ .collect(Collectors.toSet());
+ ((InMemoryFlagSource) tester.controller().flagSource()).withBooleanFlag(Flags.ALLOW_DIRECT_ROUTING.id(), false);
+
+ // Without everything
+ context.submit(applicationPackageBuilder.build()).deploy();
+ assertEquals(Set.of(RoutingMethod.shared), routingMethods.get());
+
+ // Without Athenz service
+ context.submit(applicationPackageBuilder.compileVersion(RoutingController.DIRECT_ROUTING_MIN_VERSION).build())
+ .deploy();
+ assertEquals(Set.of(RoutingMethod.shared), routingMethods.get());
+
+ // Without feature flag
+ var applicationPackage = applicationPackageBuilder.compileVersion(RoutingController.DIRECT_ROUTING_MIN_VERSION)
+ .athenzIdentity(AthenzDomain.from("domain"), AthenzService.from("service"))
+ .build();
+ context.submit(applicationPackage).deploy();
+ assertEquals(Set.of(RoutingMethod.shared), routingMethods.get());
+
+ // With everything required
+ ((InMemoryFlagSource) tester.controller().flagSource()).withBooleanFlag(Flags.ALLOW_DIRECT_ROUTING.id(), true);
+ context.submit(applicationPackage).deploy();
+ assertEquals(Set.of(RoutingMethod.shared, RoutingMethod.sharedLayer4), routingMethods.get());
+ }
+
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/ApplicationPackageBuilder.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/ApplicationPackageBuilder.java
index 58175762129..2f2b1fbb364 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/ApplicationPackageBuilder.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/ApplicationPackageBuilder.java
@@ -1,6 +1,7 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller.deployment;
+import com.yahoo.component.Version;
import com.yahoo.config.application.api.ValidationId;
import com.yahoo.config.provision.AthenzDomain;
import com.yahoo.config.provision.AthenzService;
@@ -57,6 +58,7 @@ public class ApplicationPackageBuilder {
private String searchDefinition = "search test { }";
private boolean explicitSystemTest = false;
private boolean explicitStagingTest = false;
+ private Version compileVersion = Version.fromString("6.1");
public ApplicationPackageBuilder majorVersion(int majorVersion) {
this.majorVersion = OptionalInt.of(majorVersion);
@@ -164,6 +166,11 @@ public class ApplicationPackageBuilder {
return this;
}
+ public ApplicationPackageBuilder compileVersion(Version version) {
+ compileVersion = version;
+ return this;
+ }
+
public ApplicationPackageBuilder athenzIdentity(AthenzDomain domain, AthenzService service) {
this.athenzIdentityAttributes = String.format("athenz-domain='%s' athenz-service='%s'", domain.value(),
service.value());
@@ -260,8 +267,8 @@ public class ApplicationPackageBuilder {
return searchDefinition.getBytes(UTF_8);
}
- private static byte[] buildMeta() {
- return "{\"compileVersion\":\"6.1\",\"buildTime\":1000}".getBytes(UTF_8);
+ private static byte[] buildMeta(Version compileVersion) {
+ return ("{\"compileVersion\":\"" + compileVersion.toFullString() + "\",\"buildTime\":1000}").getBytes(UTF_8);
}
public ApplicationPackage build() {
@@ -285,7 +292,7 @@ public class ApplicationPackageBuilder {
out.write(searchDefinition());
out.closeEntry();
out.putNextEntry(new ZipEntry(dir + "build-meta.json"));
- out.write(buildMeta());
+ out.write(buildMeta(compileVersion));
out.closeEntry();
out.putNextEntry(new ZipEntry(dir + "security/clients.pem"));
out.write(X509CertificateUtils.toPem(trustedCertificates).getBytes(UTF_8));
@@ -307,7 +314,7 @@ public class ApplicationPackageBuilder {
out.write(deploymentXml.getBytes(UTF_8));
out.closeEntry();
out.putNextEntry(new ZipEntry("build-meta.json"));
- out.write(buildMeta());
+ out.write(buildMeta(Version.fromString("6.1")));
out.closeEntry();
} catch (IOException e) {
throw new UncheckedIOException(e);
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentContext.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentContext.java
index 4550b29d2fd..706a7cec2a9 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentContext.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentContext.java
@@ -13,6 +13,8 @@ import com.yahoo.security.KeyAlgorithm;
import com.yahoo.security.KeyUtils;
import com.yahoo.security.SignatureAlgorithm;
import com.yahoo.security.X509CertificateBuilder;
+import com.yahoo.vespa.flags.Flags;
+import com.yahoo.vespa.flags.InMemoryFlagSource;
import com.yahoo.vespa.hosted.controller.Application;
import com.yahoo.vespa.hosted.controller.ControllerTester;
import com.yahoo.vespa.hosted.controller.Instance;
@@ -91,6 +93,7 @@ public class DeploymentContext {
.emailAddress("b@a")
.trust(generateCertificate())
.build();
+
public static final SourceRevision defaultSourceRevision = new SourceRevision("repository1", "master", "commit1");
private final TenantAndApplicationId applicationId;
@@ -104,7 +107,6 @@ public class DeploymentContext {
private boolean deferDnsUpdates = false;
public DeploymentContext(ApplicationId instanceId, DeploymentTester tester) {
-
this.applicationId = TenantAndApplicationId.from(instanceId);
this.instanceId = instanceId;
this.testerId = TesterId.of(instanceId);
@@ -112,6 +114,7 @@ public class DeploymentContext {
this.runner = tester.runner();
this.tester = tester;
createTenantAndApplication();
+ ((InMemoryFlagSource) tester.controller().flagSource()).withBooleanFlag(Flags.ALLOW_DIRECT_ROUTING.id(), true);
}
private void createTenantAndApplication() {
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTriggerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTriggerTest.java
index d2835c8b830..2b5e8b3e91c 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTriggerTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTriggerTest.java
@@ -1087,7 +1087,7 @@ public class DeploymentTriggerTest {
services.zoneRegistry()
.setSystemName(SystemName.cd)
.setZones(zones)
- .setRoutingMethod(zones, RoutingMethod.exclusive);
+ .setRoutingMethod(zones, RoutingMethod.shared);
tester = new DeploymentTester(new ControllerTester(services));
tester.configServer().bootstrap(services.zoneRegistry().zones().all().ids(), SystemApplication.values());
tester.controllerTester().upgradeSystem(Version.fromString("6.1"));
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunnerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunnerTest.java
index a3d1b9adb35..21b6e729e41 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunnerTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunnerTest.java
@@ -4,6 +4,8 @@ package com.yahoo.vespa.hosted.controller.deployment;
import com.google.common.collect.ImmutableList;
import com.yahoo.component.Version;
import com.yahoo.config.application.api.DeploymentSpec;
+import com.yahoo.config.provision.AthenzDomain;
+import com.yahoo.config.provision.AthenzService;
import com.yahoo.config.provision.HostName;
import com.yahoo.config.provision.NodeResources;
import com.yahoo.config.provision.SystemName;
@@ -11,6 +13,7 @@ import com.yahoo.config.provision.zone.RoutingMethod;
import com.yahoo.config.provision.zone.ZoneId;
import com.yahoo.slime.Inspector;
import com.yahoo.slime.SlimeUtils;
+import com.yahoo.vespa.hosted.controller.RoutingController;
import com.yahoo.vespa.hosted.controller.api.application.v4.model.configserverbindings.ConfigChangeActions;
import com.yahoo.vespa.hosted.controller.api.application.v4.model.configserverbindings.RefeedAction;
import com.yahoo.vespa.hosted.controller.api.application.v4.model.configserverbindings.RestartAction;
@@ -258,7 +261,16 @@ public class InternalStepRunnerTest {
var systemTestZone = JobType.systemTest.zone(system());
var stagingZone = JobType.stagingTest.zone(system());
tester.controllerTester().zoneRegistry().exclusiveRoutingIn(ZoneApiMock.from(systemTestZone), ZoneApiMock.from(stagingZone));
- app.newRun(JobType.systemTest);
+ var applicationPackage = new ApplicationPackageBuilder()
+ .athenzIdentity(AthenzDomain.from("domain"), AthenzService.from("service"))
+ .upgradePolicy("default")
+ .region("us-central-1")
+ .parallel("us-west-1", "us-east-3")
+ .compileVersion(RoutingController.DIRECT_ROUTING_MIN_VERSION)
+ .build();
+ app.submit(applicationPackage)
+ .triggerJobs();
+
tester.runner().run();
assertEquals(unfinished, tester.jobs().last(app.instanceId(), JobType.systemTest).get().stepStatuses().get(Step.installReal));
assertEquals(unfinished, tester.jobs().last(app.instanceId(), JobType.systemTest).get().stepStatuses().get(Step.installTester));
@@ -266,7 +278,7 @@ public class InternalStepRunnerTest {
app.flushDnsUpdates();
tester.configServer().convergeServices(app.instanceId(), JobType.systemTest.zone(system()));
tester.configServer().convergeServices(app.testerId().id(), JobType.systemTest.zone(system()));
- tester.runner().run();;
+ tester.runner().run();
assertEquals(succeeded, tester.jobs().last(app.instanceId(), JobType.systemTest).get().stepStatuses().get(Step.installReal));
assertEquals(succeeded, tester.jobs().last(app.instanceId(), JobType.systemTest).get().stepStatuses().get(Step.installTester));
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java
index b6f4fa22984..c83961e315a 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java
@@ -24,6 +24,7 @@ import com.yahoo.vespa.hosted.controller.Application;
import com.yahoo.vespa.hosted.controller.ControllerTester;
import com.yahoo.vespa.hosted.controller.Instance;
import com.yahoo.vespa.hosted.controller.LockedTenant;
+import com.yahoo.vespa.hosted.controller.RoutingController;
import com.yahoo.vespa.hosted.controller.api.application.v4.EnvironmentResource;
import com.yahoo.vespa.hosted.controller.api.application.v4.model.DeployOptions;
import com.yahoo.vespa.hosted.controller.api.identifiers.DeploymentId;
@@ -1503,6 +1504,8 @@ public class ApplicationApiTest extends ControllerContainerTest {
deploymentTester.controllerTester().zoneRegistry().setRoutingMethod(ZoneApiMock.from(zone),
List.of(RoutingMethod.exclusive, RoutingMethod.shared));
ApplicationPackage applicationPackage = new ApplicationPackageBuilder()
+ .athenzIdentity(com.yahoo.config.provision.AthenzDomain.from("domain"), AthenzService.from("service"))
+ .compileVersion(RoutingController.DIRECT_ROUTING_MIN_VERSION)
.environment(Environment.prod)
.instances("instance1")
.region(zone.region().value())
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/routing/RoutingApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/routing/RoutingApiTest.java
index f079bd1d7e6..fefd23eb67c 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/routing/RoutingApiTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/routing/RoutingApiTest.java
@@ -2,9 +2,12 @@
package com.yahoo.vespa.hosted.controller.restapi.routing;
import com.yahoo.application.container.handler.Request;
+import com.yahoo.config.provision.AthenzDomain;
+import com.yahoo.config.provision.AthenzService;
import com.yahoo.config.provision.zone.RoutingMethod;
import com.yahoo.config.provision.zone.ZoneId;
import com.yahoo.vespa.hosted.controller.ControllerTester;
+import com.yahoo.vespa.hosted.controller.RoutingController;
import com.yahoo.vespa.hosted.controller.deployment.ApplicationPackageBuilder;
import com.yahoo.vespa.hosted.controller.deployment.DeploymentTester;
import com.yahoo.vespa.hosted.controller.integration.ZoneApiMock;
@@ -126,6 +129,8 @@ public class RoutingApiTest extends ControllerContainerTest {
ZoneApiMock.from(eastZone));
// Deploy application
var applicationPackage = new ApplicationPackageBuilder()
+ .athenzIdentity(AthenzDomain.from("domain"), AthenzService.from("service"))
+ .compileVersion(RoutingController.DIRECT_ROUTING_MIN_VERSION)
.region(westZone.region())
.region(eastZone.region())
.endpoint("default", "default", eastZone.region().value(), westZone.region().value())
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 732ea9bff31..719b2cc47f9 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
@@ -5,6 +5,8 @@ import com.google.common.collect.Sets;
import com.yahoo.config.application.api.DeploymentSpec;
import com.yahoo.config.application.api.ValidationId;
import com.yahoo.config.provision.ApplicationId;
+import com.yahoo.config.provision.AthenzDomain;
+import com.yahoo.config.provision.AthenzService;
import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.HostName;
@@ -14,6 +16,7 @@ import com.yahoo.config.provision.zone.RoutingMethod;
import com.yahoo.config.provision.zone.ZoneId;
import com.yahoo.vespa.hosted.controller.ControllerTester;
import com.yahoo.vespa.hosted.controller.Instance;
+import com.yahoo.vespa.hosted.controller.RoutingController;
import com.yahoo.vespa.hosted.controller.api.application.v4.model.DeployOptions;
import com.yahoo.vespa.hosted.controller.api.integration.configserver.LoadBalancer;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.JobType;
@@ -57,10 +60,9 @@ public class RoutingPoliciesTest {
private final ZoneId zone2 = ZoneId.from("prod", "us-central-1");
private final ZoneId zone3 = ZoneId.from("prod", "us-east-3");
- private final ApplicationPackage applicationPackage = new ApplicationPackageBuilder()
- .region(zone1.region())
- .region(zone2.region())
- .build();
+ private final ApplicationPackage applicationPackage = applicationPackageBuilder().region(zone1.region())
+ .region(zone2.region())
+ .build();
@Test
public void global_routing_policies() {
@@ -69,7 +71,7 @@ public class RoutingPoliciesTest {
var context2 = tester.newDeploymentContext("tenant1", "app2", "default");
int clustersPerZone = 2;
int numberOfDeployments = 2;
- var applicationPackage = new ApplicationPackageBuilder()
+ var applicationPackage = applicationPackageBuilder()
.region(zone1.region())
.region(zone2.region())
.endpoint("r0", "c0")
@@ -88,7 +90,7 @@ public class RoutingPoliciesTest {
tester.policiesOf(context1.instance().id()).size());
// Applications gains a new deployment
- ApplicationPackage applicationPackage2 = new ApplicationPackageBuilder()
+ ApplicationPackage applicationPackage2 = applicationPackageBuilder()
.region(zone1.region())
.region(zone2.region())
.region(zone3.region())
@@ -108,7 +110,7 @@ public class RoutingPoliciesTest {
// Another application is deployed with a single cluster and global endpoint
var endpoint4 = "r0.app2.tenant1.global.vespa.oath.cloud";
tester.provisionLoadBalancers(1, context2.instanceId(), zone1, zone2);
- var applicationPackage3 = new ApplicationPackageBuilder()
+ var applicationPackage3 = applicationPackageBuilder()
.region(zone1.region())
.region(zone2.region())
.endpoint("r0", "c0")
@@ -117,7 +119,7 @@ public class RoutingPoliciesTest {
tester.assertTargets(context2.instanceId(), EndpointId.of("r0"), 0, zone1, zone2);
// All endpoints for app1 are removed
- ApplicationPackage applicationPackage4 = new ApplicationPackageBuilder()
+ ApplicationPackage applicationPackage4 = applicationPackageBuilder()
.region(zone1.region())
.region(zone2.region())
.region(zone3.region())
@@ -231,7 +233,7 @@ public class RoutingPoliciesTest {
var context = tester.newDeploymentContext("tenant1", "app1", "default");
tester.provisionLoadBalancers(1, context.instanceId(), zone1, zone2);
- var applicationPackage = new ApplicationPackageBuilder()
+ var applicationPackage = applicationPackageBuilder()
.region(zone1.region().value())
.endpoint("r0", "c0")
.build();
@@ -300,7 +302,7 @@ public class RoutingPoliciesTest {
// Initial load balancer is provisioned
tester.provisionLoadBalancers(1, context.instanceId(), zone1);
- var applicationPackage = new ApplicationPackageBuilder()
+ var applicationPackage = applicationPackageBuilder()
.region(zone1.region())
.build();
@@ -341,7 +343,7 @@ public class RoutingPoliciesTest {
// Provision load balancers and deploy application
tester.provisionLoadBalancers(1, context.instanceId(), zone1, zone2);
- var applicationPackage = new ApplicationPackageBuilder()
+ var applicationPackage = applicationPackageBuilder()
.region(zone1.region())
.region(zone2.region())
.endpoint("r0", "c0", zone1.region().value(), zone2.region().value())
@@ -395,7 +397,7 @@ public class RoutingPoliciesTest {
assertEquals(changedAt.truncatedTo(ChronoUnit.MILLIS), policy1.status().globalRouting().changedAt());
// Deployment is set out through a new deployment.xml
- var applicationPackage2 = new ApplicationPackageBuilder()
+ var applicationPackage2 = applicationPackageBuilder()
.region(zone1.region())
.region(zone2.region(), false)
.endpoint("r0", "c0", zone1.region().value(), zone2.region().value())
@@ -406,7 +408,7 @@ public class RoutingPoliciesTest {
tester.assertTargets(context.instanceId(), EndpointId.of("r1"), 0, zone1);
// ... back in
- var applicationPackage3 = new ApplicationPackageBuilder()
+ var applicationPackage3 = applicationPackageBuilder()
.region(zone1.region())
.region(zone2.region())
.endpoint("r0", "c0", zone1.region().value(), zone2.region().value())
@@ -425,7 +427,7 @@ public class RoutingPoliciesTest {
var contexts = List.of(context1, context2);
// Deploy applications
- var applicationPackage = new ApplicationPackageBuilder()
+ var applicationPackage = applicationPackageBuilder()
.region(zone1.region())
.region(zone2.region())
.endpoint("default", "c0", zone1.region().value(), zone2.region().value())
@@ -493,7 +495,7 @@ public class RoutingPoliciesTest {
var context = tester.tester.newDeploymentContext();
var endpointId = EndpointId.of("r0");
- var applicationPackage = new ApplicationPackageBuilder()
+ var applicationPackage = applicationPackageBuilder()
.trustDefaultCertificate()
.region(sharedRegion)
.endpoint(endpointId.id(), "default")
@@ -523,7 +525,7 @@ public class RoutingPoliciesTest {
// Provision load balancers and deploy application
tester.provisionLoadBalancers(1, context.instanceId(), zone1, zone2);
- var applicationPackage = new ApplicationPackageBuilder()
+ var applicationPackage = applicationPackageBuilder()
.region(zone1.region())
.region(zone2.region())
.endpoint("r0", "c0", zone1.region().value(), zone2.region().value())
@@ -571,6 +573,13 @@ public class RoutingPoliciesTest {
}
tester.assertTargets(context.instanceId(), EndpointId.of("r0"), 0, zone1, zone2);
}
+
+ /** Returns an application package builder that satisfies requirements for a directly routed endpoint */
+ private static ApplicationPackageBuilder applicationPackageBuilder() {
+ return new ApplicationPackageBuilder()
+ .athenzIdentity(AthenzDomain.from("domain"), AthenzService.from("service"))
+ .compileVersion(RoutingController.DIRECT_ROUTING_MIN_VERSION);
+ }
private static List<LoadBalancer> createLoadBalancers(ZoneId zone, ApplicationId application, int count) {
List<LoadBalancer> loadBalancers = new ArrayList<>();
diff --git a/flags/src/main/java/com/yahoo/vespa/flags/Flags.java b/flags/src/main/java/com/yahoo/vespa/flags/Flags.java
index 7d1da56a5dc..5a5fbb6bc9a 100644
--- a/flags/src/main/java/com/yahoo/vespa/flags/Flags.java
+++ b/flags/src/main/java/com/yahoo/vespa/flags/Flags.java
@@ -267,6 +267,12 @@ public class Flags {
"Takes effect on internal redeploy",
APPLICATION_ID);
+ public static final UnboundBooleanFlag ALLOW_DIRECT_ROUTING = defineFeatureFlag(
+ "publish-direct-routing-endpoint", false,
+ "Whether an application should receive a directly routed endpoint in its endpoint list",
+ "Takes effect immediately",
+ APPLICATION_ID);
+
/** WARNING: public for testing: All flags should be defined in {@link Flags}. */
public static UnboundBooleanFlag defineFeatureFlag(String flagId, boolean defaultValue, String description,
String modificationEffect, FetchVector.Dimension... dimensions) {