aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Marius Venstad <jvenstad@yahoo-inc.com>2018-01-04 10:42:48 +0100
committerJon Marius Venstad <jvenstad@yahoo-inc.com>2018-01-04 10:42:48 +0100
commitbcf738eab365824a62b56818a02d4147ee41cfc6 (patch)
tree6191b70c023bdb05abd4fcab489e2a4db6ad221d
parent23ed1db9ff118a45fdd2b3636599a0e7ec8521cf (diff)
Split PushingBuildSystem into a ZK backed queue and a maintainer
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/BuildSystem.java35
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentQueue.java89
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTrigger.java12
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTriggerer.java55
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/PolledBuildSystem.java117
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/PushingBuildSystem.java132
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ControllerMaintenance.java6
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java1
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentQueueTest.java (renamed from controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/PolledBuildSystemTest.java)16
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTester.java2
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTriggerTest.java30
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTriggererTest.java (renamed from controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/PushingBuildSystemTest.java)28
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/screwdriver/ScrewdriverApiTest.java1
13 files changed, 194 insertions, 330 deletions
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/BuildSystem.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/BuildSystem.java
deleted file mode 100644
index 852ae26a5b5..00000000000
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/BuildSystem.java
+++ /dev/null
@@ -1,35 +0,0 @@
-// 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.config.provision.ApplicationId;
-import com.yahoo.vespa.hosted.controller.api.integration.BuildService.BuildJob;
-import com.yahoo.vespa.hosted.controller.application.DeploymentJobs.JobType;
-
-import java.util.List;
-
-/**
- * @author jvenstad
- * @author mpolden
- */
-// TODO: Remove, and let PushingBuildSystem take its place, with a mock BuildService for testing.
-public interface BuildSystem {
-
- /**
- * Add a job for the given application to the build system
- *
- * @param applicationId the ID of the application owning the job
- * @param jobType the job type to be queued
- * @param first whether the job should be added to the front of the queue
- */
- void addJob(ApplicationId applicationId, JobType jobType, boolean first);
-
- /** Remove and return a list of jobs which should be run now */
- List<BuildJob> takeJobsToRun();
-
- /** Get a list of all jobs currently waiting to run */
- List<BuildJob> jobs();
-
- /** Removes all queued jobs for the given application */
- void removeJobs(ApplicationId applicationId);
-
-}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentQueue.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentQueue.java
new file mode 100644
index 00000000000..d961915f532
--- /dev/null
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentQueue.java
@@ -0,0 +1,89 @@
+// 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.google.common.collect.ImmutableList;
+import com.yahoo.config.provision.ApplicationId;
+import com.yahoo.vespa.curator.Lock;
+import com.yahoo.vespa.hosted.controller.Controller;
+import com.yahoo.vespa.hosted.controller.api.integration.BuildService.BuildJob;
+import com.yahoo.vespa.hosted.controller.application.DeploymentJobs.JobType;
+import com.yahoo.vespa.hosted.controller.persistence.CuratorDb;
+
+import java.util.Deque;
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Consumer;
+
+/**
+ * Stores a queue for each type of job, and offers jobs from each of these to a periodic
+ * polling mechanism which is responsible for triggering the offered jobs in an external build service.
+ *
+ * @author jvenstad
+ */
+public class DeploymentQueue {
+
+ private final Controller controller;
+ private final CuratorDb curator;
+
+ public DeploymentQueue(Controller controller, CuratorDb curator) {
+ this.controller = controller;
+ this.curator = curator;
+ }
+
+ public void addJob(ApplicationId applicationId, JobType jobType, boolean first) {
+ locked(jobType, queue -> {
+ if (first)
+ queue.addFirst(applicationId);
+ else
+ queue.addLast(applicationId);
+ });
+ }
+
+ public List<BuildJob> jobs() {
+ ImmutableList.Builder<BuildJob> builder = ImmutableList.builder();
+ for (JobType jobType : JobType.values())
+ locked(jobType, queue ->
+ queue.forEach(id -> toBuildJob(id, jobType).ifPresent(builder::add)));
+
+ return builder.build();
+ }
+
+ public List<BuildJob> takeJobsToRun() {
+ ImmutableList.Builder<BuildJob> builder = ImmutableList.builder();
+ for (JobType jobType : JobType.values())
+ locked(jobType, queue ->
+ queue.stream()
+ .limit(isCapacityConstrained(jobType) ? 1 : 1 << 30)
+ .peek(id -> toBuildJob(id, jobType).ifPresent(builder::add))
+ .forEach(queue::remove));
+
+ return builder.build();
+ }
+
+ public void removeJobs(ApplicationId applicationId) {
+ for (JobType jobType : JobType.values())
+ locked(jobType, queue -> {
+ while (queue.remove(applicationId)); // Keep removing until not found.
+ });
+ }
+
+ /** Lock the job queues and read, modify, and store the queue for the given job type. */
+ private void locked(JobType jobType, Consumer<Deque<ApplicationId>> modifications) {
+ try (Lock lock = curator.lockJobQueues()) {
+ Deque<ApplicationId> queue = curator.readJobQueue(jobType);
+ modifications.accept(queue);
+ curator.writeJobQueue(jobType, queue);
+ }
+ }
+
+ private static boolean isCapacityConstrained(JobType jobType) {
+ return jobType == JobType.stagingTest || jobType == JobType.systemTest;
+ }
+
+ private Optional<BuildJob> toBuildJob(ApplicationId applicationId, JobType jobType) {
+ return controller.applications().get(applicationId)
+ .flatMap(application -> application.deploymentJobs().projectId())
+ .map(projectId -> new BuildJob(projectId, jobType.jobName()));
+ }
+
+}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTrigger.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTrigger.java
index 2e66ff97fc6..41a9c81ef91 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTrigger.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTrigger.java
@@ -47,16 +47,16 @@ public class DeploymentTrigger {
private final Controller controller;
private final Clock clock;
- private final BuildSystem buildSystem;
+ private final DeploymentQueue deploymentQueue;
private final DeploymentOrder order;
- public DeploymentTrigger(Controller controller, CuratorDb curator, Clock clock, BuildSystem buildSystem) {
+ public DeploymentTrigger(Controller controller, CuratorDb curator, Clock clock, DeploymentQueue deploymentQueue) {
Objects.requireNonNull(controller,"controller cannot be null");
Objects.requireNonNull(curator,"curator cannot be null");
Objects.requireNonNull(clock,"clock cannot be null");
this.controller = controller;
this.clock = clock;
- this.buildSystem = buildSystem;
+ this.deploymentQueue = deploymentQueue;
this.order = new DeploymentOrder(controller);
this.jobTimeout = controller.system().equals(SystemName.main) ? Duration.ofHours(12) : Duration.ofHours(1);
}
@@ -64,7 +64,7 @@ public class DeploymentTrigger {
/** Returns the time in the past before which jobs are at this moment considered unresponsive */
public Instant jobTimeoutLimit() { return clock.instant().minus(jobTimeout); }
- public BuildSystem buildSystem() { return buildSystem; }
+ public DeploymentQueue buildSystem() { return deploymentQueue; }
public DeploymentOrder deploymentOrder() { return order; }
@@ -238,7 +238,7 @@ public class DeploymentTrigger {
*/
public void cancelChange(ApplicationId applicationId) {
applications().lockOrThrow(applicationId, application -> {
- buildSystem.removeJobs(application.id());
+ deploymentQueue.removeJobs(application.id());
applications().store(application.withDeploying(Optional.empty()));
});
}
@@ -313,7 +313,7 @@ public class DeploymentTrigger {
log.info(String.format("Triggering %s for %s, %s: %s", jobType, application,
application.deploying().map(d -> "deploying " + d).orElse("restarted deployment"),
reason));
- buildSystem.addJob(application.id(), jobType, first);
+ deploymentQueue.addJob(application.id(), jobType, first);
return application.withJobTriggering(jobType,
application.deploying(),
clock.instant(),
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTriggerer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTriggerer.java
new file mode 100644
index 00000000000..173f21bfca1
--- /dev/null
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTriggerer.java
@@ -0,0 +1,55 @@
+// 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.vespa.hosted.controller.Controller;
+import com.yahoo.vespa.hosted.controller.api.integration.BuildService;
+import com.yahoo.vespa.hosted.controller.maintenance.JobControl;
+import com.yahoo.vespa.hosted.controller.maintenance.Maintainer;
+
+import java.time.Duration;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Triggers deployment jobs in an external BuildService.
+ *
+ * Triggering is performed by an Executor, as there is no guarantee the BuildService provides a timely response.
+ *
+ * @author jvenstad
+ */
+public class DeploymentTriggerer extends Maintainer {
+
+ private static final Logger log = Logger.getLogger(DeploymentTriggerer.class.getName());
+ static final int triggeringRetries = 5;
+
+ private final BuildService buildService;
+ private final DeploymentQueue deploymentQueue;
+ private final Executor executor;
+
+ public DeploymentTriggerer(Controller controller, Duration triggeringInterval, JobControl jobControl,
+ BuildService buildService, DeploymentQueue deploymentQueue) {
+ this(controller, triggeringInterval, jobControl, buildService, deploymentQueue, Executors.newFixedThreadPool(20));
+ }
+
+ DeploymentTriggerer(Controller controller, Duration triggeringInterval, JobControl jobControl,
+ BuildService buildService, DeploymentQueue deploymentQueue, Executor executor) {
+ super(controller, triggeringInterval, jobControl);
+ this.buildService = buildService;
+ this.deploymentQueue = deploymentQueue;
+ this.executor = executor;
+ }
+
+ @Override
+ protected void maintain() {
+ deploymentQueue.takeJobsToRun().forEach(buildJob -> executor.execute(() -> {
+ for (int i = 0; i < triggeringRetries; i++)
+ if (buildService.trigger(buildJob))
+ return;
+
+ log.log(Level.WARNING, "Exhausted all " + triggeringRetries + " retries for " + buildJob + " without success.");
+ }));
+ }
+
+}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/PolledBuildSystem.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/PolledBuildSystem.java
deleted file mode 100644
index 4d793767af5..00000000000
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/PolledBuildSystem.java
+++ /dev/null
@@ -1,117 +0,0 @@
-// 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.config.provision.ApplicationId;
-import com.yahoo.vespa.curator.Lock;
-import com.yahoo.vespa.hosted.controller.Controller;
-import com.yahoo.vespa.hosted.controller.api.integration.BuildService.BuildJob;
-import com.yahoo.vespa.hosted.controller.application.DeploymentJobs.JobType;
-import com.yahoo.vespa.hosted.controller.persistence.CuratorDb;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Deque;
-import java.util.List;
-import java.util.Optional;
-import java.util.logging.Logger;
-
-/**
- * Stores a queue for each type of job, and offers jobs from each of these to a periodic
- * polling mechanism which is responsible for triggering the offered jobs in an external build service.
- *
- * @author jvenstad
- * @author mpolden
- */
-public class PolledBuildSystem implements BuildSystem {
-
- private static final Logger log = Logger.getLogger(PolledBuildSystem.class.getName());
-
- // The number of jobs to offer, on each poll, for zones that have limited capacity
- private static final int maxCapacityConstrainedJobsToOffer = 2;
-
- private final Controller controller;
- private final CuratorDb curator;
-
- public PolledBuildSystem(Controller controller, CuratorDb curator) {
- this.controller = controller;
- this.curator = curator;
- }
-
- @Override
- public void addJob(ApplicationId applicationId, JobType jobType, boolean first) {
- try (Lock lock = curator.lockJobQueues()) {
- Deque<ApplicationId> queue = curator.readJobQueue(jobType);
- if ( ! queue.contains(applicationId)) {
- if (first) {
- queue.addFirst(applicationId);
- } else {
- queue.add(applicationId);
- }
- }
- curator.writeJobQueue(jobType, queue);
- }
- }
-
- @Override
- public List<BuildJob> jobs() {
- return getJobs(false);
- }
-
- @Override
- public List<BuildJob> takeJobsToRun() {
- return getJobs(true);
- }
-
-
- @Override
- public void removeJobs(ApplicationId application) {
- try (Lock lock = curator.lockJobQueues()) {
- for (JobType jobType : JobType.values()) {
- Deque<ApplicationId> queue = curator.readJobQueue(jobType);
- while (queue.remove(application)) {
- // keep removing until not found
- }
- curator.writeJobQueue(jobType, queue);
- }
- }
- }
-
- private List<BuildJob> getJobs(boolean removeFromQueue) {
- int capacityConstrainedJobsOffered = 0;
- try (Lock lock = curator.lockJobQueues()) {
- List<BuildJob> jobsToRun = new ArrayList<>();
- for (JobType jobType : JobType.values()) {
- Deque<ApplicationId> queue = curator.readJobQueue(jobType);
- for (ApplicationId a : queue) {
- ApplicationId application = removeFromQueue ? queue.poll() : a;
-
- Optional<Long> projectId = projectId(application);
- if (projectId.isPresent()) {
- jobsToRun.add(new BuildJob(projectId.get(), jobType.jobName()));
- } else {
- log.warning("Not queuing " + jobType.jobName() + " for " + application.toShortString() +
- " because project ID is missing");
- }
-
- // Return a limited number of jobs at a time for capacity constrained zones
- if (removeFromQueue && isCapacityConstrained(jobType) &&
- ++capacityConstrainedJobsOffered >= maxCapacityConstrainedJobsToOffer) {
- break;
- }
- }
- if (removeFromQueue)
- curator.writeJobQueue(jobType, queue);
- }
- return Collections.unmodifiableList(jobsToRun);
- }
- }
-
- private Optional<Long> projectId(ApplicationId applicationId) {
- return controller.applications().require(applicationId).deploymentJobs().projectId();
- }
-
- private static boolean isCapacityConstrained(JobType jobType) {
- return jobType == JobType.stagingTest || jobType == JobType.systemTest;
- }
-
-}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/PushingBuildSystem.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/PushingBuildSystem.java
deleted file mode 100644
index f95d5f949e6..00000000000
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/PushingBuildSystem.java
+++ /dev/null
@@ -1,132 +0,0 @@
-// 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.google.common.collect.ImmutableList;
-import com.yahoo.config.provision.ApplicationId;
-import com.yahoo.vespa.curator.Lock;
-import com.yahoo.vespa.hosted.controller.Controller;
-import com.yahoo.vespa.hosted.controller.api.integration.BuildService;
-import com.yahoo.vespa.hosted.controller.api.integration.BuildService.BuildJob;
-import com.yahoo.vespa.hosted.controller.application.DeploymentJobs.JobType;
-import com.yahoo.vespa.hosted.controller.maintenance.JobControl;
-import com.yahoo.vespa.hosted.controller.maintenance.Maintainer;
-
-import java.time.Duration;
-import java.util.Deque;
-import java.util.List;
-import java.util.Optional;
-import java.util.concurrent.Executor;
-import java.util.function.Consumer;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import java.util.stream.Stream;
-
-/**
- * Stores and triggers build jobs in an external BuildService.
- *
- * Capacity constrained jobs are added to FIFO queues which are polled with a given interval.
- * Other jobs are triggered right away, with the provided BuildService, unless this maintainer
- * is currently disabled, in which case they, too, are stored in queues.
- *
- * All triggering (constrained and otherwise) can be turned off in the given JobControl.
- *
- * Triggering is performed by an Executor, as there is no guarantee the BuildService provides a timely response.
- *
- * @author jvenstad
- */
-public class PushingBuildSystem extends Maintainer implements BuildSystem {
-
- private static final Logger log = Logger.getLogger(PushingBuildSystem.class.getName());
- static final int triggeringRetries = 5;
-
- private final Executor executor;
- private final BuildService buildService;
-
- public PushingBuildSystem(Controller controller, Duration triggeringInterval, JobControl jobControl,
- BuildService buildService, Executor executor) {
- super(controller, triggeringInterval, jobControl);
- this.buildService = buildService;
- this.executor = executor;
- }
-
- @Override
- public void addJob(ApplicationId applicationId, JobType jobType, boolean first) {
- if (isCapacityConstrained(jobType) || ! jobControl().isActive(name()))
- locked(jobType, queue -> {
- if (first)
- queue.addFirst(applicationId);
- else
- queue.addLast(applicationId);
- });
- else
- triggerWithRetries(applicationId, jobType);
- }
-
- @Override
- public List<BuildJob> jobs() {
- ImmutableList.Builder<BuildJob> builder = ImmutableList.builder();
- for (JobType jobType : JobType.values())
- for (ApplicationId applicationId : curator().readJobQueue(jobType))
- projectId(applicationId).ifPresent(projectId -> builder.add(new BuildJob(projectId, jobType.jobName())));
-
- return builder.build();
- }
-
- @Override
- public List<BuildJob> takeJobsToRun() {
- throw new UnsupportedOperationException("I'll do that myself, thank you very much!");
- }
-
- @Override
- public void removeJobs(ApplicationId applicationId) {
- for (JobType jobType : JobType.values())
- locked(jobType, queue -> {
- while (queue.remove(applicationId)); // Keep removing until not found.
- });
- }
-
- @Override
- protected void maintain() {
- triggerStoredJobs();
- }
-
- private void triggerStoredJobs() {
- for (JobType jobType : JobType.values())
- locked(jobType, queue ->
- queue.stream()
- .limit(isCapacityConstrained(jobType) ? 1 : 10)
- .peek(applicationId -> triggerWithRetries(applicationId, jobType))
- .forEach(queue::remove));
- }
-
- private void triggerWithRetries(ApplicationId applicationId, JobType jobType) {
- projectId(applicationId).ifPresent(projectId -> {
- executor.execute(() -> {
- for (int i = 0; i < triggeringRetries; i++)
- if (buildService.trigger(new BuildJob(projectId, jobType.jobName())))
- return;
-
- log.log(Level.WARNING, "Exhausted all " + triggeringRetries + " retries without success.");
- });
- });
- }
-
- private Optional<Long> projectId(ApplicationId applicationId) {
- return controller().applications().get(applicationId)
- .flatMap(application -> application.deploymentJobs().projectId());
- }
-
- private static boolean isCapacityConstrained(JobType jobType) {
- return jobType == JobType.stagingTest || jobType == JobType.systemTest;
- }
-
- /** Lock the job queues and read, modify, and store the queue for the given job type. */
- private void locked(JobType jobType, Consumer<Deque<ApplicationId>> modifications) {
- try (Lock lock = curator().lockJobQueues()) {
- Deque<ApplicationId> queue = curator().readJobQueue(jobType);
- modifications.accept(queue);
- curator().writeJobQueue(jobType, queue);
- }
- }
-
-}
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 7d4af84c3a6..5e76be9d384 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
@@ -9,10 +9,12 @@ import com.yahoo.vespa.hosted.controller.api.integration.BuildService;
import com.yahoo.vespa.hosted.controller.api.integration.organization.OwnershipIssues;
import com.yahoo.vespa.hosted.controller.api.integration.organization.DeploymentIssues;
import com.yahoo.vespa.hosted.controller.api.integration.chef.Chef;
+import com.yahoo.vespa.hosted.controller.deployment.DeploymentTriggerer;
import com.yahoo.vespa.hosted.controller.maintenance.config.MaintainerConfig;
import com.yahoo.vespa.hosted.controller.persistence.CuratorDb;
import java.time.Duration;
+import java.util.concurrent.Executors;
/**
* Maintenance jobs of the controller.
@@ -37,6 +39,7 @@ public class ControllerMaintenance extends AbstractComponent {
private final DeploymentMetricsMaintainer deploymentMetricsMaintainer;
private final ApplicationOwnershipConfirmer applicationOwnershipConfirmer;
private final DnsMaintainer dnsMaintainer;
+ private final DeploymentTriggerer deploymentTriggerer;
@SuppressWarnings("unused") // instantiated by Dependency Injection
public ControllerMaintenance(MaintainerConfig maintainerConfig, Controller controller, CuratorDb curator,
@@ -57,6 +60,8 @@ public class ControllerMaintenance extends AbstractComponent {
deploymentMetricsMaintainer = new DeploymentMetricsMaintainer(controller, Duration.ofMinutes(10), jobControl);
applicationOwnershipConfirmer = new ApplicationOwnershipConfirmer(controller, Duration.ofHours(12), jobControl, ownershipIssues);
dnsMaintainer = new DnsMaintainer(controller, Duration.ofHours(1), jobControl, nameService);
+ deploymentTriggerer = new DeploymentTriggerer(controller, Duration.ofSeconds(30), jobControl, buildService,
+ controller.applications().deploymentTrigger().buildSystem());
}
public Upgrader upgrader() { return upgrader; }
@@ -78,6 +83,7 @@ public class ControllerMaintenance extends AbstractComponent {
deploymentMetricsMaintainer.deconstruct();
applicationOwnershipConfirmer.deconstruct();
dnsMaintainer.deconstruct();
+ deploymentTriggerer.deconstruct();
}
}
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 17801bde546..47c5280108f 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
@@ -34,7 +34,6 @@ import com.yahoo.vespa.hosted.controller.application.DeploymentJobs.JobType;
import com.yahoo.vespa.hosted.controller.application.JobStatus;
import com.yahoo.vespa.hosted.controller.athenz.mock.AthenzDbMock;
import com.yahoo.vespa.hosted.controller.deployment.ApplicationPackageBuilder;
-import com.yahoo.vespa.hosted.controller.deployment.BuildSystem;
import com.yahoo.vespa.hosted.controller.deployment.DeploymentTester;
import com.yahoo.vespa.hosted.controller.persistence.ApplicationSerializer;
import com.yahoo.vespa.hosted.controller.rotation.RotationId;
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/PolledBuildSystemTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentQueueTest.java
index e66d7e9168d..fa99ef5a03a 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/PolledBuildSystemTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentQueueTest.java
@@ -19,7 +19,7 @@ import static org.junit.Assert.assertEquals;
* @author mpolden
*/
@RunWith(Parameterized.class)
-public class PolledBuildSystemTest {
+public class DeploymentQueueTest {
@Parameterized.Parameters(name = "jobType={0}")
public static Iterable<?> capacityConstrainedJobs() {
@@ -28,14 +28,14 @@ public class PolledBuildSystemTest {
private final JobType jobType;
- public PolledBuildSystemTest(JobType jobType) {
+ public DeploymentQueueTest(JobType jobType) {
this.jobType = jobType;
}
@Test
public void throttle_capacity_constrained_jobs() {
DeploymentTester tester = new DeploymentTester();
- BuildSystem buildSystem = new PolledBuildSystem(tester.controller(), new MockCuratorDb());
+ DeploymentQueue deploymentQueue = new DeploymentQueue(tester.controller(), new MockCuratorDb());
int project1 = 1;
int project2 = 2;
@@ -48,19 +48,19 @@ public class PolledBuildSystemTest {
ApplicationId app3 = tester.createAndDeploy("app3", project3, applicationPackage).id();
// Trigger jobs in capacity constrained environment
- buildSystem.addJob(app1, jobType, false);
- buildSystem.addJob(app2, jobType, false);
- buildSystem.addJob(app3, jobType, false);
+ deploymentQueue.addJob(app1, jobType, false);
+ deploymentQueue.addJob(app2, jobType, false);
+ deploymentQueue.addJob(app3, jobType, false);
// A limited number of jobs are offered at a time:
// First offer
- List<BuildJob> nextJobs = buildSystem.takeJobsToRun();
+ List<BuildJob> nextJobs = deploymentQueue.takeJobsToRun();
assertEquals(2, nextJobs.size());
assertEquals(project1, nextJobs.get(0).projectId());
assertEquals(project2, nextJobs.get(1).projectId());
// Second offer
- nextJobs = buildSystem.takeJobsToRun();
+ nextJobs = deploymentQueue.takeJobsToRun();
assertEquals(1, nextJobs.size());
assertEquals(project3, nextJobs.get(0).projectId());
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTester.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTester.java
index 2b0e953c12c..637d015b6ad 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTester.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTester.java
@@ -71,7 +71,7 @@ public class DeploymentTester {
// TODO: This thing simulates the wrong thing: the build system won't hold the jobs that are running,
// and so these should be consumed immediately upon triggering, and be "somewhere else" while running.
- public BuildSystem buildSystem() { return tester.controller().applications().deploymentTrigger().buildSystem(); }
+ public DeploymentQueue buildSystem() { return tester.controller().applications().deploymentTrigger().buildSystem(); }
public DeploymentTrigger deploymentTrigger() { return tester.controller().applications().deploymentTrigger(); }
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 10f8e80f318..94aaed6df63 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
@@ -79,7 +79,7 @@ public class DeploymentTriggerTest {
@Test
public void deploymentSpecDecidesTriggerOrder() {
DeploymentTester tester = new DeploymentTester();
- BuildSystem buildSystem = tester.buildSystem();
+ DeploymentQueue deploymentQueue = tester.buildSystem();
TenantId tenant = tester.controllerTester().createTenant("tenant1", "domain1", 1L);
Application application = tester.controllerTester().createApplication(tenant, "app1", "default", 1L);
ApplicationPackage applicationPackage = new ApplicationPackageBuilder()
@@ -98,13 +98,13 @@ public class DeploymentTriggerTest {
tester.deployAndNotify(application, applicationPackage, true, JobType.productionCorpUsEast1);
tester.deployAndNotify(application, applicationPackage, true, JobType.productionUsCentral1);
tester.deployAndNotify(application, applicationPackage, true, JobType.productionUsWest1);
- assertTrue("All jobs consumed", buildSystem.jobs().isEmpty());
+ assertTrue("All jobs consumed", deploymentQueue.jobs().isEmpty());
}
@Test
public void deploymentsSpecWithDelays() {
DeploymentTester tester = new DeploymentTester();
- BuildSystem buildSystem = tester.buildSystem();
+ DeploymentQueue deploymentQueue = tester.buildSystem();
Application application = tester.createApplication("app1", "tenant1", 1, 1L);
ApplicationPackage applicationPackage = new ApplicationPackageBuilder()
@@ -124,21 +124,21 @@ public class DeploymentTriggerTest {
tester.deployAndNotify(application, applicationPackage, true, JobType.systemTest);
tester.clock().advance(Duration.ofSeconds(1)); // Make staging test sort as the last successful job
tester.deployAndNotify(application, applicationPackage, true, JobType.stagingTest);
- assertTrue("No more jobs triggered at this time", buildSystem.jobs().isEmpty());
+ assertTrue("No more jobs triggered at this time", deploymentQueue.jobs().isEmpty());
// 30 seconds pass, us-west-1 is triggered
tester.clock().advance(Duration.ofSeconds(30));
tester.deploymentTrigger().triggerReadyJobs();
// Consume us-west-1 job without reporting completion
- assertEquals(1, buildSystem.jobs().size());
- assertEquals(JobType.productionUsWest1.jobName(), buildSystem.jobs().get(0).jobName());
- buildSystem.takeJobsToRun();
+ assertEquals(1, deploymentQueue.jobs().size());
+ assertEquals(JobType.productionUsWest1.jobName(), deploymentQueue.jobs().get(0).jobName());
+ deploymentQueue.takeJobsToRun();
// 3 minutes pass, delayed trigger does nothing as us-west-1 is still in progress
tester.clock().advance(Duration.ofMinutes(3));
tester.deploymentTrigger().triggerReadyJobs();
- assertTrue("No more jobs triggered at this time", buildSystem.jobs().isEmpty());
+ assertTrue("No more jobs triggered at this time", deploymentQueue.jobs().isEmpty());
// us-west-1 completes
tester.deploy(JobType.productionUsWest1, application, applicationPackage);
@@ -146,18 +146,18 @@ public class DeploymentTriggerTest {
// Delayed trigger does nothing as not enough time has passed after us-west-1 completion
tester.deploymentTrigger().triggerReadyJobs();
- assertTrue("No more jobs triggered at this time", buildSystem.jobs().isEmpty());
+ assertTrue("No more jobs triggered at this time", deploymentQueue.jobs().isEmpty());
// 3 minutes pass, us-central-1 is triggered
tester.clock().advance(Duration.ofMinutes(3));
tester.deploymentTrigger().triggerReadyJobs();
tester.deployAndNotify(application, applicationPackage, true, JobType.productionUsCentral1);
- assertTrue("All jobs consumed", buildSystem.jobs().isEmpty());
+ assertTrue("All jobs consumed", deploymentQueue.jobs().isEmpty());
// Delayed trigger job runs again, with nothing to trigger
tester.clock().advance(Duration.ofMinutes(10));
tester.deploymentTrigger().triggerReadyJobs();
- assertTrue("All jobs consumed", buildSystem.jobs().isEmpty());
+ assertTrue("All jobs consumed", deploymentQueue.jobs().isEmpty());
}
@Test
@@ -235,7 +235,7 @@ public class DeploymentTriggerTest {
@Test
public void testSuccessfulDeploymentApplicationPackageChanged() {
DeploymentTester tester = new DeploymentTester();
- BuildSystem buildSystem = tester.buildSystem();
+ DeploymentQueue deploymentQueue = tester.buildSystem();
TenantId tenant = tester.controllerTester().createTenant("tenant1", "domain1", 1L);
Application application = tester.controllerTester().createApplication(tenant, "app1", "default", 1L);
ApplicationPackage previousApplicationPackage = new ApplicationPackageBuilder()
@@ -263,7 +263,7 @@ public class DeploymentTriggerTest {
tester.deployAndNotify(application, newApplicationPackage, true, JobType.productionUsCentral1);
tester.deployAndNotify(application, newApplicationPackage, true, JobType.productionUsWest1);
tester.deployAndNotify(application, newApplicationPackage, true, JobType.productionApNortheast1);
- assertTrue("All jobs consumed", buildSystem.jobs().isEmpty());
+ assertTrue("All jobs consumed", deploymentQueue.jobs().isEmpty());
}
@Test
@@ -333,7 +333,7 @@ public class DeploymentTriggerTest {
@Test
public void testHandleMultipleNotificationsFromLastJob() {
DeploymentTester tester = new DeploymentTester();
- BuildSystem buildSystem = tester.buildSystem();
+ DeploymentQueue deploymentQueue = tester.buildSystem();
TenantId tenant = tester.controllerTester().createTenant("tenant1", "domain1", 1L);
Application application = tester.controllerTester().createApplication(tenant, "app1", "default", 1L);
ApplicationPackage applicationPackage = new ApplicationPackageBuilder()
@@ -353,7 +353,7 @@ public class DeploymentTriggerTest {
tester.notifyJobCompletion(JobType.productionCorpUsEast1, application, true);
assertFalse("Change has been deployed",
tester.applications().require(application.id()).deploying().isPresent());
- assertTrue("All jobs consumed", buildSystem.jobs().isEmpty());
+ assertTrue("All jobs consumed", deploymentQueue.jobs().isEmpty());
}
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/PushingBuildSystemTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTriggererTest.java
index 015d714c23d..ba2eb10a8ca 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/PushingBuildSystemTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/DeploymentTriggererTest.java
@@ -17,17 +17,17 @@ import static org.junit.Assert.assertEquals;
/**
* @author jvenstad
*/
-public class PushingBuildSystemTest {
+public class DeploymentTriggererTest {
@Test
public void testTriggering() {
DeploymentTester tester = new DeploymentTester();
JobControl jobControl = new JobControl(tester.controller().curator());
- BuildSystem buildSystem = new PushingBuildSystem(tester.controller(),
- Duration.ofDays(1),
- jobControl,
- new MockBuildService(),
- Runnable::run);
+ DeploymentQueue deploymentQueue = new DeploymentTriggerer(tester.controller(),
+ Duration.ofDays(1),
+ jobControl,
+ new MockBuildService(),
+ Runnable::run);
// Make sure the applications exist in the controller, as the build system uses this information.
ApplicationId app1 = tester.createAndDeploy("app1", 1, "default-policy").id();
@@ -35,22 +35,22 @@ public class PushingBuildSystemTest {
ApplicationId app3 = tester.createAndDeploy("app3", 3, "default-policy").id();
// Trigger jobs in a capacity-constrained environment.
- buildSystem.addJob(app1, systemTest, false);
- buildSystem.addJob(app2, systemTest, false);
- buildSystem.addJob(app3, systemTest, false);
+ deploymentQueue.addJob(app1, systemTest, false);
+ deploymentQueue.addJob(app2, systemTest, false);
+ deploymentQueue.addJob(app3, systemTest, false);
// Trigger jobs in a non-constrained environment.
- buildSystem.addJob(app1, productionUsWest1, false);
- buildSystem.addJob(app2, productionUsWest1, false);
- buildSystem.addJob(app3, productionUsWest1, false);
+ deploymentQueue.addJob(app1, productionUsWest1, false);
+ deploymentQueue.addJob(app2, productionUsWest1, false);
+ deploymentQueue.addJob(app3, productionUsWest1, false);
// A single capacity-constrained job is triggered each run.
- List<BuildService.BuildJob> nextJobs = buildSystem.takeJobsToRun();
+ List<BuildService.BuildJob> nextJobs = deploymentQueue.takeJobsToRun();
assertEquals(2, nextJobs.size());
assertEquals(project1, nextJobs.get(0).projectId());
assertEquals(project2, nextJobs.get(1).projectId());
- nextJobs = buildSystem.takeJobsToRun();
+ nextJobs = deploymentQueue.takeJobsToRun();
assertEquals(1, nextJobs.size());
assertEquals(project3, nextJobs.get(0).projectId());
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/screwdriver/ScrewdriverApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/screwdriver/ScrewdriverApiTest.java
index d680d943f84..7adc593278a 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/screwdriver/ScrewdriverApiTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/screwdriver/ScrewdriverApiTest.java
@@ -15,7 +15,6 @@ import com.yahoo.vespa.hosted.controller.application.DeploymentJobs.JobError;
import com.yahoo.vespa.hosted.controller.application.DeploymentJobs.JobType;
import com.yahoo.vespa.hosted.controller.application.JobStatus;
import com.yahoo.vespa.hosted.controller.deployment.ApplicationPackageBuilder;
-import com.yahoo.vespa.hosted.controller.deployment.BuildSystem;
import com.yahoo.vespa.hosted.controller.restapi.ContainerControllerTester;
import com.yahoo.vespa.hosted.controller.restapi.ControllerContainerTest;
import com.yahoo.vespa.hosted.controller.versions.VersionStatus;