diff options
author | Jon Marius Venstad <venstad@gmail.com> | 2019-09-18 13:25:53 +0200 |
---|---|---|
committer | Jon Marius Venstad <venstad@gmail.com> | 2019-09-18 16:39:10 +0200 |
commit | 9a396151e692152294f1382e896b92861b79f8ff (patch) | |
tree | 1e67bc316edb9565e12bd3ea3d83843daef4e99d | |
parent | a64c2bec5539a200769a973702ba6543ae621837 (diff) |
(Locked)?Application(Serializer|List)? renamed with Instance
17 files changed, 425 insertions, 425 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 e0203f4063e..f8685501fc7 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 @@ -256,7 +256,7 @@ public class ApplicationController { if ( ! id.instance().isTester()) // Only store the application permits for non-user applications. accessControl.createApplication(id, credentials.get()); } - LockedApplication application = new LockedApplication(new Instance(id, clock.instant()), lock); + LockedInstance application = new LockedInstance(new Instance(id, clock.instant()), lock); store(application); log.info("Created " + application); return application.get(); @@ -292,7 +292,7 @@ public class ApplicationController { Optional<ApplicationCertificate> applicationCertificate; try (Lock lock = lock(applicationId)) { - LockedApplication application = new LockedApplication(require(applicationId), lock); + LockedInstance application = new LockedInstance(require(applicationId), lock); boolean manuallyDeployed = options.deployDirectly || zone.environment().isManuallyDeployed(); boolean preferOldestVersion = options.deployCurrentVersion; @@ -396,7 +396,7 @@ public class ApplicationController { } /** Stores the deployment spec and validation overrides from the application package, and runs cleanup. */ - public LockedApplication storeWithUpdatedConfig(LockedApplication application, ApplicationPackage applicationPackage) { + public LockedInstance storeWithUpdatedConfig(LockedInstance application, ApplicationPackage applicationPackage) { deploymentSpecValidator.validate(applicationPackage.deploymentSpec()); application = application.with(applicationPackage.deploymentSpec()); @@ -459,7 +459,7 @@ public class ApplicationController { } /** Makes sure the application has a global rotation, if eligible. */ - private LockedApplication withRotation(LockedApplication application, ZoneId zone) { + private LockedInstance withRotation(LockedInstance application, ZoneId zone) { if (zone.environment() == Environment.prod) { try (RotationLock rotationLock = rotationRepository.lock()) { var rotations = rotationRepository.getOrAssignRotations(application.get(), rotationLock); @@ -566,7 +566,7 @@ public class ApplicationController { return new ActivateResult(new RevisionId("0"), prepareResponse, 0); } - private LockedApplication withoutDeletedDeployments(LockedApplication application) { + private LockedInstance withoutDeletedDeployments(LockedInstance application) { List<Deployment> deploymentsToRemove = application.get().productionDeployments().values().stream() .filter(deployment -> ! application.get().deploymentSpec().includes(deployment.zone().environment(), Optional.of(deployment.zone().region()))) @@ -585,13 +585,13 @@ public class ApplicationController { " in deployment.xml. " + ValidationOverrides.toAllowMessage(ValidationId.deploymentRemoval)); - LockedApplication applicationWithRemoval = application; + LockedInstance applicationWithRemoval = application; for (Deployment deployment : deploymentsToRemove) applicationWithRemoval = deactivate(applicationWithRemoval, deployment.zone()); return applicationWithRemoval; } - private LockedApplication withoutUnreferencedDeploymentJobs(LockedApplication application) { + private LockedInstance withoutUnreferencedDeploymentJobs(LockedInstance application) { for (JobType job : JobList.from(application.get()).production().mapToList(JobStatus::type)) { ZoneId zone = job.zone(controller.system()); if (application.get().deploymentSpec().includes(zone.environment(), Optional.of(zone.region()))) @@ -733,7 +733,7 @@ public class ApplicationController { * * @param application a locked application to store */ - public void store(LockedApplication application) { + public void store(LockedInstance application) { curator.writeApplication(application.get()); } @@ -743,9 +743,9 @@ public class ApplicationController { * @param applicationId ID of the application to lock and get. * @param action Function which acts on the locked application. */ - public void lockIfPresent(ApplicationId applicationId, Consumer<LockedApplication> action) { + public void lockIfPresent(ApplicationId applicationId, Consumer<LockedInstance> action) { try (Lock lock = lock(applicationId)) { - get(applicationId).map(application -> new LockedApplication(application, lock)).ifPresent(action); + get(applicationId).map(application -> new LockedInstance(application, lock)).ifPresent(action); } } @@ -756,9 +756,9 @@ public class ApplicationController { * @param action Function which acts on the locked application. * @throws IllegalArgumentException when application does not exist. */ - public void lockOrThrow(ApplicationId applicationId, Consumer<LockedApplication> action) { + public void lockOrThrow(ApplicationId applicationId, Consumer<LockedInstance> action) { try (Lock lock = lock(applicationId)) { - action.accept(new LockedApplication(require(applicationId), lock)); + action.accept(new LockedInstance(require(applicationId), lock)); } } @@ -788,7 +788,7 @@ public class ApplicationController { /** Deactivate application in the given zone */ public void deactivate(ApplicationId application, ZoneId zone) { - lockOrThrow(application, lockedApplication -> store(deactivate(lockedApplication, zone))); + lockOrThrow(application, lockedInstance -> store(deactivate(lockedInstance, zone))); } /** @@ -796,7 +796,7 @@ public class ApplicationController { * * @return the application with the deployment in the given zone removed */ - private LockedApplication deactivate(LockedApplication application, ZoneId zone) { + private LockedInstance deactivate(LockedInstance application, ZoneId zone) { try { configServer.deactivate(new DeploymentId(application.get().id(), zone)); } catch (NotFoundException ignored) { diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/LockedApplication.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/LockedApplication.java deleted file mode 100644 index 88fc6307a84..00000000000 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/LockedApplication.java +++ /dev/null @@ -1,288 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.hosted.controller; - -import com.yahoo.component.Version; -import com.yahoo.config.application.api.DeploymentSpec; -import com.yahoo.config.application.api.ValidationOverrides; -import com.yahoo.config.provision.ApplicationId; -import com.yahoo.config.provision.ClusterSpec; -import com.yahoo.config.provision.zone.ZoneId; -import com.yahoo.vespa.curator.Lock; -import com.yahoo.vespa.hosted.controller.api.integration.deployment.ApplicationVersion; -import com.yahoo.vespa.hosted.controller.api.integration.deployment.JobType; -import com.yahoo.vespa.hosted.controller.api.integration.organization.IssueId; -import com.yahoo.vespa.hosted.controller.api.integration.organization.User; -import com.yahoo.vespa.hosted.controller.application.AssignedRotation; -import com.yahoo.vespa.hosted.controller.application.Change; -import com.yahoo.vespa.hosted.controller.application.ClusterInfo; -import com.yahoo.vespa.hosted.controller.application.ClusterUtilization; -import com.yahoo.vespa.hosted.controller.application.Deployment; -import com.yahoo.vespa.hosted.controller.application.DeploymentJobs; -import com.yahoo.vespa.hosted.controller.application.DeploymentMetrics; -import com.yahoo.vespa.hosted.controller.application.JobStatus; -import com.yahoo.vespa.hosted.controller.metric.ApplicationMetrics; -import com.yahoo.vespa.hosted.controller.rotation.RotationStatus; - -import java.time.Instant; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.OptionalInt; -import java.util.OptionalLong; - -/** - * An application that has been locked for modification. Provides methods for modifying an application's fields. - * - * @author mpolden - * @author jonmv - */ -public class LockedApplication { - - private final Lock lock; - private final ApplicationId id; - private final Instant createdAt; - private final DeploymentSpec deploymentSpec; - private final ValidationOverrides validationOverrides; - private final Map<ZoneId, Deployment> deployments; - private final DeploymentJobs deploymentJobs; - private final Change change; - private final Change outstandingChange; - private final Optional<IssueId> ownershipIssueId; - private final Optional<User> owner; - private final OptionalInt majorVersion; - private final ApplicationMetrics metrics; - private final Optional<String> pemDeployKey; - private final List<AssignedRotation> rotations; - private final RotationStatus rotationStatus; - - /** - * Used to create a locked application - * - * @param instance The application to lock. - * @param lock The lock for the application. - */ - LockedApplication(Instance instance, Lock lock) { - this(Objects.requireNonNull(lock, "lock cannot be null"), instance.id(), instance.createdAt(), - instance.deploymentSpec(), instance.validationOverrides(), - instance.deployments(), - instance.deploymentJobs(), instance.change(), instance.outstandingChange(), - instance.ownershipIssueId(), instance.owner(), instance.majorVersion(), instance.metrics(), - instance.pemDeployKey(), instance.rotations(), instance.rotationStatus()); - } - - private LockedApplication(Lock lock, ApplicationId id, Instant createdAt, - DeploymentSpec deploymentSpec, ValidationOverrides validationOverrides, - Map<ZoneId, Deployment> deployments, DeploymentJobs deploymentJobs, Change change, - Change outstandingChange, Optional<IssueId> ownershipIssueId, Optional<User> owner, - OptionalInt majorVersion, ApplicationMetrics metrics, Optional<String> pemDeployKey, - List<AssignedRotation> rotations, RotationStatus rotationStatus) { - this.lock = lock; - this.id = id; - this.createdAt = createdAt; - this.deploymentSpec = deploymentSpec; - this.validationOverrides = validationOverrides; - this.deployments = deployments; - this.deploymentJobs = deploymentJobs; - this.change = change; - this.outstandingChange = outstandingChange; - this.ownershipIssueId = ownershipIssueId; - this.owner = owner; - this.majorVersion = majorVersion; - this.metrics = metrics; - this.pemDeployKey = pemDeployKey; - this.rotations = rotations; - this.rotationStatus = rotationStatus; - } - - /** Returns a read-only copy of this */ - public Instance get() { - return new Instance(id, createdAt, deploymentSpec, validationOverrides, deployments, deploymentJobs, change, - outstandingChange, ownershipIssueId, owner, majorVersion, metrics, pemDeployKey, - rotations, rotationStatus); - } - - public LockedApplication withBuiltInternally(boolean builtInternally) { - return new LockedApplication(lock, id, createdAt, deploymentSpec, validationOverrides, deployments, - deploymentJobs.withBuiltInternally(builtInternally), change, outstandingChange, - ownershipIssueId, owner, majorVersion, metrics, pemDeployKey, - rotations, rotationStatus); - } - - public LockedApplication withProjectId(OptionalLong projectId) { - return new LockedApplication(lock, id, createdAt, deploymentSpec, validationOverrides, deployments, - deploymentJobs.withProjectId(projectId), change, outstandingChange, - ownershipIssueId, owner, majorVersion, metrics, pemDeployKey, - rotations, rotationStatus); - } - - public LockedApplication withDeploymentIssueId(IssueId issueId) { - return new LockedApplication(lock, id, createdAt, deploymentSpec, validationOverrides, deployments, - deploymentJobs.with(issueId), change, outstandingChange, - ownershipIssueId, owner, majorVersion, metrics, pemDeployKey, - rotations, rotationStatus); - } - - public LockedApplication withJobPause(JobType jobType, OptionalLong pausedUntil) { - return new LockedApplication(lock, id, createdAt, deploymentSpec, validationOverrides, deployments, - deploymentJobs.withPause(jobType, pausedUntil), change, outstandingChange, - ownershipIssueId, owner, majorVersion, metrics, pemDeployKey, - rotations, rotationStatus); - } - - public LockedApplication withJobCompletion(long projectId, JobType jobType, JobStatus.JobRun completion, - Optional<DeploymentJobs.JobError> jobError) { - return new LockedApplication(lock, id, createdAt, deploymentSpec, validationOverrides, deployments, - deploymentJobs.withCompletion(projectId, jobType, completion, jobError), - change, outstandingChange, ownershipIssueId, owner, majorVersion, metrics, - pemDeployKey, rotations, rotationStatus); - } - - public LockedApplication withJobTriggering(JobType jobType, JobStatus.JobRun job) { - return new LockedApplication(lock, id, createdAt, deploymentSpec, validationOverrides, deployments, - deploymentJobs.withTriggering(jobType, job), change, outstandingChange, - ownershipIssueId, owner, majorVersion, metrics, pemDeployKey, - rotations, rotationStatus); - } - - public LockedApplication withNewDeployment(ZoneId zone, ApplicationVersion applicationVersion, Version version, - Instant instant, Map<DeploymentMetrics.Warning, Integer> warnings) { - // Use info from previous deployment if available, otherwise create a new one. - Deployment previousDeployment = deployments.getOrDefault(zone, new Deployment(zone, applicationVersion, - version, instant)); - Deployment newDeployment = new Deployment(zone, applicationVersion, version, instant, - previousDeployment.clusterUtils(), - previousDeployment.clusterInfo(), - previousDeployment.metrics().with(warnings), - previousDeployment.activity()); - return with(newDeployment); - } - - public LockedApplication withClusterUtilization(ZoneId zone, Map<ClusterSpec.Id, ClusterUtilization> clusterUtilization) { - Deployment deployment = deployments.get(zone); - if (deployment == null) return this; // No longer deployed in this zone. - return with(deployment.withClusterUtils(clusterUtilization)); - } - - public LockedApplication withClusterInfo(ZoneId zone, Map<ClusterSpec.Id, ClusterInfo> clusterInfo) { - Deployment deployment = deployments.get(zone); - if (deployment == null) return this; // No longer deployed in this zone. - return with(deployment.withClusterInfo(clusterInfo)); - - } - - public LockedApplication recordActivityAt(Instant instant, ZoneId zone) { - Deployment deployment = deployments.get(zone); - if (deployment == null) return this; - return with(deployment.recordActivityAt(instant)); - } - - public LockedApplication with(ZoneId zone, DeploymentMetrics deploymentMetrics) { - Deployment deployment = deployments.get(zone); - if (deployment == null) return this; // No longer deployed in this zone. - return with(deployment.withMetrics(deploymentMetrics)); - } - - public LockedApplication withoutDeploymentIn(ZoneId zone) { - Map<ZoneId, Deployment> deployments = new LinkedHashMap<>(this.deployments); - deployments.remove(zone); - return with(deployments); - } - - public LockedApplication withoutDeploymentJob(JobType jobType) { - return new LockedApplication(lock, id, createdAt, deploymentSpec, validationOverrides, deployments, - deploymentJobs.without(jobType), change, outstandingChange, - ownershipIssueId, owner, majorVersion, metrics, pemDeployKey, - rotations, rotationStatus); - } - - public LockedApplication with(DeploymentSpec deploymentSpec) { - return new LockedApplication(lock, id, createdAt, deploymentSpec, validationOverrides, deployments, - deploymentJobs, change, outstandingChange, - ownershipIssueId, owner, majorVersion, metrics, pemDeployKey, - rotations, rotationStatus); - } - - public LockedApplication with(ValidationOverrides validationOverrides) { - return new LockedApplication(lock, id, createdAt, deploymentSpec, validationOverrides, deployments, - deploymentJobs, change, outstandingChange, ownershipIssueId, owner, majorVersion, - metrics, pemDeployKey, rotations, rotationStatus); - } - - public LockedApplication withChange(Change change) { - return new LockedApplication(lock, id, createdAt, deploymentSpec, validationOverrides, deployments, - deploymentJobs, change, outstandingChange, ownershipIssueId, owner, majorVersion, - metrics, pemDeployKey, rotations, rotationStatus); - } - - public LockedApplication withOutstandingChange(Change outstandingChange) { - return new LockedApplication(lock, id, createdAt, deploymentSpec, validationOverrides, deployments, - deploymentJobs, change, outstandingChange, ownershipIssueId, owner, majorVersion, - metrics, pemDeployKey, rotations, rotationStatus); - } - - public LockedApplication withOwnershipIssueId(IssueId issueId) { - return new LockedApplication(lock, id, createdAt, deploymentSpec, validationOverrides, deployments, - deploymentJobs, change, outstandingChange, Optional.ofNullable(issueId), owner, - majorVersion, metrics, pemDeployKey, rotations, rotationStatus); - } - - public LockedApplication withOwner(User owner) { - return new LockedApplication(lock, id, createdAt, deploymentSpec, validationOverrides, deployments, - deploymentJobs, change, outstandingChange, ownershipIssueId, - Optional.ofNullable(owner), majorVersion, metrics, pemDeployKey, - rotations, rotationStatus); - } - - /** Set a major version for this, or set to null to remove any major version override */ - public LockedApplication withMajorVersion(Integer majorVersion) { - return new LockedApplication(lock, id, createdAt, deploymentSpec, validationOverrides, deployments, - deploymentJobs, change, outstandingChange, ownershipIssueId, owner, - majorVersion == null ? OptionalInt.empty() : OptionalInt.of(majorVersion), - metrics, pemDeployKey, rotations, rotationStatus); - } - - public LockedApplication with(ApplicationMetrics metrics) { - return new LockedApplication(lock, id, createdAt, deploymentSpec, validationOverrides, deployments, - deploymentJobs, change, outstandingChange, ownershipIssueId, owner, majorVersion, - metrics, pemDeployKey, rotations, rotationStatus); - } - - public LockedApplication withPemDeployKey(String pemDeployKey) { - return new LockedApplication(lock, id, createdAt, deploymentSpec, validationOverrides, deployments, - deploymentJobs, change, outstandingChange, ownershipIssueId, owner, majorVersion, - metrics, Optional.ofNullable(pemDeployKey), rotations, rotationStatus); - } - - public LockedApplication with(List<AssignedRotation> assignedRotations) { - return new LockedApplication(lock, id, createdAt, deploymentSpec, validationOverrides, deployments, - deploymentJobs, change, outstandingChange, ownershipIssueId, owner, majorVersion, - metrics, pemDeployKey, assignedRotations, rotationStatus); - } - - public LockedApplication with(RotationStatus rotationStatus) { - return new LockedApplication(lock, id, createdAt, deploymentSpec, validationOverrides, deployments, - deploymentJobs, change, outstandingChange, ownershipIssueId, owner, majorVersion, - metrics, pemDeployKey, rotations, rotationStatus); - } - - /** Don't expose non-leaf sub-objects. */ - private LockedApplication with(Deployment deployment) { - Map<ZoneId, Deployment> deployments = new LinkedHashMap<>(this.deployments); - deployments.put(deployment.zone(), deployment); - return with(deployments); - } - - private LockedApplication with(Map<ZoneId, Deployment> deployments) { - return new LockedApplication(lock, id, createdAt, deploymentSpec, validationOverrides, deployments, - deploymentJobs, change, outstandingChange, ownershipIssueId, owner, majorVersion, - metrics, pemDeployKey, rotations, rotationStatus); - } - - @Override - public String toString() { - return "application '" + id + "'"; - } - -} diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/LockedInstance.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/LockedInstance.java new file mode 100644 index 00000000000..26eacbbf4f4 --- /dev/null +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/LockedInstance.java @@ -0,0 +1,288 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.controller; + +import com.yahoo.component.Version; +import com.yahoo.config.application.api.DeploymentSpec; +import com.yahoo.config.application.api.ValidationOverrides; +import com.yahoo.config.provision.ApplicationId; +import com.yahoo.config.provision.ClusterSpec; +import com.yahoo.config.provision.zone.ZoneId; +import com.yahoo.vespa.curator.Lock; +import com.yahoo.vespa.hosted.controller.api.integration.deployment.ApplicationVersion; +import com.yahoo.vespa.hosted.controller.api.integration.deployment.JobType; +import com.yahoo.vespa.hosted.controller.api.integration.organization.IssueId; +import com.yahoo.vespa.hosted.controller.api.integration.organization.User; +import com.yahoo.vespa.hosted.controller.application.AssignedRotation; +import com.yahoo.vespa.hosted.controller.application.Change; +import com.yahoo.vespa.hosted.controller.application.ClusterInfo; +import com.yahoo.vespa.hosted.controller.application.ClusterUtilization; +import com.yahoo.vespa.hosted.controller.application.Deployment; +import com.yahoo.vespa.hosted.controller.application.DeploymentJobs; +import com.yahoo.vespa.hosted.controller.application.DeploymentMetrics; +import com.yahoo.vespa.hosted.controller.application.JobStatus; +import com.yahoo.vespa.hosted.controller.metric.ApplicationMetrics; +import com.yahoo.vespa.hosted.controller.rotation.RotationStatus; + +import java.time.Instant; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.OptionalInt; +import java.util.OptionalLong; + +/** + * An application that has been locked for modification. Provides methods for modifying an application's fields. + * + * @author mpolden + * @author jonmv + */ +public class LockedInstance { + + private final Lock lock; + private final ApplicationId id; + private final Instant createdAt; + private final DeploymentSpec deploymentSpec; + private final ValidationOverrides validationOverrides; + private final Map<ZoneId, Deployment> deployments; + private final DeploymentJobs deploymentJobs; + private final Change change; + private final Change outstandingChange; + private final Optional<IssueId> ownershipIssueId; + private final Optional<User> owner; + private final OptionalInt majorVersion; + private final ApplicationMetrics metrics; + private final Optional<String> pemDeployKey; + private final List<AssignedRotation> rotations; + private final RotationStatus rotationStatus; + + /** + * Used to create a locked application + * + * @param instance The application to lock. + * @param lock The lock for the application. + */ + LockedInstance(Instance instance, Lock lock) { + this(Objects.requireNonNull(lock, "lock cannot be null"), instance.id(), instance.createdAt(), + instance.deploymentSpec(), instance.validationOverrides(), + instance.deployments(), + instance.deploymentJobs(), instance.change(), instance.outstandingChange(), + instance.ownershipIssueId(), instance.owner(), instance.majorVersion(), instance.metrics(), + instance.pemDeployKey(), instance.rotations(), instance.rotationStatus()); + } + + private LockedInstance(Lock lock, ApplicationId id, Instant createdAt, + DeploymentSpec deploymentSpec, ValidationOverrides validationOverrides, + Map<ZoneId, Deployment> deployments, DeploymentJobs deploymentJobs, Change change, + Change outstandingChange, Optional<IssueId> ownershipIssueId, Optional<User> owner, + OptionalInt majorVersion, ApplicationMetrics metrics, Optional<String> pemDeployKey, + List<AssignedRotation> rotations, RotationStatus rotationStatus) { + this.lock = lock; + this.id = id; + this.createdAt = createdAt; + this.deploymentSpec = deploymentSpec; + this.validationOverrides = validationOverrides; + this.deployments = deployments; + this.deploymentJobs = deploymentJobs; + this.change = change; + this.outstandingChange = outstandingChange; + this.ownershipIssueId = ownershipIssueId; + this.owner = owner; + this.majorVersion = majorVersion; + this.metrics = metrics; + this.pemDeployKey = pemDeployKey; + this.rotations = rotations; + this.rotationStatus = rotationStatus; + } + + /** Returns a read-only copy of this */ + public Instance get() { + return new Instance(id, createdAt, deploymentSpec, validationOverrides, deployments, deploymentJobs, change, + outstandingChange, ownershipIssueId, owner, majorVersion, metrics, pemDeployKey, + rotations, rotationStatus); + } + + public LockedInstance withBuiltInternally(boolean builtInternally) { + return new LockedInstance(lock, id, createdAt, deploymentSpec, validationOverrides, deployments, + deploymentJobs.withBuiltInternally(builtInternally), change, outstandingChange, + ownershipIssueId, owner, majorVersion, metrics, pemDeployKey, + rotations, rotationStatus); + } + + public LockedInstance withProjectId(OptionalLong projectId) { + return new LockedInstance(lock, id, createdAt, deploymentSpec, validationOverrides, deployments, + deploymentJobs.withProjectId(projectId), change, outstandingChange, + ownershipIssueId, owner, majorVersion, metrics, pemDeployKey, + rotations, rotationStatus); + } + + public LockedInstance withDeploymentIssueId(IssueId issueId) { + return new LockedInstance(lock, id, createdAt, deploymentSpec, validationOverrides, deployments, + deploymentJobs.with(issueId), change, outstandingChange, + ownershipIssueId, owner, majorVersion, metrics, pemDeployKey, + rotations, rotationStatus); + } + + public LockedInstance withJobPause(JobType jobType, OptionalLong pausedUntil) { + return new LockedInstance(lock, id, createdAt, deploymentSpec, validationOverrides, deployments, + deploymentJobs.withPause(jobType, pausedUntil), change, outstandingChange, + ownershipIssueId, owner, majorVersion, metrics, pemDeployKey, + rotations, rotationStatus); + } + + public LockedInstance withJobCompletion(long projectId, JobType jobType, JobStatus.JobRun completion, + Optional<DeploymentJobs.JobError> jobError) { + return new LockedInstance(lock, id, createdAt, deploymentSpec, validationOverrides, deployments, + deploymentJobs.withCompletion(projectId, jobType, completion, jobError), + change, outstandingChange, ownershipIssueId, owner, majorVersion, metrics, + pemDeployKey, rotations, rotationStatus); + } + + public LockedInstance withJobTriggering(JobType jobType, JobStatus.JobRun job) { + return new LockedInstance(lock, id, createdAt, deploymentSpec, validationOverrides, deployments, + deploymentJobs.withTriggering(jobType, job), change, outstandingChange, + ownershipIssueId, owner, majorVersion, metrics, pemDeployKey, + rotations, rotationStatus); + } + + public LockedInstance withNewDeployment(ZoneId zone, ApplicationVersion applicationVersion, Version version, + Instant instant, Map<DeploymentMetrics.Warning, Integer> warnings) { + // Use info from previous deployment if available, otherwise create a new one. + Deployment previousDeployment = deployments.getOrDefault(zone, new Deployment(zone, applicationVersion, + version, instant)); + Deployment newDeployment = new Deployment(zone, applicationVersion, version, instant, + previousDeployment.clusterUtils(), + previousDeployment.clusterInfo(), + previousDeployment.metrics().with(warnings), + previousDeployment.activity()); + return with(newDeployment); + } + + public LockedInstance withClusterUtilization(ZoneId zone, Map<ClusterSpec.Id, ClusterUtilization> clusterUtilization) { + Deployment deployment = deployments.get(zone); + if (deployment == null) return this; // No longer deployed in this zone. + return with(deployment.withClusterUtils(clusterUtilization)); + } + + public LockedInstance withClusterInfo(ZoneId zone, Map<ClusterSpec.Id, ClusterInfo> clusterInfo) { + Deployment deployment = deployments.get(zone); + if (deployment == null) return this; // No longer deployed in this zone. + return with(deployment.withClusterInfo(clusterInfo)); + + } + + public LockedInstance recordActivityAt(Instant instant, ZoneId zone) { + Deployment deployment = deployments.get(zone); + if (deployment == null) return this; + return with(deployment.recordActivityAt(instant)); + } + + public LockedInstance with(ZoneId zone, DeploymentMetrics deploymentMetrics) { + Deployment deployment = deployments.get(zone); + if (deployment == null) return this; // No longer deployed in this zone. + return with(deployment.withMetrics(deploymentMetrics)); + } + + public LockedInstance withoutDeploymentIn(ZoneId zone) { + Map<ZoneId, Deployment> deployments = new LinkedHashMap<>(this.deployments); + deployments.remove(zone); + return with(deployments); + } + + public LockedInstance withoutDeploymentJob(JobType jobType) { + return new LockedInstance(lock, id, createdAt, deploymentSpec, validationOverrides, deployments, + deploymentJobs.without(jobType), change, outstandingChange, + ownershipIssueId, owner, majorVersion, metrics, pemDeployKey, + rotations, rotationStatus); + } + + public LockedInstance with(DeploymentSpec deploymentSpec) { + return new LockedInstance(lock, id, createdAt, deploymentSpec, validationOverrides, deployments, + deploymentJobs, change, outstandingChange, + ownershipIssueId, owner, majorVersion, metrics, pemDeployKey, + rotations, rotationStatus); + } + + public LockedInstance with(ValidationOverrides validationOverrides) { + return new LockedInstance(lock, id, createdAt, deploymentSpec, validationOverrides, deployments, + deploymentJobs, change, outstandingChange, ownershipIssueId, owner, majorVersion, + metrics, pemDeployKey, rotations, rotationStatus); + } + + public LockedInstance withChange(Change change) { + return new LockedInstance(lock, id, createdAt, deploymentSpec, validationOverrides, deployments, + deploymentJobs, change, outstandingChange, ownershipIssueId, owner, majorVersion, + metrics, pemDeployKey, rotations, rotationStatus); + } + + public LockedInstance withOutstandingChange(Change outstandingChange) { + return new LockedInstance(lock, id, createdAt, deploymentSpec, validationOverrides, deployments, + deploymentJobs, change, outstandingChange, ownershipIssueId, owner, majorVersion, + metrics, pemDeployKey, rotations, rotationStatus); + } + + public LockedInstance withOwnershipIssueId(IssueId issueId) { + return new LockedInstance(lock, id, createdAt, deploymentSpec, validationOverrides, deployments, + deploymentJobs, change, outstandingChange, Optional.ofNullable(issueId), owner, + majorVersion, metrics, pemDeployKey, rotations, rotationStatus); + } + + public LockedInstance withOwner(User owner) { + return new LockedInstance(lock, id, createdAt, deploymentSpec, validationOverrides, deployments, + deploymentJobs, change, outstandingChange, ownershipIssueId, + Optional.ofNullable(owner), majorVersion, metrics, pemDeployKey, + rotations, rotationStatus); + } + + /** Set a major version for this, or set to null to remove any major version override */ + public LockedInstance withMajorVersion(Integer majorVersion) { + return new LockedInstance(lock, id, createdAt, deploymentSpec, validationOverrides, deployments, + deploymentJobs, change, outstandingChange, ownershipIssueId, owner, + majorVersion == null ? OptionalInt.empty() : OptionalInt.of(majorVersion), + metrics, pemDeployKey, rotations, rotationStatus); + } + + public LockedInstance with(ApplicationMetrics metrics) { + return new LockedInstance(lock, id, createdAt, deploymentSpec, validationOverrides, deployments, + deploymentJobs, change, outstandingChange, ownershipIssueId, owner, majorVersion, + metrics, pemDeployKey, rotations, rotationStatus); + } + + public LockedInstance withPemDeployKey(String pemDeployKey) { + return new LockedInstance(lock, id, createdAt, deploymentSpec, validationOverrides, deployments, + deploymentJobs, change, outstandingChange, ownershipIssueId, owner, majorVersion, + metrics, Optional.ofNullable(pemDeployKey), rotations, rotationStatus); + } + + public LockedInstance with(List<AssignedRotation> assignedRotations) { + return new LockedInstance(lock, id, createdAt, deploymentSpec, validationOverrides, deployments, + deploymentJobs, change, outstandingChange, ownershipIssueId, owner, majorVersion, + metrics, pemDeployKey, assignedRotations, rotationStatus); + } + + public LockedInstance with(RotationStatus rotationStatus) { + return new LockedInstance(lock, id, createdAt, deploymentSpec, validationOverrides, deployments, + deploymentJobs, change, outstandingChange, ownershipIssueId, owner, majorVersion, + metrics, pemDeployKey, rotations, rotationStatus); + } + + /** Don't expose non-leaf sub-objects. */ + private LockedInstance with(Deployment deployment) { + Map<ZoneId, Deployment> deployments = new LinkedHashMap<>(this.deployments); + deployments.put(deployment.zone(), deployment); + return with(deployments); + } + + private LockedInstance with(Map<ZoneId, Deployment> deployments) { + return new LockedInstance(lock, id, createdAt, deploymentSpec, validationOverrides, deployments, + deploymentJobs, change, outstandingChange, ownershipIssueId, owner, majorVersion, + metrics, pemDeployKey, rotations, rotationStatus); + } + + @Override + public String toString() { + return "application '" + id + "'"; + } + +} diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ApplicationList.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/InstanceList.java index b58476acd41..809e0a8f0fb 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ApplicationList.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/InstanceList.java @@ -22,21 +22,21 @@ import java.util.stream.Stream; * @author bratseth */ // TODO jvenstad: Make an AbstractFilteringList based on JobList and let this extend it for free not()s? -public class ApplicationList { +public class InstanceList { private final ImmutableList<Instance> list; - private ApplicationList(Iterable<Instance> applications) { + private InstanceList(Iterable<Instance> applications) { this.list = ImmutableList.copyOf(applications); } // ----------------------------------- Factories - public static ApplicationList from(Iterable<Instance> applications) { - return new ApplicationList(applications); + public static InstanceList from(Iterable<Instance> applications) { + return new InstanceList(applications); } - public static ApplicationList from(Collection<ApplicationId> ids, ApplicationController applications) { + public static InstanceList from(Collection<ApplicationId> ids, ApplicationController applications) { return listOf(ids.stream().map(applications::require)); } @@ -55,27 +55,27 @@ public class ApplicationList { // ----------------------------------- Filters /** Returns the subset of applications which are upgrading (to any version), not considering block windows. */ - public ApplicationList upgrading() { + public InstanceList upgrading() { return listOf(list.stream().filter(application -> application.change().platform().isPresent())); } /** Returns the subset of applications which are currently upgrading to the given version */ - public ApplicationList upgradingTo(Version version) { + public InstanceList upgradingTo(Version version) { return listOf(list.stream().filter(application -> isUpgradingTo(version, application))); } /** Returns the subset of applications which are not pinned to a certain Vespa version. */ - public ApplicationList unpinned() { + public InstanceList unpinned() { return listOf(list.stream().filter(application -> ! application.change().isPinned())); } /** Returns the subset of applications which are currently not upgrading to the given version */ - public ApplicationList notUpgradingTo(Version version) { + public InstanceList notUpgradingTo(Version version) { return notUpgradingTo(Collections.singletonList(version)); } /** Returns the subset of applications which are currently not upgrading to any of the given versions */ - public ApplicationList notUpgradingTo(Collection<Version> versions) { + public InstanceList notUpgradingTo(Collection<Version> versions) { return listOf(list.stream().filter(application -> versions.stream().noneMatch(version -> isUpgradingTo(version, application)))); } @@ -83,90 +83,90 @@ public class ApplicationList { * Returns the subset of applications which are currently not upgrading to the given version, * or returns all if no version is specified */ - public ApplicationList notUpgradingTo(Optional<Version> version) { + public InstanceList notUpgradingTo(Optional<Version> version) { if (version.isEmpty()) return this; return notUpgradingTo(version.get()); } /** Returns the subset of applications which have changes left to deploy; blocked, or deploying */ - public ApplicationList withChanges() { + public InstanceList withChanges() { return listOf(list.stream().filter(application -> application.change().hasTargets() || application.outstandingChange().hasTargets())); } /** Returns the subset of applications which are currently not deploying a change */ - public ApplicationList notDeploying() { + public InstanceList notDeploying() { return listOf(list.stream().filter(application -> ! application.change().hasTargets())); } /** Returns the subset of applications which currently does not have any failing jobs */ - public ApplicationList notFailing() { + public InstanceList notFailing() { return listOf(list.stream().filter(application -> ! application.deploymentJobs().hasFailures())); } /** Returns the subset of applications which currently have failing jobs */ - public ApplicationList failing() { + public InstanceList failing() { return listOf(list.stream().filter(application -> application.deploymentJobs().hasFailures())); } /** Returns the subset of applications which have been failing an upgrade to the given version since the given instant */ - public ApplicationList failingUpgradeToVersionSince(Version version, Instant threshold) { + public InstanceList failingUpgradeToVersionSince(Version version, Instant threshold) { return listOf(list.stream().filter(application -> failingUpgradeToVersionSince(application, version, threshold))); } /** Returns the subset of applications which have been failing an application change since the given instant */ - public ApplicationList failingApplicationChangeSince(Instant threshold) { + public InstanceList failingApplicationChangeSince(Instant threshold) { return listOf(list.stream().filter(application -> failingApplicationChangeSince(application, threshold))); } /** Returns the subset of applications which currently does not have any failing jobs on the given version */ - public ApplicationList notFailingOn(Version version) { + public InstanceList notFailingOn(Version version) { return listOf(list.stream().filter(application -> ! failingOn(version, application))); } /** Returns the subset of applications which have at least one production deployment */ - public ApplicationList hasDeployment() { + public InstanceList hasDeployment() { return listOf(list.stream().filter(a -> !a.productionDeployments().isEmpty())); } /** Returns the subset of applications which started failing on the given version */ - public ApplicationList startedFailingOn(Version version) { + public InstanceList startedFailingOn(Version version) { return listOf(list.stream().filter(application -> ! JobList.from(application).firstFailing().on(version).isEmpty())); } /** Returns the subset of applications which has the given upgrade policy */ - public ApplicationList with(UpgradePolicy policy) { + public InstanceList with(UpgradePolicy policy) { return listOf(list.stream().filter(a -> a.deploymentSpec().upgradePolicy() == policy)); } /** Returns the subset of applications which does not have the given upgrade policy */ - public ApplicationList without(UpgradePolicy policy) { + public InstanceList without(UpgradePolicy policy) { return listOf(list.stream().filter(a -> a.deploymentSpec().upgradePolicy() != policy)); } /** Returns the subset of applications which have at least one deployment on a lower version than the given one */ - public ApplicationList onLowerVersionThan(Version version) { + public InstanceList onLowerVersionThan(Version version) { return listOf(list.stream() .filter(a -> a.productionDeployments().values().stream() .anyMatch(d -> d.version().isBefore(version)))); } /** Returns the subset of applications which have a project ID */ - public ApplicationList withProjectId() { + public InstanceList withProjectId() { return listOf(list.stream().filter(a -> a.deploymentJobs().projectId().isPresent())); } /** Returns the subset of applications which have at least one production deployment */ - public ApplicationList hasProductionDeployment() { + public InstanceList hasProductionDeployment() { return listOf(list.stream().filter(a -> ! a.productionDeployments().isEmpty())); } /** Returns the subset of applications that are allowed to upgrade at the given time */ - public ApplicationList canUpgradeAt(Instant instant) { + public InstanceList canUpgradeAt(Instant instant) { return listOf(list.stream().filter(a -> a.deploymentSpec().canUpgradeAt(instant))); } /** Returns the subset of applications that have at least one assigned rotation */ - public ApplicationList hasRotation() { + public InstanceList hasRotation() { return listOf(list.stream().filter(a -> !a.rotations().isEmpty())); } @@ -176,15 +176,15 @@ public class ApplicationList { * @param targetMajorVersion the target major version which applications returned allows upgrading to * @param defaultMajorVersion the default major version to assume for applications not specifying one */ - public ApplicationList allowMajorVersion(int targetMajorVersion, int defaultMajorVersion) { + public InstanceList allowMajorVersion(int targetMajorVersion, int defaultMajorVersion) { return listOf(list.stream().filter(a -> a.deploymentSpec().majorVersion().orElse(a.majorVersion().orElse(defaultMajorVersion)) >= targetMajorVersion)); } /** Returns the first n application in this (or all, if there are less than n). */ - public ApplicationList first(int n) { + public InstanceList first(int n) { if (list.size() < n) return this; - return new ApplicationList(list.subList(0, n)); + return new InstanceList(list.subList(0, n)); } // ----------------------------------- Sorting @@ -194,7 +194,7 @@ public class ApplicationList { * If multiple versions are deployed the oldest is used. * Applications without any deployments are ordered first. */ - public ApplicationList byIncreasingDeployedVersion() { + public InstanceList byIncreasingDeployedVersion() { return listOf(list.stream().sorted(Comparator.comparing(application -> application.oldestDeployedPlatform().orElse(Version.emptyVersion)))); } @@ -227,7 +227,7 @@ public class ApplicationList { } /** Convenience converter from a stream to an ApplicationList */ - private static ApplicationList listOf(Stream<Instance> applications) { + private static InstanceList listOf(Stream<Instance> applications) { return from(applications::iterator); } 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 05f9eb7a501..7ccb4163284 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 @@ -14,7 +14,7 @@ import com.yahoo.vespa.hosted.controller.api.integration.BuildService.JobState; import com.yahoo.vespa.hosted.controller.api.integration.deployment.ApplicationVersion; import com.yahoo.vespa.hosted.controller.api.integration.deployment.JobType; import com.yahoo.config.provision.zone.ZoneId; -import com.yahoo.vespa.hosted.controller.application.ApplicationList; +import com.yahoo.vespa.hosted.controller.application.InstanceList; import com.yahoo.vespa.hosted.controller.application.Change; import com.yahoo.vespa.hosted.controller.application.Deployment; import com.yahoo.vespa.hosted.controller.application.DeploymentJobs.JobReport; @@ -294,13 +294,13 @@ public class DeploymentTrigger { /** Returns the set of all jobs which have changes to propagate from the upstream steps. */ private List<Job> computeReadyJobs() { - return ApplicationList.from(applications().asList()) - .withProjectId() - .withChanges() - .idList().stream() - .map(this::computeReadyJobs) - .flatMap(Collection::stream) - .collect(toList()); + return InstanceList.from(applications().asList()) + .withProjectId() + .withChanges() + .idList().stream() + .map(this::computeReadyJobs) + .flatMap(Collection::stream) + .collect(toList()); } /** 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 031c88e55af..6d535254970 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 @@ -12,7 +12,7 @@ import com.yahoo.vespa.flags.FlagSource; import com.yahoo.vespa.flags.Flags; import com.yahoo.vespa.hosted.controller.Instance; import com.yahoo.vespa.hosted.controller.Controller; -import com.yahoo.vespa.hosted.controller.LockedApplication; +import com.yahoo.vespa.hosted.controller.LockedInstance; import com.yahoo.vespa.hosted.controller.api.identifiers.DeploymentId; import com.yahoo.vespa.hosted.controller.api.integration.LogEntry; import com.yahoo.vespa.hosted.controller.api.integration.configserver.NotFoundException; @@ -309,7 +309,7 @@ public class JobController { } /** Registers the given application, copying necessary application packages, and returns the modified version. */ - private LockedApplication registered(LockedApplication application) { + private LockedInstance registered(LockedInstance application) { // TODO jvenstad: Remove when there are no more SDv3 pipelines. // Copy all current packages to the new application store application.get().productionDeployments().values().stream() diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ApplicationOwnershipConfirmer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ApplicationOwnershipConfirmer.java index 3a3666beb27..d94004eda2b 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ApplicationOwnershipConfirmer.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ApplicationOwnershipConfirmer.java @@ -10,7 +10,7 @@ import com.yahoo.vespa.hosted.controller.api.integration.organization.Applicatio import com.yahoo.vespa.hosted.controller.api.integration.organization.IssueId; import com.yahoo.vespa.hosted.controller.api.integration.organization.OwnershipIssues; import com.yahoo.vespa.hosted.controller.api.integration.organization.User; -import com.yahoo.vespa.hosted.controller.application.ApplicationList; +import com.yahoo.vespa.hosted.controller.application.InstanceList; import com.yahoo.vespa.hosted.controller.tenant.Tenant; import com.yahoo.vespa.hosted.controller.tenant.UserTenant; import com.yahoo.yolean.Exceptions; @@ -47,13 +47,13 @@ public class ApplicationOwnershipConfirmer extends Maintainer { /** File an ownership issue with the owners of all applications we know about. */ private void confirmApplicationOwnerships() { - ApplicationList.from(controller().applications().asList()) - .withProjectId() - .hasProductionDeployment() - .asList() - .stream() - .filter(application -> application.createdAt().isBefore(controller().clock().instant().minus(Duration.ofDays(90)))) - .forEach(application -> { + InstanceList.from(controller().applications().asList()) + .withProjectId() + .hasProductionDeployment() + .asList() + .stream() + .filter(application -> application.createdAt().isBefore(controller().clock().instant().minus(Duration.ofDays(90)))) + .forEach(application -> { try { Tenant tenant = tenantOf(application.id()); tenant.contact().ifPresent(contact -> { // TODO jvenstad: Makes sense to require, and run this only in main? @@ -99,13 +99,13 @@ public class ApplicationOwnershipConfirmer extends Maintainer { } private void updateConfirmedApplicationOwners() { - ApplicationList.from(controller().applications().asList()) - .withProjectId() - .hasProductionDeployment() - .asList() - .stream() - .filter(application -> application.ownershipIssueId().isPresent()) - .forEach(application -> { + InstanceList.from(controller().applications().asList()) + .withProjectId() + .hasProductionDeployment() + .asList() + .stream() + .filter(application -> application.ownershipIssueId().isPresent()) + .forEach(application -> { IssueId ownershipIssueId = application.ownershipIssueId().get(); ownershipIssues.getConfirmedOwner(ownershipIssueId).ifPresent(owner -> { controller().applications().lockIfPresent(application.id(), lockedApplication -> diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentIssueReporter.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentIssueReporter.java index 455064550aa..11c210adc48 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentIssueReporter.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentIssueReporter.java @@ -9,7 +9,7 @@ import com.yahoo.vespa.hosted.controller.Controller; import com.yahoo.vespa.hosted.controller.api.integration.organization.DeploymentIssues; import com.yahoo.vespa.hosted.controller.api.integration.organization.IssueId; import com.yahoo.vespa.hosted.controller.api.integration.organization.User; -import com.yahoo.vespa.hosted.controller.application.ApplicationList; +import com.yahoo.vespa.hosted.controller.application.InstanceList; import com.yahoo.vespa.hosted.controller.tenant.Tenant; import com.yahoo.yolean.Exceptions; @@ -51,9 +51,9 @@ public class DeploymentIssueReporter extends Maintainer { /** Returns the applications to maintain issue status for. */ private List<Instance> applications() { - return ApplicationList.from(controller().applications().asList()) - .withProjectId() - .asList(); + return InstanceList.from(controller().applications().asList()) + .withProjectId() + .asList(); } /** @@ -62,11 +62,11 @@ public class DeploymentIssueReporter extends Maintainer { * where deployment has not failed for this amount of time. */ private void maintainDeploymentIssues(List<Instance> instances) { - Set<ApplicationId> failingApplications = ApplicationList.from(instances) - .failingApplicationChangeSince(controller().clock().instant().minus(maxFailureAge)) - .asList().stream() - .map(Instance::id) - .collect(Collectors.toSet()); + Set<ApplicationId> failingApplications = InstanceList.from(instances) + .failingApplicationChangeSince(controller().clock().instant().minus(maxFailureAge)) + .asList().stream() + .map(Instance::id) + .collect(Collectors.toSet()); for (Instance instance : instances) if (failingApplications.contains(instance.id())) @@ -89,14 +89,14 @@ public class DeploymentIssueReporter extends Maintainer { if ((controller().versionStatus().version(systemVersion).confidence() != broken)) return; - if (ApplicationList.from(instances) - .failingUpgradeToVersionSince(systemVersion, controller().clock().instant().minus(upgradeGracePeriod)) - .isEmpty()) + if (InstanceList.from(instances) + .failingUpgradeToVersionSince(systemVersion, controller().clock().instant().minus(upgradeGracePeriod)) + .isEmpty()) return; - List<ApplicationId> failingApplications = ApplicationList.from(instances) - .failingUpgradeToVersionSince(systemVersion, controller().clock().instant()) - .idList(); + List<ApplicationId> failingApplications = InstanceList.from(instances) + .failingUpgradeToVersionSince(systemVersion, controller().clock().instant()) + .idList(); deploymentIssues.fileUnlessOpen(failingApplications, systemVersion); } diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/MetricsReporter.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/MetricsReporter.java index b062c23d98a..ba3b2118e9f 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/MetricsReporter.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/MetricsReporter.java @@ -7,7 +7,7 @@ import com.yahoo.jdisc.Metric; import com.yahoo.vespa.hosted.controller.Instance; import com.yahoo.vespa.hosted.controller.Controller; import com.yahoo.vespa.hosted.controller.api.integration.deployment.JobType; -import com.yahoo.vespa.hosted.controller.application.ApplicationList; +import com.yahoo.vespa.hosted.controller.application.InstanceList; import com.yahoo.vespa.hosted.controller.application.Deployment; import com.yahoo.vespa.hosted.controller.application.DeploymentMetrics; import com.yahoo.vespa.hosted.controller.application.JobList; @@ -61,8 +61,8 @@ public class MetricsReporter extends Maintainer { } private void reportDeploymentMetrics() { - ApplicationList applications = ApplicationList.from(controller().applications().asList()) - .hasProductionDeployment(); + InstanceList applications = InstanceList.from(controller().applications().asList()) + .hasProductionDeployment(); metric.set(DEPLOYMENT_FAIL_METRIC, deploymentFailRatio(applications) * 100, metric.createContext(Collections.emptyMap())); @@ -92,21 +92,21 @@ public class MetricsReporter extends Maintainer { metric.createContext(Map.of())); } - private static double deploymentFailRatio(ApplicationList applicationList) { - List<Instance> instances = applicationList.asList(); + private static double deploymentFailRatio(InstanceList instanceList) { + List<Instance> instances = instanceList.asList(); if (instances.isEmpty()) return 0; return (double) instances.stream().filter(a -> a.deploymentJobs().hasFailures()).count() / (double) instances.size(); } - private static Map<ApplicationId, Duration> averageDeploymentDurations(ApplicationList applications, Instant now) { + private static Map<ApplicationId, Duration> averageDeploymentDurations(InstanceList applications, Instant now) { return applications.asList().stream() .collect(Collectors.toMap(Instance::id, application -> averageDeploymentDuration(application, now))); } - private static Map<ApplicationId, Integer> deploymentsFailingUpgrade(ApplicationList applications) { + private static Map<ApplicationId, Integer> deploymentsFailingUpgrade(InstanceList applications) { return applications.asList() .stream() .collect(Collectors.toMap(Instance::id, MetricsReporter::deploymentsFailingUpgrade)); @@ -134,7 +134,7 @@ public class MetricsReporter extends Maintainer { .orElse(Duration.ZERO); } - private static Map<ApplicationId, Integer> deploymentWarnings(ApplicationList applications) { + private static Map<ApplicationId, Integer> deploymentWarnings(InstanceList applications) { return applications.asList().stream() .collect(Collectors.toMap(Instance::id, a -> maxWarningCountOf(a.deployments().values()))); } diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/RotationStatusUpdater.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/RotationStatusUpdater.java index 0e7086809d3..6c7d4cab908 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/RotationStatusUpdater.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/RotationStatusUpdater.java @@ -7,7 +7,7 @@ import com.yahoo.vespa.hosted.controller.Instance; import com.yahoo.vespa.hosted.controller.ApplicationController; import com.yahoo.vespa.hosted.controller.Controller; import com.yahoo.vespa.hosted.controller.api.integration.routing.GlobalRoutingService; -import com.yahoo.vespa.hosted.controller.application.ApplicationList; +import com.yahoo.vespa.hosted.controller.application.InstanceList; import com.yahoo.vespa.hosted.controller.rotation.RotationId; import com.yahoo.vespa.hosted.controller.rotation.RotationState; import com.yahoo.vespa.hosted.controller.rotation.RotationStatus; @@ -43,7 +43,7 @@ public class RotationStatusUpdater extends Maintainer { protected void maintain() { var failures = new AtomicInteger(0); var lastException = new AtomicReference<Exception>(null); - var applicationList = ApplicationList.from(applications.asList()).hasRotation(); + var applicationList = InstanceList.from(applications.asList()).hasRotation(); // Run parallel stream inside a custom ForkJoinPool so that we can control the number of threads used var pool = new ForkJoinPool(applicationsToUpdateInParallel); diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/Upgrader.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/Upgrader.java index 10decd226cb..c4ca94e169d 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/Upgrader.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/Upgrader.java @@ -6,7 +6,7 @@ import com.yahoo.config.application.api.DeploymentSpec.UpgradePolicy; import com.yahoo.vespa.curator.Lock; import com.yahoo.vespa.hosted.controller.Instance; import com.yahoo.vespa.hosted.controller.Controller; -import com.yahoo.vespa.hosted.controller.application.ApplicationList; +import com.yahoo.vespa.hosted.controller.application.InstanceList; import com.yahoo.vespa.hosted.controller.application.Change; import com.yahoo.vespa.hosted.controller.persistence.CuratorDb; import com.yahoo.vespa.hosted.controller.versions.VespaVersion; @@ -70,7 +70,7 @@ public class Upgrader extends Maintainer { cancelUpgradesOf(applications().with(UpgradePolicy.conservative).upgrading().failing().notUpgradingTo(conservativeTargets), reason); // Schedule the right upgrades - ApplicationList applications = applications(); + InstanceList applications = applications(); canaryTarget.ifPresent(target -> upgrade(applications.with(UpgradePolicy.canary), target)); defaultTargets.forEach(target -> upgrade(applications.with(UpgradePolicy.defaultPolicy), target)); conservativeTargets.forEach(target -> upgrade(applications.with(UpgradePolicy.conservative), target)); @@ -90,11 +90,11 @@ public class Upgrader extends Maintainer { } /** Returns a list of all applications, except those which are pinned — these should not be manipulated by the Upgrader */ - private ApplicationList applications() { - return ApplicationList.from(controller().applications().asList()).unpinned(); + private InstanceList applications() { + return InstanceList.from(controller().applications().asList()).unpinned(); } - private void upgrade(ApplicationList applications, Version version) { + private void upgrade(InstanceList applications, Version version) { applications = applications.hasProductionDeployment(); applications = applications.onLowerVersionThan(version); applications = applications.allowMajorVersion(version.getMajor(), targetMajorVersion().orElse(version.getMajor())); @@ -107,7 +107,7 @@ public class Upgrader extends Maintainer { controller().applications().deploymentTrigger().triggerChange(instance.id(), Change.of(version)); } - private void cancelUpgradesOf(ApplicationList applications, String reason) { + private void cancelUpgradesOf(InstanceList applications, String reason) { if (applications.isEmpty()) return; log.info("Cancelling upgrading of " + applications.asList().size() + " applications: " + reason); for (Instance instance : applications.asList()) diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/CuratorDb.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/CuratorDb.java index 6822d441cdf..07deaf336ff 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/CuratorDb.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/CuratorDb.java @@ -83,7 +83,7 @@ public class CuratorDb { private final ControllerVersionSerializer controllerVersionSerializer = new ControllerVersionSerializer(); private final ConfidenceOverrideSerializer confidenceOverrideSerializer = new ConfidenceOverrideSerializer(); private final TenantSerializer tenantSerializer = new TenantSerializer(); - private final ApplicationSerializer applicationSerializer = new ApplicationSerializer(); + private final InstanceSerializer instanceSerializer = new InstanceSerializer(); private final RunSerializer runSerializer = new RunSerializer(); private final OsVersionSerializer osVersionSerializer = new OsVersionSerializer(); private final OsVersionStatusSerializer osVersionStatusSerializer = new OsVersionStatusSerializer(osVersionSerializer); @@ -332,11 +332,11 @@ public class CuratorDb { // -------------- Application --------------------------------------------- public void writeApplication(Instance instance) { - curator.set(applicationPath(instance.id()), asJson(applicationSerializer.toSlime(instance))); + curator.set(applicationPath(instance.id()), asJson(instanceSerializer.toSlime(instance))); } public Optional<Instance> readApplication(ApplicationId application) { - return readSlime(applicationPath(application)).map(applicationSerializer::fromSlime); + return readSlime(applicationPath(application)).map(instanceSerializer::fromSlime); } public List<Instance> readApplications() { diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/ApplicationSerializer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/InstanceSerializer.java index 24d960c3635..3cd594a277d 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/ApplicationSerializer.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/InstanceSerializer.java @@ -53,7 +53,7 @@ import java.util.stream.Collectors; * * @author bratseth */ -public class ApplicationSerializer { +public class InstanceSerializer { // WARNING: Since there are multiple servers in a ZooKeeper cluster and they upgrade one by one // (and rewrite all nodes on startup), changes to the serialized format must be made diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/versions/VersionStatus.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/versions/VersionStatus.java index 17926f18b5c..c6c66eab1b4 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/versions/VersionStatus.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/versions/VersionStatus.java @@ -11,7 +11,7 @@ import com.yahoo.log.LogLevel; import com.yahoo.vespa.hosted.controller.Instance; import com.yahoo.vespa.hosted.controller.Controller; import com.yahoo.vespa.hosted.controller.api.integration.configserver.Node; -import com.yahoo.vespa.hosted.controller.application.ApplicationList; +import com.yahoo.vespa.hosted.controller.application.InstanceList; import com.yahoo.vespa.hosted.controller.application.Deployment; import com.yahoo.vespa.hosted.controller.application.JobList; import com.yahoo.vespa.hosted.controller.application.SystemApplication; @@ -196,9 +196,9 @@ public class VersionStatus { versionMap.put(infrastructureVersion, DeploymentStatistics.empty(infrastructureVersion)); } - ApplicationList applicationList = ApplicationList.from(instances) - .hasProductionDeployment(); - for (Instance instance : applicationList.asList()) { + InstanceList instanceList = InstanceList.from(instances) + .hasProductionDeployment(); + for (Instance instance : instanceList.asList()) { // Note that each version deployed on this application in production exists // (ignore non-production versions) for (Deployment deployment : instance.productionDeployments().values()) { diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/versions/VespaVersion.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/versions/VespaVersion.java index be277bc2262..aaf216f805b 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/versions/VespaVersion.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/versions/VespaVersion.java @@ -5,7 +5,7 @@ import com.google.common.collect.ImmutableSet; import com.yahoo.component.Version; import com.yahoo.config.provision.HostName; import com.yahoo.vespa.hosted.controller.Controller; -import com.yahoo.vespa.hosted.controller.application.ApplicationList; +import com.yahoo.vespa.hosted.controller.application.InstanceList; import java.time.Instant; import java.time.ZoneOffset; @@ -49,12 +49,12 @@ public class VespaVersion implements Comparable<VespaVersion> { public static Confidence confidenceFrom(DeploymentStatistics statistics, Controller controller) { // 'production on this': All deployment jobs upgrading to this version have completed without failure - ApplicationList productionOnThis = ApplicationList.from(statistics.production(), controller.applications()) - .notUpgradingTo(statistics.version()) - .notFailing(); - ApplicationList failingOnThis = ApplicationList.from(statistics.failing(), controller.applications()); - ApplicationList all = ApplicationList.from(controller.applications().asList()) - .hasDeployment(); + InstanceList productionOnThis = InstanceList.from(statistics.production(), controller.applications()) + .notUpgradingTo(statistics.version()) + .notFailing(); + InstanceList failingOnThis = InstanceList.from(statistics.failing(), controller.applications()); + InstanceList all = InstanceList.from(controller.applications().asList()) + .hasDeployment(); // 'broken' if any Canary fails if ( ! failingOnThis.with(UpgradePolicy.canary).isEmpty()) @@ -162,10 +162,10 @@ public class VespaVersion implements Comparable<VespaVersion> { } private static boolean nonCanaryApplicationsBroken(Version version, - ApplicationList failingOnThis, - ApplicationList productionOnThis) { - ApplicationList failingNonCanaries = failingOnThis.without(UpgradePolicy.canary).startedFailingOn(version); - ApplicationList productionNonCanaries = productionOnThis.without(UpgradePolicy.canary); + InstanceList failingOnThis, + InstanceList productionOnThis) { + InstanceList failingNonCanaries = failingOnThis.without(UpgradePolicy.canary).startedFailingOn(version); + InstanceList productionNonCanaries = productionOnThis.without(UpgradePolicy.canary); if (productionNonCanaries.size() + failingNonCanaries.size() == 0) return false; diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTester.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTester.java index 52a8f5f5e27..6744bdea985 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTester.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTester.java @@ -33,7 +33,7 @@ import com.yahoo.vespa.hosted.controller.api.integration.athenz.AthenzDbMock; import com.yahoo.vespa.hosted.controller.integration.ConfigServerMock; import com.yahoo.vespa.hosted.controller.integration.ServiceRegistryMock; import com.yahoo.vespa.hosted.controller.integration.ZoneRegistryMock; -import com.yahoo.vespa.hosted.controller.persistence.ApplicationSerializer; +import com.yahoo.vespa.hosted.controller.persistence.InstanceSerializer; import com.yahoo.vespa.hosted.controller.persistence.CuratorDb; import com.yahoo.vespa.hosted.controller.persistence.MockCuratorDb; import com.yahoo.vespa.hosted.controller.security.AthenzCredentials; @@ -182,10 +182,10 @@ public final class ControllerTester { /** Create application from slime */ public Instance createApplication(Slime slime) { - ApplicationSerializer serializer = new ApplicationSerializer(); + InstanceSerializer serializer = new InstanceSerializer(); Instance instance = serializer.fromSlime(slime); try (Lock lock = controller().applications().lock(instance.id())) { - controller().applications().store(new LockedApplication(instance, lock)); + controller().applications().store(new LockedInstance(instance, lock)); } return instance; } @@ -244,8 +244,8 @@ public final class ControllerTester { public Instance createApplication(TenantName tenant, String applicationName, String instanceName, long projectId) { ApplicationId applicationId = ApplicationId.from(tenant.value(), applicationName, instanceName); controller().applications().createApplication(applicationId, credentialsFor(applicationId)); - controller().applications().lockOrThrow(applicationId, lockedApplication -> - controller().applications().store(lockedApplication.withProjectId(OptionalLong.of(projectId)))); + controller().applications().lockOrThrow(applicationId, lockedInstance -> + controller().applications().store(lockedInstance.withProjectId(OptionalLong.of(projectId)))); return controller().applications().require(applicationId); } @@ -277,8 +277,8 @@ public final class ControllerTester { } /** Used by ApplicationSerializerTest to avoid breaking encapsulation. Should not be used by anything else */ - public static LockedApplication writable(Instance instance) { - return new LockedApplication(instance, new Lock("/test", new MockCurator())); + public static LockedInstance writable(Instance instance) { + return new LockedInstance(instance, new Lock("/test", new MockCurator())); } private static Controller createController(CuratorDb curator, RotationsConfig rotationsConfig, diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/ApplicationSerializerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/InstanceSerializerTest.java index 25193688d85..8a6a6efbd5a 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/ApplicationSerializerTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/InstanceSerializerTest.java @@ -53,9 +53,9 @@ import static org.junit.Assert.assertEquals; /** * @author bratseth */ -public class ApplicationSerializerTest { +public class InstanceSerializerTest { - private static final ApplicationSerializer applicationSerializer = new ApplicationSerializer(); + private static final InstanceSerializer INSTANCE_SERIALIZER = new InstanceSerializer(); private static final Path testData = Paths.get("src/test/java/com/yahoo/vespa/hosted/controller/persistence/testdata/"); private static final ZoneId zone1 = ZoneId.from("prod", "us-west-1"); private static final ZoneId zone2 = ZoneId.from("prod", "us-east-3"); @@ -119,7 +119,7 @@ public class ApplicationSerializerTest { List.of(AssignedRotation.fromStrings("foo", "default", "my-rotation", Set.of())), rotationStatus); - Instance serialized = applicationSerializer.fromSlime(applicationSerializer.toSlime(original)); + Instance serialized = INSTANCE_SERIALIZER.fromSlime(INSTANCE_SERIALIZER.toSlime(original)); assertEquals(original.id(), serialized.id()); assertEquals(original.createdAt(), serialized.createdAt()); @@ -184,26 +184,26 @@ public class ApplicationSerializerTest { assertEquals(original.deployments().get(zone2).metrics().warnings(), serialized.deployments().get(zone2).metrics().warnings()); { // test more deployment serialization cases Instance original2 = writable(original).withChange(Change.of(ApplicationVersion.from(new SourceRevision("repo1", "branch1", "commit1"), 42))).get(); - Instance serialized2 = applicationSerializer.fromSlime(applicationSerializer.toSlime(original2)); + Instance serialized2 = INSTANCE_SERIALIZER.fromSlime(INSTANCE_SERIALIZER.toSlime(original2)); assertEquals(original2.change(), serialized2.change()); assertEquals(serialized2.change().application().get().source(), original2.change().application().get().source()); Instance original3 = writable(original).withChange(Change.of(ApplicationVersion.from(new SourceRevision("a", "b", "c"), 42))).get(); - Instance serialized3 = applicationSerializer.fromSlime(applicationSerializer.toSlime(original3)); + Instance serialized3 = INSTANCE_SERIALIZER.fromSlime(INSTANCE_SERIALIZER.toSlime(original3)); assertEquals(original3.change(), serialized3.change()); assertEquals(serialized3.change().application().get().source(), original3.change().application().get().source()); Instance original4 = writable(original).withChange(Change.empty()).get(); - Instance serialized4 = applicationSerializer.fromSlime(applicationSerializer.toSlime(original4)); + Instance serialized4 = INSTANCE_SERIALIZER.fromSlime(INSTANCE_SERIALIZER.toSlime(original4)); assertEquals(original4.change(), serialized4.change()); Instance original5 = writable(original).withChange(Change.of(ApplicationVersion.from(new SourceRevision("a", "b", "c"), 42))).get(); - Instance serialized5 = applicationSerializer.fromSlime(applicationSerializer.toSlime(original5)); + Instance serialized5 = INSTANCE_SERIALIZER.fromSlime(INSTANCE_SERIALIZER.toSlime(original5)); assertEquals(original5.change(), serialized5.change()); Instance original6 = writable(original).withOutstandingChange(Change.of(ApplicationVersion.from(new SourceRevision("a", "b", "c"), 42))).get(); - Instance serialized6 = applicationSerializer.fromSlime(applicationSerializer.toSlime(original6)); + Instance serialized6 = INSTANCE_SERIALIZER.fromSlime(INSTANCE_SERIALIZER.toSlime(original6)); assertEquals(original6.outstandingChange(), serialized6.outstandingChange()); } } @@ -241,7 +241,7 @@ public class ApplicationSerializerTest { @Test public void testCompleteApplicationDeserialization() throws Exception { byte[] applicationJson = Files.readAllBytes(testData.resolve("complete-application.json")); - applicationSerializer.fromSlime(SlimeUtils.jsonToSlime(applicationJson)); + INSTANCE_SERIALIZER.fromSlime(SlimeUtils.jsonToSlime(applicationJson)); // ok if no error } |