use of com.yahoo.component.Version in project vespa by vespa-engine.
the class VersionStatus method findConfigServerVersions.
private static ListMap<Version, String> findConfigServerVersions(Controller controller) {
List<URI> configServers = controller.zoneRegistry().zones().controllerManaged().not().among(ZoneId.from("prod.cd-us-east-1a"), ZoneId.from("prod.aws-us-east-1a")).ids().stream().flatMap(zoneId -> controller.zoneRegistry().getConfigServerUris(zoneId).stream()).collect(Collectors.toList());
ListMap<Version, String> versions = new ListMap<>();
for (URI configServer : configServers) versions.put(controller.applications().configServer().version(configServer), configServer.getHost());
return versions;
}
use of com.yahoo.component.Version in project vespa by vespa-engine.
the class VersionStatus method compute.
/**
* Compute version status using the given current version. This is useful for testing.
*/
public static VersionStatus compute(Controller controller, Version currentVersion) {
ListMap<Version, String> configServerVersions = findConfigServerVersions(controller);
Set<Version> infrastructureVersions = new HashSet<>();
infrastructureVersions.add(currentVersion);
infrastructureVersions.addAll(configServerVersions.keySet());
// The system version is the oldest infrastructure version
Version systemVersion = infrastructureVersions.stream().sorted().findFirst().get();
Collection<DeploymentStatistics> deploymentStatistics = computeDeploymentStatistics(infrastructureVersions, controller.applications().asList());
List<VespaVersion> versions = new ArrayList<>();
for (DeploymentStatistics statistics : deploymentStatistics) {
if (statistics.version().isEmpty())
continue;
try {
VespaVersion vespaVersion = createVersion(statistics, statistics.version().equals(systemVersion), configServerVersions.getList(statistics.version()), controller);
versions.add(vespaVersion);
} catch (IllegalArgumentException e) {
log.log(Level.WARNING, "Unable to create VespaVersion for version " + statistics.version().toFullString(), e);
}
}
Collections.sort(versions);
return new VersionStatus(versions);
}
use of com.yahoo.component.Version in project vespa by vespa-engine.
the class VersionStatus method computeDeploymentStatistics.
private static Collection<DeploymentStatistics> computeDeploymentStatistics(Set<Version> infrastructureVersions, List<Application> applications) {
Map<Version, DeploymentStatistics> versionMap = new HashMap<>();
for (Version infrastructureVersion : infrastructureVersions) {
versionMap.put(infrastructureVersion, DeploymentStatistics.empty(infrastructureVersion));
}
ApplicationList applicationList = ApplicationList.from(applications).notPullRequest().hasProductionDeployment();
for (Application application : applicationList.asList()) {
// (ignore non-production versions)
for (Deployment deployment : application.productionDeployments().values()) {
versionMap.computeIfAbsent(deployment.version(), DeploymentStatistics::empty);
}
// List versions which have failing jobs, versions which are in production, and versions for which there are running deployment jobs
// Failing versions
JobList.from(application).failing().not().failingApplicationChange().not().failingBecause(outOfCapacity).mapToList(job -> job.lastCompleted().get().version()).forEach(version -> versionMap.put(version, versionMap.getOrDefault(version, DeploymentStatistics.empty(version)).withFailing(application.id())));
// Succeeding versions
JobList.from(application).lastSuccess().present().production().mapToList(job -> job.lastSuccess().get().version()).forEach(version -> versionMap.put(version, versionMap.getOrDefault(version, DeploymentStatistics.empty(version)).withProduction(application.id())));
// Deploying versions
JobList.from(application).upgrading().mapToList(job -> job.lastTriggered().get().version()).forEach(version -> versionMap.put(version, versionMap.getOrDefault(version, DeploymentStatistics.empty(version)).withDeploying(application.id())));
}
return versionMap.values();
}
use of com.yahoo.component.Version in project vespa by vespa-engine.
the class DeploymentTriggerTest method testTriggerFailing.
@Test
public void testTriggerFailing() {
DeploymentTester tester = new DeploymentTester();
Application app = tester.createApplication("app1", "tenant1", 1, 1L);
ApplicationPackage applicationPackage = new ApplicationPackageBuilder().upgradePolicy("default").environment(Environment.prod).region("us-west-1").build();
Version version = new Version(5, 1);
tester.updateVersionStatus(version);
tester.upgrader().maintain();
tester.readyJobTrigger().maintain();
// Deploy completely once
tester.jobCompletion(component).application(app).uploadArtifact(applicationPackage).submit();
tester.deployAndNotify(app, applicationPackage, true, DeploymentJobs.JobType.systemTest);
tester.deployAndNotify(app, applicationPackage, true, DeploymentJobs.JobType.stagingTest);
tester.deployAndNotify(app, applicationPackage, true, JobType.productionUsWest1);
// New version is released
version = new Version(5, 2);
tester.updateVersionStatus(version);
tester.upgrader().maintain();
tester.readyJobTrigger().maintain();
// system-test fails and is retried
tester.deployAndNotify(app, applicationPackage, false, JobType.systemTest);
assertEquals("Job is retried on failure", 1, tester.deploymentQueue().jobs().size());
tester.deployAndNotify(app, applicationPackage, true, JobType.systemTest);
// staging-test times out and is retried
tester.deploymentQueue().takeJobsToRun();
tester.clock().advance(Duration.ofHours(12).plus(Duration.ofSeconds(1)));
tester.readyJobTrigger().maintain();
assertEquals("Retried dead job", 1, tester.deploymentQueue().jobs().size());
assertEquals(JobType.stagingTest.jobName(), tester.deploymentQueue().jobs().get(0).jobName());
}
use of com.yahoo.component.Version in project vespa by vespa-engine.
the class DeploymentTriggerTest method dualChangesAreNotSkippedWhenOnePartIsDeployedAlready.
@Test
public void dualChangesAreNotSkippedWhenOnePartIsDeployedAlready() {
DeploymentTester tester = new DeploymentTester();
Application application = tester.createApplication("app1", "tenant1", 1, 1L);
Supplier<Application> app = () -> tester.application(application.id());
ApplicationPackage applicationPackage = new ApplicationPackageBuilder().environment(Environment.prod).region("us-central-1").region("eu-west-1").build();
tester.deployCompletely(application, applicationPackage);
// Platform upgrade which doesn't succeed, allowing a dual change.
Version version1 = new Version("7.1");
tester.upgradeSystem(version1);
tester.completeUpgradeWithError(application, version1, applicationPackage, productionEuWest1);
// Deploy the new application version, even though the platform version is already deployed in us-central-1.
// Let it fail in us-central-1 after deployment, so we can test this zone is later skipped.
tester.jobCompletion(component).application(application).nextBuildNumber().uploadArtifact(applicationPackage).submit();
tester.deployAndNotify(application, applicationPackage, true, false, systemTest);
tester.deployAndNotify(application, applicationPackage, true, false, stagingTest);
tester.jobCompletion(productionEuWest1).application(application).unsuccessful().submit();
tester.deploy(productionUsCentral1, application, Optional.empty(), false);
// Deploying before notifying here makes the job not re-trigger, but instead triggers the next job (because of triggerReadyJobs() in notification.)
tester.deployAndNotify(application, applicationPackage, false, productionUsCentral1);
assertEquals(ApplicationVersion.from(BuildJob.defaultSourceRevision, BuildJob.defaultBuildNumber + 1), app.get().deployments().get(ZoneId.from("prod.us-central-1")).applicationVersion());
assertEquals(Collections.singletonList(new BuildService.BuildJob(1, productionEuWest1.jobName())), tester.deploymentQueue().jobs());
tester.deploy(productionEuWest1, application, Optional.empty(), false);
tester.deployAndNotify(application, Optional.empty(), false, true, productionEuWest1);
assertFalse(app.get().change().isPresent());
assertTrue(tester.deploymentQueue().jobs().isEmpty());
}
Aggregations