diff options
author | Jon Marius Venstad <jvenstad@yahoo-inc.com> | 2018-01-04 10:42:48 +0100 |
---|---|---|
committer | Jon Marius Venstad <jvenstad@yahoo-inc.com> | 2018-01-04 10:42:48 +0100 |
commit | bcf738eab365824a62b56818a02d4147ee41cfc6 (patch) | |
tree | 6191b70c023bdb05abd4fcab489e2a4db6ad221d | |
parent | 23ed1db9ff118a45fdd2b3636599a0e7ec8521cf (diff) |
Split PushingBuildSystem into a ZK backed queue and a maintainer
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; |