diff options
author | Jon Marius Venstad <jvenstad@yahoo-inc.com> | 2019-05-08 23:04:49 +0200 |
---|---|---|
committer | Jon Marius Venstad <jvenstad@yahoo-inc.com> | 2019-05-09 11:18:40 +0200 |
commit | a4fbbe508632a822d545e6d880b5a297b97c381e (patch) | |
tree | c8da87636869c2382bbbe1346259e7fe55c330a8 /controller-server | |
parent | 0f2bfc8a8478ee4f08a8ca3f0dd6453c3658b58f (diff) |
Add deploy method to JobController, which runs a deploy job
Diffstat (limited to 'controller-server')
2 files changed, 70 insertions, 2 deletions
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 43318c3dcc8..6e792e959b8 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 @@ -2,6 +2,7 @@ package com.yahoo.vespa.hosted.controller.deployment; import com.google.common.collect.ImmutableMap; +import com.yahoo.component.Version; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.Environment; import com.yahoo.vespa.curator.Lock; @@ -298,7 +299,38 @@ public class JobController { }); } - // TODO add deploy which aborts running, waits for it to stop, locks step, stores package, starts the job + /** 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) { + controller.applications().lockOrThrow(id, application -> { + if ( ! application.get().deploymentJobs().deployedInternally()) + controller.applications().store(registered(application)); + }); + if (type.environment() != Environment.dev) + throw new IllegalArgumentException("Direct deployments are only allowed to the dev environment."); + + last(id, type).filter(run -> ! run.hasEnded()).ifPresent(run -> abortAndWait(run.id())); + locked(id, type, __ -> { + controller.applications().applicationStore().putDev(id, applicationPackage.zippedContent()); + start(id, type, new Versions(platform.orElse(controller.systemVersion()), + ApplicationVersion.unknown, + Optional.empty(), + Optional.empty())); + }); + } + + /** Aborts a run and waits for it complete. */ + private void abortAndWait(RunId id) { + abort(id); + while ( ! last(id.application(), id.type()).get().hasEnded()) { + try { + Thread.sleep(100); + } + catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException(e); + } + } + } /** Unregisters the given application and makes all associated data eligible for garbage collection. */ public void unregister(ApplicationId id) { 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 41f57a80ffd..d0ffb805e61 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 @@ -5,6 +5,7 @@ import com.yahoo.component.Version; import com.yahoo.config.application.api.DeploymentSpec; import com.yahoo.config.provision.HostName; import com.yahoo.config.provision.SystemName; +import com.yahoo.config.provision.zone.ZoneId; import com.yahoo.slime.ArrayTraverser; import com.yahoo.slime.Inspector; import com.yahoo.vespa.config.SlimeUtils; @@ -18,7 +19,6 @@ 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.api.integration.deployment.TesterCloud; import com.yahoo.vespa.hosted.controller.api.integration.stubs.MockMailer; -import com.yahoo.config.provision.zone.ZoneId; import org.junit.Before; import org.junit.Test; @@ -32,12 +32,15 @@ import java.time.Duration; import java.util.Collections; import java.util.List; import java.util.Optional; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; import static com.yahoo.vespa.hosted.controller.api.integration.LogEntry.Type.debug; import static com.yahoo.vespa.hosted.controller.api.integration.LogEntry.Type.error; import static com.yahoo.vespa.hosted.controller.api.integration.LogEntry.Type.info; import static com.yahoo.vespa.hosted.controller.api.integration.LogEntry.Type.warning; import static com.yahoo.vespa.hosted.controller.deployment.InternalDeploymentTester.appId; +import static com.yahoo.vespa.hosted.controller.deployment.InternalDeploymentTester.applicationPackage; import static com.yahoo.vespa.hosted.controller.deployment.InternalDeploymentTester.testerId; import static com.yahoo.vespa.hosted.controller.deployment.Step.Status.failed; import static com.yahoo.vespa.hosted.controller.deployment.Step.Status.succeeded; @@ -45,6 +48,7 @@ import static com.yahoo.vespa.hosted.controller.deployment.Step.Status.unfinishe import static java.util.Collections.singletonList; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; /** * @author jonmv @@ -274,6 +278,38 @@ public class InternalStepRunnerTest { } @Test + public void deployToDev() { + ZoneId zone = JobType.devUsEast1.zone(tester.tester().controller().system()); + tester.jobs().deploy(appId, JobType.devUsEast1, Optional.empty(), applicationPackage); + tester.runner().run(); + RunId id = tester.jobs().last(appId, JobType.devUsEast1).get().id(); + assertEquals(unfinished, tester.jobs().run(id).get().steps().get(Step.installReal)); + + Version version = new Version("7.8.9"); + Future<?> concurrentDeployment = Executors.newSingleThreadExecutor().submit(() -> { + tester.jobs().deploy(appId, JobType.devUsEast1, Optional.of(version), applicationPackage); + }); + while ( ! concurrentDeployment.isDone()) + tester.runner().run(); + assertEquals(id.number() + 1, tester.jobs().last(appId, JobType.devUsEast1).get().id().number()); + + tester.runner().run(); + tester.configServer().convergeServices(appId, zone); + assertEquals(unfinished, tester.jobs().run(id).get().steps().get(Step.installReal)); + + tester.configServer().setVersion(appId, zone, version); + tester.runner().run(); + assertTrue(tester.jobs().active().isEmpty()); + assertEquals(version, tester.tester().application(appId).deployments().get(zone).version()); + + try { + tester.jobs().deploy(appId, JobType.productionApNortheast1, Optional.empty(), applicationPackage); + fail("Deployments outside dev should not be allowed."); + } + catch (IllegalArgumentException expected) { } + } + + @Test public void notificationIsSent() { tester.startSystemTestTests(); tester.cloud().set(TesterCloud.Status.NOT_STARTED); |