aboutsummaryrefslogtreecommitdiffstats
path: root/controller-server/src/main/java/com/yahoo
diff options
context:
space:
mode:
Diffstat (limited to 'controller-server/src/main/java/com/yahoo')
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java63
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunner.java22
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobController.java7
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java3
4 files changed, 68 insertions, 27 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 3fad76b2e07..bc31a0a02fa 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
@@ -37,6 +37,7 @@ import com.yahoo.vespa.hosted.controller.api.integration.configserver.PrepareRes
import com.yahoo.vespa.hosted.controller.api.integration.deployment.ApplicationStore;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.ApplicationVersion;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.ArtifactRepository;
+import com.yahoo.vespa.hosted.controller.api.integration.deployment.JobId;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.JobType;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.TesterId;
import com.yahoo.vespa.hosted.controller.application.ApplicationPackage;
@@ -286,9 +287,65 @@ public class ApplicationController {
return deploy(applicationId, zone, applicationPackageFromDeployer, Optional.empty(), options);
}
- /** Deploys an application. If the application does not exist it is created. */
- // TODO: Get rid of the options arg
- // TODO jonmv: Split this, and choose between deployDirectly and deploy in handler, excluding internally built from the latter.
+ /** Deploys an application package for an existing application instance. */
+ public ActivateResult deploy2(JobId job, boolean deploySourceVersions) { // TODO jonmv: make it number one!
+ if (job.application().instance().isTester())
+ throw new IllegalArgumentException("'" + job.application() + "' is a tester application!");
+
+ TenantAndApplicationId applicationId = TenantAndApplicationId.from(job.application());
+ ZoneId zone = job.type().zone(controller.system());
+
+ try (Lock deploymentLock = lockForDeployment(job.application(), zone)) {
+ Set<ContainerEndpoint> endpoints;
+ Optional<EndpointCertificateMetadata> endpointCertificateMetadata;
+
+ Run run = controller.jobController().last(job)
+ .orElseThrow(() -> new IllegalStateException("No known run of '" + job + "'"));
+
+ if (run.hasEnded())
+ throw new IllegalStateException("No deployment expected for " + job + " now, as no job is running");
+
+ Version platform = run.versions().sourcePlatform().filter(__ -> deploySourceVersions).orElse(run.versions().targetPlatform());
+ ApplicationVersion revision = run.versions().sourceApplication().filter(__ -> deploySourceVersions).orElse(run.versions().targetApplication());
+ ApplicationPackage applicationPackage = getApplicationPackage(job.application(), zone, revision);
+
+ try (Lock lock = lock(applicationId)) {
+ LockedApplication application = new LockedApplication(requireApplication(applicationId), lock);
+ Instance instance = application.get().require(job.application().instance());
+
+ Deployment deployment = instance.deployments().get(zone);
+ if ( zone.environment().isProduction() && deployment != null
+ && ( platform.compareTo(deployment.version()) < 0 && ! instance.change().isPinned()
+ || revision.compareTo(deployment.applicationVersion()) < 0 && ! (revision.isUnknown() && controller.system().isCd())))
+ throw new IllegalArgumentException(String.format("Rejecting deployment of application %s to %s, as the requested versions (platform: %s, application: %s)" +
+ " are older than the currently deployed (platform: %s, application: %s).",
+ job.application(), zone, platform, revision, deployment.version(), deployment.applicationVersion()));
+
+ if ( ! applicationPackage.trustedCertificates().isEmpty()
+ && run.testerCertificate().isPresent())
+ applicationPackage = applicationPackage.withTrustedCertificate(run.testerCertificate().get());
+
+ endpointCertificateMetadata = endpointCertificateManager.getEndpointCertificateMetadata(instance, zone);
+
+ endpoints = controller.routing().registerEndpointsInDns(applicationPackage.deploymentSpec(), instance, zone);
+ } // Release application lock while doing the deployment, which is a lengthy task.
+
+ // Carry out deployment without holding the application lock.
+ ActivateResult result = deploy(job.application(), applicationPackage, zone, platform, endpoints, endpointCertificateMetadata);
+
+ lockApplicationOrThrow(applicationId, application ->
+ store(application.with(job.application().instance(),
+ instance -> instance.withNewDeployment(zone, revision, platform,
+ clock.instant(), warningsFrom(result)))));
+ return result;
+ }
+ }
+
+ private ApplicationPackage getApplicationPackage(ApplicationId application, ZoneId zone, ApplicationVersion revision) {
+ return new ApplicationPackage(revision.isUnknown() ? applicationStore.getDev(application, zone)
+ : applicationStore.get(application.tenant(), application.application(), revision));
+ }
+
public ActivateResult deploy(ApplicationId instanceId, ZoneId zone,
Optional<ApplicationPackage> applicationPackageFromDeployer,
Optional<ApplicationVersion> applicationVersionFromDeployer,
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunner.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunner.java
index 861c8089ed5..628a7e41eb2 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunner.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunner.java
@@ -173,34 +173,20 @@ public class InternalStepRunner implements StepRunner {
versions.sourcePlatform().orElse(versions.targetPlatform()) +
" and application version " +
versions.sourceApplication().orElse(versions.targetApplication()).id() + " ...");
- return deployReal(id, true, versions, logger);
+ return deployReal(id, true, logger);
}
private Optional<RunStatus> deployReal(RunId id, DualLogger logger) {
Versions versions = controller.jobController().run(id).get().versions();
logger.log("Deploying platform version " + versions.targetPlatform() +
" and application version " + versions.targetApplication().id() + " ...");
- return deployReal(id, false, versions, logger);
+ return deployReal(id, false, logger);
}
- private Optional<RunStatus> deployReal(RunId id, boolean setTheStage, Versions versions, DualLogger logger) {
- Optional<ApplicationPackage> applicationPackage = id.type().environment().isManuallyDeployed()
- ? Optional.of(new ApplicationPackage(controller.applications().applicationStore()
- .getDev(id.application(), id.type().zone(controller.system()))))
- : Optional.empty();
-
- Optional<Version> vespaVersion = id.type().environment().isManuallyDeployed()
- ? Optional.of(versions.targetPlatform()) // TODO jonmv: This makes it impossible to deploy on older majors — fix.
- : Optional.empty();
+ private Optional<RunStatus> deployReal(RunId id, boolean setTheStage, DualLogger logger) {
return deploy(id.application(),
id.type(),
- () -> controller.applications().deploy(id.application(),
- id.type().zone(controller.system()),
- applicationPackage,
- new DeployOptions(false,
- vespaVersion,
- false,
- setTheStage)),
+ () -> controller.applications().deploy2(id.job(), setTheStage),
controller.jobController().run(id).get()
.stepInfo(setTheStage ? deployInitialReal : deployReal).get()
.startTime().get(),
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobController.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobController.java
index 007654b2a7c..5d8ad6594df 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobController.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/JobController.java
@@ -418,9 +418,6 @@ public class JobController {
/** Orders a run of the given type, or throws an IllegalStateException if that job type is already running. */
public void start(ApplicationId id, JobType type, Versions versions, JobProfile profile) {
- if (profile != JobProfile.development && versions.targetApplication().isUnknown())
- throw new IllegalArgumentException(" Target application must be a valid reference");
-
controller.applications().lockApplicationIfPresent(TenantAndApplicationId.from(id), application -> {
locked(id, type, __ -> {
Optional<Run> last = last(id, type);
@@ -436,9 +433,6 @@ public class JobController {
/** Stores the given package and starts a deployment of it, after aborting any such ongoing deployment. */
public void deploy(ApplicationId id, JobType type, Optional<Version> platform, ApplicationPackage applicationPackage) {
- if ( ! type.environment().isManuallyDeployed())
- throw new IllegalArgumentException("Direct deployments are only allowed to manually deployed environments.");
-
controller.applications().lockApplicationOrThrow(TenantAndApplicationId.from(id), application -> {
if ( ! application.get().instances().containsKey(id.instance()))
application = controller.applications().withNewInstance(application, id);
@@ -546,6 +540,7 @@ public class JobController {
application.get().productionDeployments().values().stream()
.flatMap(List::stream)
.map(Deployment::applicationVersion)
+ .filter(version -> ! version.isUnknown())
.min(Comparator.comparingLong(applicationVersion -> applicationVersion.buildNumber().getAsLong()))
.ifPresent(oldestDeployed -> {
controller.applications().applicationStore().prune(id.tenant(), id.application(), oldestDeployed);
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 1c8279f6d8d..7b2e1ad7a8e 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
@@ -1482,6 +1482,9 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
}
private HttpResponse jobDeploy(ApplicationId id, JobType type, HttpRequest request) {
+ if ( ! type.environment().isManuallyDeployed() && ! isOperator(request))
+ throw new IllegalArgumentException("Direct deployments are only allowed to manually deployed environments.");
+
Map<String, byte[]> dataParts = parseDataParts(request);
if ( ! dataParts.containsKey("applicationZip"))
throw new IllegalArgumentException("Missing required form part 'applicationZip'");