summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java76
1 files changed, 50 insertions, 26 deletions
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java
index 8345aa91685..61a4e1e8656 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java
@@ -28,6 +28,7 @@ import com.yahoo.vespa.hosted.controller.api.identifiers.RevisionId;
import com.yahoo.vespa.hosted.controller.api.integration.BuildService;
import com.yahoo.vespa.hosted.controller.api.integration.configserver.ConfigServer;
import com.yahoo.vespa.hosted.controller.api.integration.configserver.ConfigServerException;
+import com.yahoo.vespa.hosted.controller.api.integration.configserver.ContainerEndpoint;
import com.yahoo.vespa.hosted.controller.api.integration.configserver.Log;
import com.yahoo.vespa.hosted.controller.api.integration.configserver.Node;
import com.yahoo.vespa.hosted.controller.api.integration.configserver.NotFoundException;
@@ -85,6 +86,7 @@ import java.util.Comparator;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -95,6 +97,7 @@ import java.util.function.Consumer;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
import static com.yahoo.vespa.hosted.controller.api.integration.configserver.Node.State.active;
import static com.yahoo.vespa.hosted.controller.api.integration.configserver.Node.State.reserved;
@@ -286,7 +289,7 @@ public class ApplicationController {
Version platformVersion;
ApplicationVersion applicationVersion;
ApplicationPackage applicationPackage;
- Set<String> rotationNames = new HashSet<>();
+ Set<ContainerEndpoint> endpoints = new LinkedHashSet<>();
try (Lock lock = lock(applicationId)) {
LockedApplication application = new LockedApplication(require(applicationId), lock);
@@ -328,9 +331,18 @@ public class ApplicationController {
application = withRotation(application, zone);
Application app = application.get();
// Include global DNS names
- app.endpointsIn(controller.system()).asList().stream().map(Endpoint::dnsName).forEach(rotationNames::add);
- // Include rotation ID to ensure that deployment can respond to health checks with rotation ID as Host header
- app.rotations().stream().map(RotationId::asString).forEach(rotationNames::add);
+ app.assignedRotations().stream()
+ .filter(assignedRotation -> assignedRotation.regions().contains(zone.region()))
+ .map(assignedRotation -> {
+ return new ContainerEndpoint(
+ assignedRotation.clusterId().value(),
+ Stream.concat(
+ app.endpointsIn(controller.system(), assignedRotation.endpointId()).legacy(false).asList().stream().map(Endpoint::dnsName),
+ app.rotations().stream().map(RotationId::asString)
+ ).collect(Collectors.toList())
+ );
+ })
+ .forEach(endpoints::add);
// Update application with information from application package
if ( ! preferOldestVersion
@@ -342,7 +354,7 @@ public class ApplicationController {
// Carry out deployment without holding the application lock.
options = withVersion(platformVersion, options);
- ActivateResult result = deploy(applicationId, applicationPackage, zone, options, rotationNames);
+ ActivateResult result = deploy(applicationId, applicationPackage, zone, options, endpoints);
lockOrThrow(applicationId, application ->
store(application.withNewDeployment(zone, applicationVersion, platformVersion, clock.instant(),
@@ -422,11 +434,11 @@ public class ApplicationController {
private ActivateResult deploy(ApplicationId application, ApplicationPackage applicationPackage,
ZoneId zone, DeployOptions deployOptions,
- Set<String> rotationNames) {
+ Set<ContainerEndpoint> endpoints) {
DeploymentId deploymentId = new DeploymentId(application, zone);
try {
ConfigServer.PreparedApplication preparedApplication =
- configServer.deploy(deploymentId, deployOptions, rotationNames, List.of(), applicationPackage.zippedContent());
+ configServer.deploy(deploymentId, deployOptions, Set.of(), endpoints, applicationPackage.zippedContent());
return new ActivateResult(new RevisionId(applicationPackage.hash()), preparedApplication.prepareResponse(),
applicationPackage.zippedContent().length);
} finally {
@@ -438,29 +450,35 @@ public class ApplicationController {
/** Makes sure the application has a global rotation, if eligible. */
private LockedApplication withRotation(LockedApplication application, ZoneId zone) {
- if (zone.environment() == Environment.prod && application.get().deploymentSpec().globalServiceId().isPresent()) {
+ if (zone.environment() == Environment.prod && applicationNeedsRotations(application.get().deploymentSpec())) {
try (RotationLock rotationLock = rotationRepository.lock()) {
- Rotation rotation = rotationRepository.getOrAssignRotation(application.get(), rotationLock);
- application = application.with(List.of(new AssignedRotation(new ClusterSpec.Id(application.get().deploymentSpec().globalServiceId().get()), EndpointId.default_(), rotation.id())));
+ final var rotations = rotationRepository.getOrAssignRotations(application.get(), rotationLock);
+ application = application.with(rotations);
store(application); // store assigned rotation even if deployment fails
+ registerAssignedRotationCnames(application.get());
+ }
+ }
+ return application;
+ }
+
+ private boolean applicationNeedsRotations(DeploymentSpec spec) {
+ return spec.globalServiceId().isPresent() || !spec.endpoints().isEmpty();
+ }
- boolean redirectLegacyDns = redirectLegacyDnsFlag.with(FetchVector.Dimension.APPLICATION_ID, application.get().id().serializedForm())
- .value();
+ private void registerAssignedRotationCnames(Application application) {
+ application.assignedRotations().forEach(assignedRotation -> {
+ final var endpoints = application
+ .endpointsIn(controller.system(), assignedRotation.endpointId())
+ .scope(Endpoint.Scope.global);
- EndpointList globalEndpoints = application.get()
- .endpointsIn(controller.system())
- .scope(Endpoint.Scope.global);
- globalEndpoints.main().ifPresent(mainEndpoint -> {
+ final var maybeRotation = rotationRepository.getRotation(assignedRotation.rotationId());
+
+ maybeRotation.ifPresent(rotation -> {
+ endpoints.main().ifPresent(mainEndpoint -> {
registerCname(mainEndpoint.dnsName(), rotation.name());
- if (redirectLegacyDns) {
- globalEndpoints.legacy(true).asList().forEach(endpoint -> registerCname(endpoint.dnsName(), mainEndpoint.dnsName()));
- } else {
- globalEndpoints.legacy(true).asList().forEach(endpoint -> registerCname(endpoint.dnsName(), rotation.name()));
- }
});
- }
- }
- return application;
+ });
+ });
}
private ActivateResult unexpectedDeployment(ApplicationId application, ZoneId zone) {
@@ -607,8 +625,14 @@ public class ApplicationController {
applicationStore.removeAll(id);
applicationStore.removeAll(TesterId.of(id));
- EndpointList endpoints = application.get().endpointsIn(controller.system());
- endpoints.asList().stream().map(Endpoint::dnsName).forEach(name -> controller.nameServiceForwarder().removeRecords(Record.Type.CNAME, RecordName.from(name), Priority.normal));
+ application.get().assignedRotations().forEach(assignedRotation -> {
+ final var endpoints = application.get().endpointsIn(controller.system(), assignedRotation.endpointId());
+ endpoints.asList().stream()
+ .map(Endpoint::dnsName)
+ .forEach(name -> {
+ controller.nameServiceForwarder().removeRecords(Record.Type.CNAME, RecordName.from(name), Priority.normal);
+ });
+ });
log.info("Deleted " + application);
}));