summaryrefslogtreecommitdiffstats
path: root/controller-server
diff options
context:
space:
mode:
authorMartin Polden <mpolden@mpolden.no>2021-05-10 09:23:20 +0200
committerGitHub <noreply@github.com>2021-05-10 09:23:20 +0200
commitef7e0dec2c3fb3e8390bdb7a278bf7ad89bf549f (patch)
treeb1f758a27eb1d3a024a6b60491eeb8c4aa38d734 /controller-server
parent82f6ea0f659f75171992a53b3608705e1a7c2234 (diff)
parent1e9a37784e2150a1ccec021f14708b7b592e7de4 (diff)
Merge pull request #17776 from vespa-engine/mpolden/new-endpoints
Register new endpoints in DNS
Diffstat (limited to 'controller-server')
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/RoutingController.java10
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/Endpoint.java23
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ControllerMaintenance.java6
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java12
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/routing/RoutingPolicies.java79
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/routing/RoutingPolicy.java51
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java4
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTester.java22
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/application/EndpointTest.java49
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/ApplicationPackageBuilder.java9
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTriggerTest.java22
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java6
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/deployment-cloud.json5
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/deployment-with-routing-policy-legacy.json71
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/deployment-with-routing-policy.json6
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/deployment-without-shared-endpoints.json3
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/deployment.json6
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/dev-us-east-1.json3
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/prod-us-central-1.json6
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/rotation/RotationRepositoryTest.java4
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/routing/RoutingPoliciesTest.java121
21 files changed, 380 insertions, 138 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 52ad813d7cc..433b2b340d5 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
@@ -96,7 +96,7 @@ public class RoutingController {
for (var routingMethod : controller.zoneRegistry().routingMethods(policy.id().zone())) {
if (routingMethod.isDirect() && !isSystemApplication && !canRouteDirectlyTo(deployment, application.get())) continue;
endpoints.addAll(policy.endpointsIn(controller.system(), routingMethod, controller.zoneRegistry()));
- endpoints.add(policy.regionEndpointIn(controller.system(), routingMethod));
+ endpoints.addAll(policy.regionEndpointsIn(controller.system(), routingMethod));
}
}
return EndpointList.copyOf(endpoints);
@@ -315,6 +315,14 @@ public class RoutingController {
.on(Port.fromRoutingMethod(method))
.routingMethod(method)
.in(controller.system()));
+ if (controller.system().isPublic()) {
+ endpoints.add(Endpoint.of(routingId.application())
+ .target(routingId.endpointId(), cluster, zones)
+ .on(Port.fromRoutingMethod(method))
+ .routingMethod(method)
+ .legacy()
+ .in(controller.system()));
+ }
// Add legacy endpoints
if (legacyNamesAvailable && method == RoutingMethod.shared) {
endpoints.add(Endpoint.of(routingId.application())
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 cc1a0a455c4..3f079a5fb9b 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
@@ -28,6 +28,10 @@ public class Endpoint {
private static final String OATH_DNS_SUFFIX = ".vespa.oath.cloud";
private static final String PUBLIC_DNS_SUFFIX = ".public.vespa.oath.cloud";
private static final String PUBLIC_CD_DNS_SUFFIX = ".public-cd.vespa.oath.cloud";
+ // TODO(mpolden): New domain is considered "legacy" for the time being, until it's ready for use. Once it's ready
+ // we'll make the vespa.oath.cloud variant legacy and this non-legacy.
+ private static final String PUBLIC_DNS_LEGACY_SUFFIX = ".vespa-app.cloud";
+ private static final String PUBLIC_CD_LEGACY_DNS_SUFFIX = ".cd.vespa-app.cloud";
private final EndpointId id;
private final ClusterSpec.Id cluster;
@@ -173,13 +177,13 @@ public class Endpoint {
String portPart = port.isDefault() ? "" : ":" + port.port;
return URI.create(scheme + "://" +
sanitize(namePart(name, separator)) +
- systemPart(system, separator) +
+ systemPart(system, separator, legacy) +
sanitize(instancePart(application, separator)) +
sanitize(application.application().value()) +
separator +
sanitize(application.tenant().value()) +
"." +
- scopePart(scope, zones, legacy) +
+ scopePart(scope, zones, legacy, system) +
dnsSuffix(system, legacy) +
portPart +
"/");
@@ -201,7 +205,15 @@ public class Endpoint {
return name + separator;
}
- private static String scopePart(Scope scope, List<ZoneId> zones, boolean legacy) {
+ private static String scopePart(Scope scope, List<ZoneId> zones, boolean legacy, SystemName system) {
+ if (system.isPublic() && legacy) {
+ if (scope == Scope.global) return "g";
+ var zone = zones.get(0);
+ var region = zone.region().value();
+ char scopeSymbol = scope == Scope.region ? 'r' : 'z';
+ String environment = zone.environment().isProduction() ? "" : "." + zone.environment().value();
+ return region + environment + "." + scopeSymbol;
+ }
if (scope == Scope.global) return "global";
var zone = zones.get(0);
var region = zone.region().value();
@@ -215,8 +227,9 @@ public class Endpoint {
return application.instance().value() + separator;
}
- private static String systemPart(SystemName system, String separator) {
+ private static String systemPart(SystemName system, String separator, boolean legacy) {
if (!system.isCd()) return "";
+ if (system.isPublic() && legacy) return "";
return system.value() + separator;
}
@@ -227,8 +240,10 @@ public class Endpoint {
if (legacy) return YAHOO_DNS_SUFFIX;
return OATH_DNS_SUFFIX;
case Public:
+ if (legacy) return PUBLIC_DNS_LEGACY_SUFFIX;
return PUBLIC_DNS_SUFFIX;
case PublicCd:
+ if (legacy) return PUBLIC_CD_LEGACY_DNS_SUFFIX;
return PUBLIC_CD_DNS_SUFFIX;
default: throw new IllegalArgumentException("No DNS suffix declared for system " + system);
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ControllerMaintenance.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ControllerMaintenance.java
index 015da1faae8..0491cf61ef3 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ControllerMaintenance.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ControllerMaintenance.java
@@ -61,7 +61,7 @@ public class ControllerMaintenance extends AbstractComponent {
maintainers.add(new SystemRoutingPolicyMaintainer(controller, intervals.systemRoutingPolicyMaintainer));
maintainers.add(new ApplicationMetaDataGarbageCollector(controller, intervals.applicationMetaDataGarbageCollector));
maintainers.add(new ContainerImageExpirer(controller, intervals.containerImageExpirer));
- maintainers.add(new HostInfoUpdater(controller, intervals.hostSwitchUpdater));
+ maintainers.add(new HostInfoUpdater(controller, intervals.hostInfoUpdater));
maintainers.add(new ReindexingTriggerer(controller, intervals.reindexingTriggerer));
maintainers.add(new EndpointCertificateMaintainer(controller, intervals.endpointCertificateMaintainer));
maintainers.add(new TrafficShareUpdater(controller, intervals.trafficFractionUpdater));
@@ -116,7 +116,7 @@ public class ControllerMaintenance extends AbstractComponent {
private final Duration systemRoutingPolicyMaintainer;
private final Duration applicationMetaDataGarbageCollector;
private final Duration containerImageExpirer;
- private final Duration hostSwitchUpdater;
+ private final Duration hostInfoUpdater;
private final Duration reindexingTriggerer;
private final Duration endpointCertificateMaintainer;
private final Duration trafficFractionUpdater;
@@ -148,7 +148,7 @@ public class ControllerMaintenance extends AbstractComponent {
this.systemRoutingPolicyMaintainer = duration(10, MINUTES);
this.applicationMetaDataGarbageCollector = duration(12, HOURS);
this.containerImageExpirer = duration(12, HOURS);
- this.hostSwitchUpdater = duration(12, HOURS);
+ this.hostInfoUpdater = duration(12, HOURS);
this.reindexingTriggerer = duration(1, HOURS);
this.endpointCertificateMaintainer = duration(12, HOURS);
this.trafficFractionUpdater = duration(5, MINUTES);
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
index 2a7132c08d6..ae4d891069c 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
@@ -1308,6 +1308,7 @@ public class ApplicationApiHandler extends AuditLoggingRequestHandler {
object.setString("url", endpoint.url().toString());
object.setString("scope", endpointScopeString(endpoint.scope()));
object.setString("routingMethod", routingMethodString(endpoint.routingMethod()));
+ object.setBool("legacy", endpoint.legacy());
}
private void toSlime(Cursor response, DeploymentId deploymentId, Deployment deployment, HttpRequest request) {
@@ -1319,17 +1320,22 @@ public class ApplicationApiHandler extends AuditLoggingRequestHandler {
var application = controller.applications().requireApplication(TenantAndApplicationId.from(deploymentId.applicationId()));
// Add zone endpoints
+ boolean legacyEndpoints = request.getBooleanProperty("includeLegacyEndpoints");
var endpointArray = response.setArray("endpoints");
EndpointList zoneEndpoints = controller.routing().endpointsOf(deploymentId)
- .scope(Endpoint.Scope.zone)
- .not().legacy();
+ .scope(Endpoint.Scope.zone);
+ if (!legacyEndpoints) {
+ zoneEndpoints = zoneEndpoints.not().legacy();
+ }
for (var endpoint : controller.routing().directEndpoints(zoneEndpoints, deploymentId.applicationId())) {
toSlime(endpoint, endpointArray.addObject());
}
// Add global endpoints
EndpointList globalEndpoints = controller.routing().endpointsOf(application, deploymentId.applicationId().instance())
- .not().legacy()
.targets(deploymentId.zoneId());
+ if (!legacyEndpoints) {
+ globalEndpoints = globalEndpoints.not().legacy();
+ }
for (var endpoint : controller.routing().directEndpoints(globalEndpoints, deploymentId.applicationId())) {
toSlime(endpoint, endpointArray.addObject());
}
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 0d1469a61fc..e2a8be15361 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
@@ -119,54 +119,63 @@ public class RoutingPolicies {
}
}
- /** Update global DNS record for given policies */
+ /** Update global DNS records for given policies */
private void updateGlobalDnsOf(Collection<RoutingPolicy> routingPolicies, Set<ZoneId> inactiveZones, @SuppressWarnings("unused") Lock lock) {
Map<RoutingId, List<RoutingPolicy>> routingTable = routingTableFrom(routingPolicies);
for (Map.Entry<RoutingId, List<RoutingPolicy>> routeEntry : routingTable.entrySet()) {
- Collection<RegionEndpoint> regionEndpoints = computeRegionEndpoints(routeEntry.getValue(), inactiveZones);
- // Create a weighted ALIAS per region, pointing to all zones within the same region
- regionEndpoints.forEach(regionEndpoint -> {
- controller.nameServiceForwarder().createAlias(RecordName.from(regionEndpoint.target().name().value()),
- Collections.unmodifiableSet(regionEndpoint.zoneTargets()),
- Priority.normal);
- });
-
- // Create global latency-based ALIAS pointing to each per-region weighted ALIAS
- Set<AliasTarget> latencyTargets = new LinkedHashSet<>();
- Set<AliasTarget> inactiveLatencyTargets = new LinkedHashSet<>();
- for (var regionEndpoint : regionEndpoints) {
- if (regionEndpoint.active()) {
- latencyTargets.add(regionEndpoint.target());
- } else {
- inactiveLatencyTargets.add(regionEndpoint.target());
- }
- }
- // If all targets are configured out, all targets are set in. We do this because otherwise removing 100% of
- // the ALIAS records would cause the global endpoint to stop resolving entirely (NXDOMAIN).
- if (latencyTargets.isEmpty() && !inactiveLatencyTargets.isEmpty()) {
- latencyTargets.addAll(inactiveLatencyTargets);
- inactiveLatencyTargets.clear();
+ RoutingId routingId = routeEntry.getKey();
+ controller.routing().endpointsOf(routingId.application())
+ .named(routingId.endpointId())
+ .not().requiresRotation()
+ .forEach(endpoint -> updateGlobalDnsOf(endpoint, inactiveZones, routeEntry.getValue()));
+ }
+ }
+
+ /** Update global DNS records for given global endpoint */
+ private void updateGlobalDnsOf(Endpoint endpoint, Set<ZoneId> inactiveZones, List<RoutingPolicy> policies) {
+ if (endpoint.scope() != Endpoint.Scope.global) throw new IllegalArgumentException("Endpoint " + endpoint + " is not global");
+ // Create a weighted ALIAS per region, pointing to all zones within the same region
+ Collection<RegionEndpoint> regionEndpoints = computeRegionEndpoints(policies, inactiveZones, endpoint.legacy());
+ regionEndpoints.forEach(regionEndpoint -> {
+ controller.nameServiceForwarder().createAlias(RecordName.from(regionEndpoint.target().name().value()),
+ Collections.unmodifiableSet(regionEndpoint.zoneTargets()),
+ Priority.normal);
+ });
+
+ // Create global latency-based ALIAS pointing to each per-region weighted ALIAS
+ Set<AliasTarget> latencyTargets = new LinkedHashSet<>();
+ Set<AliasTarget> inactiveLatencyTargets = new LinkedHashSet<>();
+ for (var regionEndpoint : regionEndpoints) {
+ if (regionEndpoint.active()) {
+ latencyTargets.add(regionEndpoint.target());
+ } else {
+ inactiveLatencyTargets.add(regionEndpoint.target());
}
- var endpoints = controller.routing().endpointsOf(routeEntry.getKey().application())
- .named(routeEntry.getKey().endpointId())
- .not().requiresRotation();
- endpoints.forEach(endpoint -> controller.nameServiceForwarder().createAlias(RecordName.from(endpoint.dnsName()),
- latencyTargets, Priority.normal));
- inactiveLatencyTargets.forEach(t -> controller.nameServiceForwarder()
- .removeRecords(Record.Type.ALIAS,
- RecordData.fqdn(t.name().value()),
- Priority.normal));
}
+
+ // If all targets are configured OUT, all targets are kept IN. We do this because otherwise removing 100% of
+ // the ALIAS records would cause the global endpoint to stop resolving entirely (NXDOMAIN).
+ if (latencyTargets.isEmpty() && !inactiveLatencyTargets.isEmpty()) {
+ latencyTargets.addAll(inactiveLatencyTargets);
+ inactiveLatencyTargets.clear();
+ }
+
+ controller.nameServiceForwarder().createAlias(RecordName.from(endpoint.dnsName()), latencyTargets, Priority.normal);
+ inactiveLatencyTargets.forEach(t -> controller.nameServiceForwarder()
+ .removeRecords(Record.Type.ALIAS,
+ RecordData.fqdn(t.name().value()),
+ Priority.normal));
}
+
/** Compute region endpoints and their targets from given policies */
- private Collection<RegionEndpoint> computeRegionEndpoints(List<RoutingPolicy> policies, Set<ZoneId> inactiveZones) {
+ private Collection<RegionEndpoint> computeRegionEndpoints(List<RoutingPolicy> policies, Set<ZoneId> inactiveZones, boolean legacy) {
Map<Endpoint, RegionEndpoint> endpoints = new LinkedHashMap<>();
RoutingMethod routingMethod = RoutingMethod.exclusive;
for (var policy : policies) {
if (policy.dnsZone().isEmpty()) continue;
if (!controller.zoneRegistry().routingMethods(policy.id().zone()).contains(routingMethod)) continue;
- Endpoint regionEndpoint = policy.regionEndpointIn(controller.system(), routingMethod);
+ Endpoint regionEndpoint = policy.regionEndpointIn(controller.system(), routingMethod, legacy);
var zonePolicy = db.readZoneRoutingPolicy(policy.id().zone());
long weight = 1;
if (isConfiguredOut(policy, zonePolicy, inactiveZones)) {
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 3ece10337f1..ae33d214ecc 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
@@ -12,6 +12,7 @@ import com.yahoo.vespa.hosted.controller.application.EndpointId;
import com.yahoo.vespa.hosted.controller.application.SystemApplication;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
@@ -75,29 +76,45 @@ public class RoutingPolicy {
public List<Endpoint> endpointsIn(SystemName system, RoutingMethod routingMethod, ZoneRegistry zoneRegistry) {
Optional<Endpoint> infraEndpoint = SystemApplication.matching(id.owner())
.flatMap(app -> app.endpointIn(id.zone(), zoneRegistry));
- List<Endpoint> endpoints = new ArrayList<>(3);
if (infraEndpoint.isPresent()) {
- endpoints.add(infraEndpoint.get());
- } else {
- endpoints.add(endpoint(routingMethod).target(id.cluster(), id.zone()).in(system));
- // Add legacy endpoints
- if (routingMethod == RoutingMethod.shared) {
- endpoints.add(endpoint(routingMethod).target(id.cluster(), id.zone())
- .on(Port.plain(4080))
- .legacy()
- .in(system));
- endpoints.add(endpoint(routingMethod).target(id.cluster(), id.zone())
- .on(Port.tls(4443))
- .legacy()
- .in(system));
- }
+ return List.of(infraEndpoint.get());
+ }
+ List<Endpoint> endpoints = new ArrayList<>(3);
+ endpoints.add(endpoint(routingMethod).target(id.cluster(), id.zone()).in(system));
+ if (system.isPublic()) {
+ endpoints.add(endpoint(routingMethod).target(id.cluster(), id.zone()).legacy().in(system));
+ }
+ // Add legacy endpoints
+ if (routingMethod == RoutingMethod.shared) {
+ endpoints.add(endpoint(routingMethod).target(id.cluster(), id.zone())
+ .on(Port.plain(4080))
+ .legacy()
+ .in(system));
+ endpoints.add(endpoint(routingMethod).target(id.cluster(), id.zone())
+ .on(Port.tls(4443))
+ .legacy()
+ .in(system));
}
return endpoints;
}
+ /** Returns all region endpoints of this */
+ public List<Endpoint> regionEndpointsIn(SystemName system, RoutingMethod routingMethod) {
+ List<Endpoint> endpoints = new ArrayList<>(2);
+ endpoints.add(regionEndpointIn(system, routingMethod, false));
+ if (system.isPublic()) {
+ endpoints.add(regionEndpointIn(system, routingMethod, true));
+ }
+ return Collections.unmodifiableList(endpoints);
+ }
+
/** 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, boolean legacy) {
+ Endpoint.EndpointBuilder endpoint = endpoint(routingMethod).targetRegion(id.cluster(), id.zone());
+ if (legacy) {
+ endpoint = endpoint.legacy();
+ }
+ return endpoint.in(system);
}
@Override
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 422c856ca01..e52d1900a9d 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
@@ -599,7 +599,7 @@ public class ControllerTest {
var context = tester.newDeploymentContext();
ZoneId zone = ZoneId.from("dev", "us-east-1");
tester.controllerTester().zoneRegistry()
- .setRoutingMethod(ZoneApiMock.from(zone), RoutingMethod.shared, RoutingMethod.sharedLayer4);
+ .setRoutingMethod(ZoneApiMock.from(zone), RoutingMethod.shared, RoutingMethod.sharedLayer4);
// Deploy
context.runJob(zone, applicationPackage);
@@ -834,7 +834,7 @@ public class ControllerTest {
@Test
public void testDeploymentDirectRouting() {
// Rotation-less system
- DeploymentTester tester = new DeploymentTester(new ControllerTester(new RotationsConfig.Builder().build()));
+ DeploymentTester tester = new DeploymentTester(new ControllerTester(new RotationsConfig.Builder().build(), main));
var context = tester.newDeploymentContext();
var zone1 = ZoneId.from("prod", "us-west-1");
var zone2 = ZoneId.from("prod", "us-east-3");
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTester.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTester.java
index 3e25a09b7d7..006e4e63136 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTester.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTester.java
@@ -8,6 +8,7 @@ import com.yahoo.config.provision.HostName;
import com.yahoo.config.provision.RegionName;
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.ZoneApi;
import com.yahoo.config.provision.zone.ZoneId;
import com.yahoo.test.ManualClock;
@@ -38,6 +39,7 @@ import com.yahoo.vespa.hosted.controller.integration.ConfigServerMock;
import com.yahoo.vespa.hosted.controller.integration.MetricsMock;
import com.yahoo.vespa.hosted.controller.integration.SecretStoreMock;
import com.yahoo.vespa.hosted.controller.integration.ServiceRegistryMock;
+import com.yahoo.vespa.hosted.controller.integration.ZoneApiMock;
import com.yahoo.vespa.hosted.controller.integration.ZoneRegistryMock;
import com.yahoo.vespa.hosted.controller.persistence.CuratorDb;
import com.yahoo.vespa.hosted.controller.persistence.MockCuratorDb;
@@ -68,6 +70,7 @@ import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Consumer;
import java.util.logging.Handler;
import java.util.logging.Logger;
+import java.util.stream.Collectors;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@@ -106,8 +109,8 @@ public final class ControllerTester {
this(new AthenzDbMock(), new MockCuratorDb(), defaultRotationsConfig(), serviceRegistryMock);
}
- public ControllerTester(RotationsConfig rotationsConfig) {
- this(rotationsConfig, new MockCuratorDb());
+ public ControllerTester(RotationsConfig rotationsConfig, SystemName system) {
+ this(new AthenzDbMock(), new MockCuratorDb(), rotationsConfig, new ServiceRegistryMock(system));
}
public ControllerTester(MockCuratorDb curatorDb) {
@@ -197,6 +200,21 @@ public final class ControllerTester {
return new Version(current.getMajor(), nextMinorVersion.getAndIncrement(), current.getMicro());
}
+ /** Set the zones and system for this and bootstrap infrastructure nodes */
+ public ControllerTester setZones(List<ZoneId> zones, SystemName system) {
+ zoneRegistry().setZones(zones.stream().map(ZoneApiMock::from).collect(Collectors.toList()))
+ .setSystemName(system);
+ configServer().bootstrap(zones, SystemApplication.notController());
+ return this;
+ }
+
+ /** Set the routing method for given zones */
+ public ControllerTester setRoutingMethod(List<ZoneId> zones, RoutingMethod routingMethod) {
+ zoneRegistry().setRoutingMethod(zones.stream().map(ZoneApiMock::from).collect(Collectors.toList()),
+ routingMethod);
+ return this;
+ }
+
/** Create a new controller instance. Useful to verify that controller state is rebuilt from persistence */
public final void createNewController() {
if (inContainer)
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 2d81d7304a1..468c92d3539 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
@@ -69,6 +69,21 @@ public class EndpointTest {
Endpoint.of(app1).target(endpointId).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 using new domain
+ "https://a1.t1.g.vespa-app.cloud/",
+ Endpoint.of(app1).target(endpointId).on(Port.tls()).routingMethod(RoutingMethod.exclusive).legacy().in(SystemName.Public),
+
+ // Default endpoint in public CD system using new domain
+ "https://a1.t1.g.cd.vespa-app.cloud/",
+ Endpoint.of(app1).target(endpointId).on(Port.tls()).routingMethod(RoutingMethod.exclusive).legacy().in(SystemName.PublicCd),
+
+ // Custom instance in public system, using new domain
+ "https://i2.a2.t2.g.vespa-app.cloud/",
+ Endpoint.of(app2).target(endpointId).on(Port.tls()).routingMethod(RoutingMethod.exclusive).legacy().in(SystemName.Public)
+ );
+ tests2.forEach((expected, endpoint) -> assertEquals(expected, endpoint.url().toString()));
}
@Test
@@ -117,6 +132,13 @@ public class EndpointTest {
Endpoint.of(app1).target(endpointId).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 system, using new domain
+ "https://foo.i2.a2.t2.g.vespa-app.cloud/",
+ Endpoint.of(app2).target(EndpointId.of("foo")).on(Port.tls()).routingMethod(RoutingMethod.exclusive).legacy().in(SystemName.Public)
+ );
+ tests2.forEach((expected, endpoint) -> assertEquals(expected, endpoint.url().toString()));
}
@Test
@@ -167,6 +189,21 @@ public class EndpointTest {
Endpoint.of(app1).target(cluster, prodZone).on(Port.tls()).routingMethod(RoutingMethod.sharedLayer4).in(SystemName.main)
);
tests.forEach((expected, endpoint) -> assertEquals(expected, endpoint.url().toString()));
+
+ Map<String, Endpoint> tests2 = Map.of(
+ // Custom cluster name in public, using new domain
+ "https://c1.a1.t1.us-north-1.z.vespa-app.cloud/",
+ Endpoint.of(app1).target(ClusterSpec.Id.from("c1"), prodZone).on(Port.tls()).routingMethod(RoutingMethod.exclusive).legacy().in(SystemName.Public),
+
+ // Default cluster name in non-production zone in public, using new domain
+ "https://a1.t1.us-north-2.test.z.vespa-app.cloud/",
+ Endpoint.of(app1).target(ClusterSpec.Id.from("default"), testZone).on(Port.tls()).routingMethod(RoutingMethod.exclusive).legacy().in(SystemName.Public),
+
+ // Default cluster name in public CD, using new domain
+ "https://a1.t1.us-north-1.z.cd.vespa-app.cloud/",
+ Endpoint.of(app1).target(ClusterSpec.Id.from("default"), prodZone).on(Port.tls()).routingMethod(RoutingMethod.exclusive).legacy().in(SystemName.PublicCd)
+ );
+ tests2.forEach((expected, endpoint) -> assertEquals(expected, endpoint.url().toString()));
}
@Test
@@ -229,8 +266,9 @@ public class EndpointTest {
}
@Test
- public void weighted_endpoints() {
+ public void region_endpoints() {
var cluster = ClusterSpec.Id.from("default");
+ var prodZone = ZoneId.from("prod", "us-north-2");
Map<String, Endpoint> tests = Map.of(
"https://a1.t1.us-north-1-w.public.vespa.oath.cloud/",
Endpoint.of(app1)
@@ -240,7 +278,7 @@ public class EndpointTest {
.in(SystemName.Public),
"https://a1.t1.us-north-2-w.public.vespa.oath.cloud/",
Endpoint.of(app1)
- .targetRegion(cluster, ZoneId.from("prod", "us-north-2"))
+ .targetRegion(cluster, prodZone)
.routingMethod(RoutingMethod.exclusive)
.on(Port.tls())
.in(SystemName.Public),
@@ -249,6 +287,13 @@ public class EndpointTest {
.targetRegion(cluster, ZoneId.from("test", "us-north-2"))
.routingMethod(RoutingMethod.exclusive)
.on(Port.tls())
+ .in(SystemName.Public),
+ "https://c1.a1.t1.us-north-2.r.vespa-app.cloud/",
+ Endpoint.of(app1)
+ .targetRegion(ClusterSpec.Id.from("c1"), prodZone)
+ .routingMethod(RoutingMethod.exclusive)
+ .on(Port.tls())
+ .legacy()
.in(SystemName.Public)
);
tests.forEach((expected, endpoint) -> assertEquals(expected, endpoint.url().toString()));
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 9eaa15cdbe3..fc7a99eb2f0 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
@@ -186,27 +186,28 @@ public class ApplicationPackageBuilder {
return this;
}
+ /** Add a trusted certificate to security/clients.pem */
public ApplicationPackageBuilder trust(X509Certificate certificate) {
this.trustedCertificates.add(certificate);
return this;
}
+ /** Add a default trusted certificate to security/clients.pem */
public ApplicationPackageBuilder trustDefaultCertificate() {
try {
var generator = KeyPairGenerator.getInstance("RSA");
- var builder = X509CertificateBuilder.fromKeypair(
+ var certificate = X509CertificateBuilder.fromKeypair(
generator.generateKeyPair(),
new X500Principal("CN=name"),
Instant.now(),
Instant.now().plusMillis(300_000),
SignatureAlgorithm.SHA256_WITH_RSA,
X509CertificateBuilder.generateRandomSerialNumber()
- );
- this.trustedCertificates.add(builder.build());
+ ).build();
+ return trust(certificate);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
- return this;
}
private byte[] deploymentSpec() {
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 81c9f51278e..c8b4eaa5236 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
@@ -5,15 +5,11 @@ import com.yahoo.component.Version;
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.ControllerTester;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.ApplicationVersion;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.JobType;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.RunId;
import com.yahoo.vespa.hosted.controller.application.ApplicationPackage;
import com.yahoo.vespa.hosted.controller.application.Change;
-import com.yahoo.vespa.hosted.controller.application.SystemApplication;
-import com.yahoo.vespa.hosted.controller.integration.ServiceRegistryMock;
-import com.yahoo.vespa.hosted.controller.integration.ZoneApiMock;
import com.yahoo.vespa.hosted.controller.versions.VespaVersion;
import org.junit.Test;
@@ -1061,17 +1057,13 @@ public class DeploymentTriggerTest {
ApplicationPackage cdPackage = new ApplicationPackageBuilder().region("cd-us-central-1")
.region("cd-aws-us-east-1a")
.build();
- ServiceRegistryMock services = new ServiceRegistryMock();
- var zones = List.of(ZoneApiMock.fromId("test.cd-us-central-1"),
- ZoneApiMock.fromId("staging.cd-us-central-1"),
- ZoneApiMock.fromId("prod.cd-us-central-1"),
- ZoneApiMock.fromId("prod.cd-aws-us-east-1a"));
- services.zoneRegistry()
- .setSystemName(SystemName.cd)
- .setZones(zones)
- .setRoutingMethod(zones, RoutingMethod.shared);
- tester = new DeploymentTester(new ControllerTester(services));
- tester.configServer().bootstrap(services.zoneRegistry().zones().all().ids(), SystemApplication.values());
+ var zones = List.of(ZoneId.from("test.cd-us-central-1"),
+ ZoneId.from("staging.cd-us-central-1"),
+ ZoneId.from("prod.cd-us-central-1"),
+ ZoneId.from("prod.cd-aws-us-east-1a"));
+ tester.controllerTester()
+ .setZones(zones, SystemName.cd)
+ .setRoutingMethod(zones, RoutingMethod.shared);
tester.controllerTester().upgradeSystem(Version.fromString("6.1"));
tester.controllerTester().computeVersionStatus();
var app = tester.newDeploymentContext();
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 31a3b5ff1cf..10e398ad133 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
@@ -1472,6 +1472,12 @@ public class ApplicationApiTest extends ControllerContainerTest {
.userIdentity(USER_ID),
new File("deployment-with-routing-policy.json"));
+ // GET deployment including legacy endpoints
+ tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/us-west-1/instance/instance1", GET)
+ .userIdentity(USER_ID)
+ .properties(Map.of("includeLegacyEndpoints", "true")),
+ new File("deployment-with-routing-policy-legacy.json"));
+
// Hide shared endpoints
((InMemoryFlagSource) tester.controller().flagSource()).withBooleanFlag(Flags.HIDE_SHARED_ROUTING_ENDPOINT.id(), true);
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/deployment-cloud.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/deployment-cloud.json
index 59022f124c0..3353d80204e 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/deployment-cloud.json
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/deployment-cloud.json
@@ -10,7 +10,8 @@
"tls": true,
"url": "https://albums.scoober.aws-us-east-1c.public.vespa.oath.cloud/",
"scope": "zone",
- "routingMethod": "exclusive"
+ "routingMethod": "exclusive",
+ "legacy": false
}
],
"clusters": "http://localhost:8080/application/v4/tenant/scoober/application/albums/instance/default/environment/prod/region/aws-us-east-1c/clusters",
@@ -44,4 +45,4 @@
"queryLatencyMillis": 0.0,
"writeLatencyMillis": 0.0
}
-} \ No newline at end of file
+}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/deployment-with-routing-policy-legacy.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/deployment-with-routing-policy-legacy.json
new file mode 100644
index 00000000000..6efcc822264
--- /dev/null
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/deployment-with-routing-policy-legacy.json
@@ -0,0 +1,71 @@
+{
+ "tenant": "tenant1",
+ "application": "application1",
+ "instance": "instance1",
+ "environment": "prod",
+ "region": "us-west-1",
+ "endpoints": [
+ {
+ "cluster": "default",
+ "tls": true,
+ "url": "https://instance1.application1.tenant1.us-west-1.vespa.oath.cloud/",
+ "scope": "zone",
+ "routingMethod": "exclusive",
+ "legacy": false
+ },
+ {
+ "cluster": "default",
+ "tls": true,
+ "url": "https://instance1--application1--tenant1.us-west-1.vespa.oath.cloud:4443/",
+ "scope": "zone",
+ "routingMethod": "shared",
+ "legacy": false
+ },
+ {
+ "cluster": "default",
+ "tls": false,
+ "url": "http://instance1.application1.tenant1.us-west-1.prod.vespa.yahooapis.com:4080/",
+ "scope": "zone",
+ "routingMethod": "shared",
+ "legacy": true
+ },
+ {
+ "cluster": "default",
+ "tls": true,
+ "url": "https://instance1--application1--tenant1.us-west-1.prod.vespa.yahooapis.com:4443/",
+ "scope": "zone",
+ "routingMethod": "shared",
+ "legacy": true
+ }
+ ],
+ "clusters": "http://localhost:8080/application/v4/tenant/tenant1/application/application1/instance/instance1/environment/prod/region/us-west-1/clusters",
+ "nodes": "http://localhost:8080/zone/v2/prod/us-west-1/nodes/v2/node/?recursive=true&application=tenant1.application1.instance1",
+ "yamasUrl": "http://monitoring-system.test/?environment=prod&region=us-west-1&application=tenant1.application1.instance1",
+ "version": "6.1.0",
+ "revision": "1.0.1-commit1",
+ "deployTimeEpochMs": "(ignore)",
+ "screwdriverId": "1000",
+ "gitRepository": "repository1",
+ "gitBranch": "master",
+ "gitCommit": "commit1",
+ "applicationVersion": {
+ "hash": "1.0.1-commit1",
+ "build": 1,
+ "source": {
+ "gitRepository": "repository1",
+ "gitBranch": "master",
+ "gitCommit": "commit1"
+ },
+ "sourceUrl": "repository1/tree/commit1",
+ "commit": "commit1"
+ },
+ "status": "complete",
+ "activity": {},
+ "metrics": {
+ "queriesPerSecond": 0.0,
+ "writesPerSecond": 0.0,
+ "documentCount": 0.0,
+ "queryLatencyMillis": 0.0,
+ "writeLatencyMillis": 0.0
+ }
+}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/deployment-with-routing-policy.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/deployment-with-routing-policy.json
index 6b3c316a485..8767c369bc3 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/deployment-with-routing-policy.json
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/deployment-with-routing-policy.json
@@ -10,14 +10,16 @@
"tls": true,
"url": "https://instance1.application1.tenant1.us-west-1.vespa.oath.cloud/",
"scope": "zone",
- "routingMethod": "exclusive"
+ "routingMethod": "exclusive",
+ "legacy": false
},
{
"cluster": "default",
"tls": true,
"url": "https://instance1--application1--tenant1.us-west-1.vespa.oath.cloud:4443/",
"scope": "zone",
- "routingMethod": "shared"
+ "routingMethod": "shared",
+ "legacy": false
}
],
"clusters":"http://localhost:8080/application/v4/tenant/tenant1/application/application1/instance/instance1/environment/prod/region/us-west-1/clusters",
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/deployment-without-shared-endpoints.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/deployment-without-shared-endpoints.json
index 66fe28a95ad..b59c1d6cf73 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/deployment-without-shared-endpoints.json
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/deployment-without-shared-endpoints.json
@@ -10,7 +10,8 @@
"tls": true,
"url": "https://instance1.application1.tenant1.us-west-1.vespa.oath.cloud/",
"scope": "zone",
- "routingMethod": "exclusive"
+ "routingMethod": "exclusive",
+ "legacy": false
}
],
"clusters":"http://localhost:8080/application/v4/tenant/tenant1/application/application1/instance/instance1/environment/prod/region/us-west-1/clusters",
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/deployment.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/deployment.json
index 946593fca00..6c00d654008 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/deployment.json
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/deployment.json
@@ -10,14 +10,16 @@
"tls": true,
"url": "https://instance1--application1--tenant1.us-central-1.vespa.oath.cloud:4443/",
"scope": "zone",
- "routingMethod": "shared"
+ "routingMethod": "shared",
+ "legacy": false
},
{
"cluster": "foo",
"tls": true,
"url": "https://instance1--application1--tenant1.global.vespa.oath.cloud:4443/",
"scope": "global",
- "routingMethod": "shared"
+ "routingMethod": "shared",
+ "legacy": false
}
],
"clusters": "http://localhost:8080/application/v4/tenant/tenant1/application/application1/instance/instance1/environment/prod/region/us-central-1/clusters",
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/dev-us-east-1.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/dev-us-east-1.json
index 7ba63e1664d..1084afc9388 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/dev-us-east-1.json
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/dev-us-east-1.json
@@ -10,7 +10,8 @@
"tls": true,
"url": "https://instance1--application1--tenant1.us-east-1.dev.vespa.oath.cloud:4443/",
"scope": "zone",
- "routingMethod": "shared"
+ "routingMethod": "shared",
+ "legacy": false
}
],
"clusters":"http://localhost:8080/application/v4/tenant/tenant1/application/application1/instance/instance1/environment/dev/region/us-east-1/clusters",
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/prod-us-central-1.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/prod-us-central-1.json
index 4251ba1ad95..9059ea338b1 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/prod-us-central-1.json
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/prod-us-central-1.json
@@ -13,14 +13,16 @@
"tls": true,
"url": "https://instance1--application1--tenant1.us-central-1.vespa.oath.cloud:4443/",
"scope": "zone",
- "routingMethod": "shared"
+ "routingMethod": "shared",
+ "legacy": false
},
{
"cluster": "foo",
"tls": true,
"url": "https://instance1--application1--tenant1.global.vespa.oath.cloud:4443/",
"scope": "global",
- "routingMethod": "shared"
+ "routingMethod": "shared",
+ "legacy": false
}
],
"clusters":"http://localhost:8080/application/v4/tenant/tenant1/application/application1/instance/instance1/environment/prod/region/us-central-1/clusters",
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/rotation/RotationRepositoryTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/rotation/RotationRepositoryTest.java
index 136ed508a33..aa9775f1d43 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/rotation/RotationRepositoryTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/rotation/RotationRepositoryTest.java
@@ -51,7 +51,7 @@ public class RotationRepositoryTest {
.region("us-west-1")
.build();
- private final DeploymentTester tester = new DeploymentTester(new ControllerTester(rotationsConfig));
+ private final DeploymentTester tester = new DeploymentTester(new ControllerTester(rotationsConfig, SystemName.main));
private final RotationRepository repository = tester.controller().routing().rotations();
private final DeploymentContext application = tester.newDeploymentContext("tenant1", "app1", "default");
@@ -92,7 +92,7 @@ public class RotationRepositoryTest {
@Test
public void strips_whitespace_in_rotation_fqdn() {
- var tester = new DeploymentTester(new ControllerTester(rotationsConfigWhitespaces));
+ var tester = new DeploymentTester(new ControllerTester(rotationsConfigWhitespaces, SystemName.main));
RotationRepository repository = tester.controller().routing().rotations();
var application2 = tester.newDeploymentContext("tenant1", "app2", "default");
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 bfb749eb681..047a4461f7c 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
@@ -14,7 +14,6 @@ import com.yahoo.config.provision.HostName;
import com.yahoo.config.provision.RegionName;
import com.yahoo.config.provision.SystemName;
import com.yahoo.config.provision.zone.RoutingMethod;
-import com.yahoo.config.provision.zone.ZoneApi;
import com.yahoo.config.provision.zone.ZoneId;
import com.yahoo.vespa.hosted.controller.ControllerTester;
import com.yahoo.vespa.hosted.controller.Instance;
@@ -28,6 +27,7 @@ import com.yahoo.vespa.hosted.controller.api.integration.dns.RecordName;
import com.yahoo.vespa.hosted.controller.application.ApplicationPackage;
import com.yahoo.vespa.hosted.controller.application.Endpoint;
import com.yahoo.vespa.hosted.controller.application.EndpointId;
+import com.yahoo.vespa.hosted.controller.application.EndpointList;
import com.yahoo.vespa.hosted.controller.application.SystemApplication;
import com.yahoo.vespa.hosted.controller.deployment.ApplicationPackageBuilder;
import com.yahoo.vespa.hosted.controller.deployment.DeploymentContext;
@@ -312,7 +312,7 @@ public class RoutingPoliciesTest {
@Test
public void zone_routing_policies_without_dns_update() {
- var tester = new RoutingPoliciesTester(new DeploymentTester(), false);
+ var tester = new RoutingPoliciesTester(new DeploymentTester(), SystemName.main, false);
var context = tester.newDeploymentContext("tenant1", "app1", "default");
tester.provisionLoadBalancers(1, context.instanceId(), true, zone1, zone2);
context.submit(applicationPackage).deferLoadBalancerProvisioningIn(Environment.prod).deploy();
@@ -323,13 +323,17 @@ public class RoutingPoliciesTest {
@Test
public void global_routing_policies_in_rotationless_system() {
- var tester = new RoutingPoliciesTester(new DeploymentTester(new ControllerTester(new RotationsConfig.Builder().build())), true);
+ var tester = new RoutingPoliciesTester(SystemName.Public);
var context = tester.newDeploymentContext("tenant1", "app1", "default");
+ List<ZoneId> prodZones = tester.controllerTester().controller().zoneRegistry().zones().all().in(Environment.prod).ids();
+ ZoneId zone1 = prodZones.get(0);
+ ZoneId zone2 = prodZones.get(1);
tester.provisionLoadBalancers(1, context.instanceId(), zone1, zone2);
var applicationPackage = applicationPackageBuilder()
.region(zone1.region().value())
.endpoint("r0", "c0")
+ .trustDefaultCertificate()
.build();
context.submit(applicationPackage).deferLoadBalancerProvisioningIn(Environment.prod).deploy();
@@ -340,6 +344,39 @@ public class RoutingPoliciesTest {
}
@Test
+ public void global_routing_policies_in_public() {
+ var tester = new RoutingPoliciesTester(SystemName.Public);
+ var context = tester.newDeploymentContext("tenant1", "app1", "default");
+ List<ZoneId> prodZones = tester.controllerTester().controller().zoneRegistry().zones().all().in(Environment.prod).ids();
+ ZoneId zone1 = prodZones.get(0);
+ ZoneId zone2 = prodZones.get(1);
+
+ var applicationPackage = applicationPackageBuilder()
+ .region(zone1.region().value())
+ .region(zone2.region().value())
+ .endpoint("default", "default")
+ .trustDefaultCertificate()
+ .build();
+ context.submit(applicationPackage).deploy();
+
+ tester.assertTargets(context.instanceId(), EndpointId.defaultId(),
+ ClusterSpec.Id.from("default"), 0,
+ Map.of(zone1, 1L, zone2, 1L), true);
+ assertEquals("Registers expected DNS names",
+ Set.of("app1.tenant1.aws-eu-west-1-w.public.vespa.oath.cloud",
+ "app1.tenant1.aws-eu-west-1.r.vespa-app.cloud",
+ "app1.tenant1.aws-eu-west-1a.public.vespa.oath.cloud",
+ "app1.tenant1.aws-eu-west-1a.z.vespa-app.cloud",
+ "app1.tenant1.aws-us-east-1-w.public.vespa.oath.cloud",
+ "app1.tenant1.aws-us-east-1.r.vespa-app.cloud",
+ "app1.tenant1.aws-us-east-1c.public.vespa.oath.cloud",
+ "app1.tenant1.aws-us-east-1c.z.vespa-app.cloud",
+ "app1.tenant1.g.vespa-app.cloud",
+ "app1.tenant1.global.public.vespa.oath.cloud"),
+ tester.recordNames());
+ }
+
+ @Test
public void manual_deployment_creates_routing_policy() {
// Empty application package is valid in manually deployed environments
var tester = new RoutingPoliciesTester();
@@ -572,24 +609,11 @@ public class RoutingPoliciesTest {
var tester = new RoutingPoliciesTester(SystemName.Public);
// Configure the system to use the same region for test, staging and prod
- var sharedRegion = RegionName.from("aws-us-east-1c");
- var prodZone = ZoneId.from(Environment.prod, sharedRegion);
- var stagingZone = ZoneId.from(Environment.staging, sharedRegion);
- var testZone = ZoneId.from(Environment.test, sharedRegion);
- var zones = List.of(ZoneApiMock.from(prodZone),
- ZoneApiMock.from(stagingZone),
- ZoneApiMock.from(testZone));
- tester.controllerTester().zoneRegistry()
- .setZones(zones)
- .setRoutingMethod(zones, RoutingMethod.exclusive);
- tester.controllerTester().configServer().bootstrap(List.of(prodZone, stagingZone, testZone),
- SystemApplication.notController());
-
var context = tester.tester.newDeploymentContext();
var endpointId = EndpointId.of("r0");
var applicationPackage = applicationPackageBuilder()
.trustDefaultCertificate()
- .region(sharedRegion)
+ .region("aws-us-east-1c")
.endpoint(endpointId.id(), "default")
.build();
@@ -600,14 +624,14 @@ public class RoutingPoliciesTest {
// Since runJob implicitly tears down the deployment and immediately deletes DNS records associated with the
// deployment, we consume only one DNS update at a time here
do {
- context = context.flushDnsUpdates(1);
+ context.flushDnsUpdates(1);
tester.assertTargets(context.instanceId(), endpointId, 0);
} while (!tester.recordNames().isEmpty());
}
// Deployment completes
context.completeRollout();
- tester.assertTargets(context.instanceId(), endpointId, ClusterSpec.Id.from("default"), 0, Map.of(prodZone, 1L));
+ tester.assertTargets(context.instanceId(), endpointId, ClusterSpec.Id.from("default"), 0, Map.of(ZoneId.from("prod", "aws-us-east-1c"), 1L));
}
@Test
@@ -711,6 +735,14 @@ public class RoutingPoliciesTest {
return loadBalancers;
}
+ private static List<ZoneId> publicZones() {
+ var sharedRegion = RegionName.from("aws-us-east-1c");
+ return List.of(ZoneId.from(Environment.prod, sharedRegion),
+ ZoneId.from(Environment.prod, RegionName.from("aws-eu-west-1a")),
+ ZoneId.from(Environment.staging, sharedRegion),
+ ZoneId.from(Environment.test, sharedRegion));
+ }
+
private static class RoutingPoliciesTester {
private final DeploymentTester tester;
@@ -720,7 +752,26 @@ public class RoutingPoliciesTest {
}
public RoutingPoliciesTester(SystemName system) {
- this(new DeploymentTester(new ControllerTester(system)), true);
+ this(new DeploymentTester(system.isPublic()
+ ? new ControllerTester(new RotationsConfig.Builder().build(), system)
+ : new ControllerTester()),
+ system,
+ true);
+ }
+
+ public RoutingPoliciesTester(DeploymentTester tester, SystemName system, boolean exclusiveRouting) {
+ this.tester = tester;
+ List<ZoneId> zones;
+ if (system.isPublic()) {
+ zones = publicZones();
+ } else {
+ zones = new ArrayList<>(tester.controllerTester().zoneRegistry().zones().all().ids()); // Default zones
+ zones.add(zone4); // Missing from default ZoneRegistryMock zones
+ }
+ tester.controllerTester().setZones(zones, system);
+ if (exclusiveRouting) {
+ tester.controllerTester().setRoutingMethod(zones, RoutingMethod.exclusive);
+ }
}
public RoutingPolicies routingPolicies() {
@@ -739,19 +790,6 @@ public class RoutingPoliciesTest {
return tester.controllerTester();
}
- public RoutingPoliciesTester(DeploymentTester tester, boolean exclusiveRouting) {
- this.tester = tester;
- List<ZoneApi> zones = new ArrayList<>(tester.controllerTester().zoneRegistry().zones().all().zones());
- zones.add(ZoneApiMock.from(zone3));
- zones.add(ZoneApiMock.from(zone4));
- tester.controllerTester().zoneRegistry().setZones(zones);
- if (exclusiveRouting) {
- tester.controllerTester().zoneRegistry().exclusiveRoutingIn(zones);
- }
- tester.controllerTester().configServer().bootstrap(tester.controllerTester().zoneRegistry().zones().all().ids(),
- SystemApplication.notController());
- }
-
private void provisionLoadBalancers(int clustersPerZone, ApplicationId application, boolean shared, ZoneId... zones) {
for (ZoneId zone : zones) {
tester.configServer().removeLoadBalancers(application, zone);
@@ -789,14 +827,21 @@ public class RoutingPoliciesTest {
}
private void assertTargets(ApplicationId application, EndpointId endpointId, ClusterSpec.Id cluster, int loadBalancerId, Map<ZoneId, Long> zoneWeights) {
+ assertTargets(application, endpointId, cluster, loadBalancerId, zoneWeights, false);
+ }
+
+ private void assertTargets(ApplicationId application, EndpointId endpointId, ClusterSpec.Id cluster, int loadBalancerId, Map<ZoneId, Long> zoneWeights, boolean legacy) {
Set<String> latencyTargets = new HashSet<>();
Map<String, List<ZoneId>> zonesByRegionEndpoint = new HashMap<>();
for (var zone : zoneWeights.keySet()) {
- Endpoint regionEndpoint = tester.controller().routing().endpointsOf(new DeploymentId(application, zone))
- .scope(Endpoint.Scope.region)
- .cluster(cluster)
- .asList()
- .get(0);
+ DeploymentId deployment = new DeploymentId(application, zone);
+ EndpointList regionEndpoints = tester.controller().routing().endpointsOf(deployment)
+ .cluster(cluster)
+ .scope(Endpoint.Scope.region);
+ if (!legacy) {
+ regionEndpoints = regionEndpoints.not().legacy();
+ }
+ Endpoint regionEndpoint = regionEndpoints.first().orElseThrow(() -> new IllegalArgumentException("No region endpoint found for " + cluster + " in " + deployment));
zonesByRegionEndpoint.computeIfAbsent(regionEndpoint.dnsName(), (k) -> new ArrayList<>())
.add(zone);
}