use of com.yahoo.component.Version in project vespa by vespa-engine.
the class ControllerTest method testCleanupOfStaleDeploymentData.
@Test
public void testCleanupOfStaleDeploymentData() throws IOException {
DeploymentTester tester = new DeploymentTester();
tester.controllerTester().zoneRegistry().setSystem(SystemName.cd);
tester.controllerTester().zoneRegistry().setZones(ZoneId.from("prod", "cd-us-central-1"));
Supplier<Map<JobType, JobStatus>> statuses = () -> tester.application(ApplicationId.from("vespa", "canary", "default")).deploymentJobs().jobStatus();
// Current system version, matches version in test data
Version version = Version.fromString("6.141.117");
tester.configServer().setDefaultVersion(version);
tester.updateVersionStatus(version);
assertEquals(version, tester.controller().versionStatus().systemVersion().get().versionNumber());
// Load test data data
byte[] json = Files.readAllBytes(Paths.get("src/test/java/com/yahoo/vespa/hosted/controller/maintenance/testdata/canary-with-stale-data.json"));
Application application = tester.controllerTester().createApplication(SlimeUtils.jsonToSlime(json));
ApplicationPackage applicationPackage = new ApplicationPackageBuilder().upgradePolicy("canary").region("cd-us-central-1").build();
tester.jobCompletion(component).application(application).uploadArtifact(applicationPackage).submit();
long cdJobsCount = statuses.get().keySet().stream().filter(type -> type.zone(SystemName.cd).isPresent()).count();
long mainJobsCount = statuses.get().keySet().stream().filter(type -> type.zone(SystemName.main).isPresent() && !type.zone(SystemName.cd).isPresent()).count();
assertEquals("Irrelevant (main) data is present.", 8, mainJobsCount);
// New version is released
version = Version.fromString("6.142.1");
tester.configServer().setDefaultVersion(version);
tester.updateVersionStatus(version);
assertEquals(version, tester.controller().versionStatus().systemVersion().get().versionNumber());
tester.upgrader().maintain();
tester.readyJobTrigger().maintain();
// Test environments pass
tester.deploy(DeploymentJobs.JobType.systemTest, application, applicationPackage);
tester.deploymentQueue().takeJobsToRun();
tester.clock().advance(Duration.ofMinutes(10));
tester.jobCompletion(systemTest).application(application).submit();
long newCdJobsCount = statuses.get().keySet().stream().filter(type -> type.zone(SystemName.cd).isPresent()).count();
long newMainJobsCount = statuses.get().keySet().stream().filter(type -> type.zone(SystemName.main).isPresent() && !type.zone(SystemName.cd).isPresent()).count();
assertEquals("Irrelevant (main) job data is removed.", 0, newMainJobsCount);
assertEquals("Relevant (cd) data is not removed.", cdJobsCount, newCdJobsCount);
}
use of com.yahoo.component.Version in project vespa by vespa-engine.
the class ApplicationApiHandler method toSlime.
private void toSlime(Cursor object, Application application, HttpRequest request) {
object.setString("application", application.id().application().value());
object.setString("instance", application.id().instance().value());
// Currently deploying change
if (application.change().isPresent()) {
Cursor deployingObject = object.setObject("deploying");
application.change().platform().ifPresent(v -> deployingObject.setString("version", v.toString()));
application.change().application().filter(v -> v != ApplicationVersion.unknown).ifPresent(v -> toSlime(v, deployingObject.setObject("revision")));
}
// Jobs sorted according to deployment spec
List<JobStatus> jobStatus = controller.applications().deploymentTrigger().deploymentOrder().sortBy(application.deploymentSpec(), application.deploymentJobs().jobStatus().values());
Cursor deploymentsArray = object.setArray("deploymentJobs");
for (JobStatus job : jobStatus) {
Cursor jobObject = deploymentsArray.addObject();
jobObject.setString("type", job.type().jobName());
jobObject.setBool("success", job.isSuccess());
job.lastTriggered().ifPresent(jobRun -> toSlime(jobRun, jobObject.setObject("lastTriggered")));
job.lastCompleted().ifPresent(jobRun -> toSlime(jobRun, jobObject.setObject("lastCompleted")));
job.firstFailing().ifPresent(jobRun -> toSlime(jobRun, jobObject.setObject("firstFailing")));
job.lastSuccess().ifPresent(jobRun -> toSlime(jobRun, jobObject.setObject("lastSuccess")));
}
// Change blockers
Cursor changeBlockers = object.setArray("changeBlockers");
application.deploymentSpec().changeBlocker().forEach(changeBlocker -> {
Cursor changeBlockerObject = changeBlockers.addObject();
changeBlockerObject.setBool("versions", changeBlocker.blocksVersions());
changeBlockerObject.setBool("revisions", changeBlocker.blocksRevisions());
changeBlockerObject.setString("timeZone", changeBlocker.window().zone().getId());
Cursor days = changeBlockerObject.setArray("days");
changeBlocker.window().days().stream().map(DayOfWeek::getValue).forEach(days::addLong);
Cursor hours = changeBlockerObject.setArray("hours");
changeBlocker.window().hours().forEach(hours::addLong);
});
// Compile version. The version that should be used when building an application
object.setString("compileVersion", application.oldestDeployedVersion().orElse(controller.systemVersion()).toFullString());
// Rotation
Cursor globalRotationsArray = object.setArray("globalRotations");
application.rotation().ifPresent(rotation -> {
globalRotationsArray.addString(rotation.url().toString());
globalRotationsArray.addString(rotation.secureUrl().toString());
object.setString("rotationId", rotation.id().asString());
});
// Deployments sorted according to deployment spec
List<Deployment> deployments = controller.applications().deploymentTrigger().deploymentOrder().sortBy(application.deploymentSpec().zones(), application.deployments().values());
Cursor instancesArray = object.setArray("instances");
for (Deployment deployment : deployments) {
Cursor deploymentObject = instancesArray.addObject();
deploymentObject.setString("environment", deployment.zone().environment().value());
deploymentObject.setString("region", deployment.zone().region().value());
// pointless
deploymentObject.setString("instance", application.id().instance().value());
if (application.rotation().isPresent()) {
Map<String, RotationStatus> rotationHealthStatus = application.rotation().map(rotation -> controller.getHealthStatus(rotation.dnsName())).orElse(Collections.emptyMap());
setRotationStatus(deployment, rotationHealthStatus, deploymentObject);
}
if (// List full deployment information when recursive.
recurseOverDeployments(request))
toSlime(deploymentObject, new DeploymentId(application.id(), deployment.zone()), deployment, request);
else
deploymentObject.setString("url", withPath(request.getUri().getPath() + "/environment/" + deployment.zone().environment().value() + "/region/" + deployment.zone().region().value() + "/instance/" + application.id().instance().value(), request.getUri()).toString());
}
// Metrics
Cursor metricsObject = object.setObject("metrics");
metricsObject.setDouble("queryServiceQuality", application.metrics().queryServiceQuality());
metricsObject.setDouble("writeServiceQuality", application.metrics().writeServiceQuality());
application.ownershipIssueId().ifPresent(issueId -> object.setString("ownershipIssueId", issueId.value()));
application.deploymentJobs().issueId().ifPresent(issueId -> object.setString("deploymentIssueId", issueId.value()));
}
use of com.yahoo.component.Version in project vespa by vespa-engine.
the class ApplicationApiHandler method toSlime.
private void toSlime(Cursor response, DeploymentId deploymentId, Deployment deployment, HttpRequest request) {
Cursor serviceUrlArray = response.setArray("serviceUrls");
controller.applications().getDeploymentEndpoints(deploymentId).ifPresent(endpoints -> endpoints.forEach(endpoint -> serviceUrlArray.addString(endpoint.toString())));
response.setString("nodes", withPath("/zone/v2/" + deploymentId.zoneId().environment() + "/" + deploymentId.zoneId().region() + "/nodes/v2/node/?&recursive=true&application=" + deploymentId.applicationId().tenant() + "." + deploymentId.applicationId().application() + "." + deploymentId.applicationId().instance(), request.getUri()).toString());
controller.zoneRegistry().getLogServerUri(deploymentId).ifPresent(elkUrl -> response.setString("elkUrl", elkUrl.toString()));
response.setString("yamasUrl", monitoringSystemUri(deploymentId).toString());
response.setString("version", deployment.version().toFullString());
response.setString("revision", deployment.applicationVersion().id());
response.setLong("deployTimeEpochMs", deployment.at().toEpochMilli());
controller.zoneRegistry().getDeploymentTimeToLive(deploymentId.zoneId()).ifPresent(deploymentTimeToLive -> response.setLong("expiryTimeEpochMs", deployment.at().plus(deploymentTimeToLive).toEpochMilli()));
controller.applications().get(deploymentId.applicationId()).flatMap(application -> application.deploymentJobs().projectId()).ifPresent(i -> response.setString("screwdriverId", String.valueOf(i)));
sourceRevisionToSlime(deployment.applicationVersion().source(), response);
// Cost
DeploymentCost appCost = deployment.calculateCost();
Cursor costObject = response.setObject("cost");
toSlime(appCost, costObject);
// Metrics
DeploymentMetrics metrics = deployment.metrics();
Cursor metricsObject = response.setObject("metrics");
metricsObject.setDouble("queriesPerSecond", metrics.queriesPerSecond());
metricsObject.setDouble("writesPerSecond", metrics.writesPerSecond());
metricsObject.setDouble("documentCount", metrics.documentCount());
metricsObject.setDouble("queryLatencyMillis", metrics.queryLatencyMillis());
metricsObject.setDouble("writeLatencyMillis", metrics.writeLatencyMillis());
}
use of com.yahoo.component.Version in project vespa by vespa-engine.
the class DeploymentIssueReporterTest method testDeploymentFailureReporting.
@Test
public void testDeploymentFailureReporting() {
// All applications deploy from unique build projects.
Long projectId1 = 10L;
Long projectId2 = 20L;
Long projectId3 = 30L;
Long propertyId1 = 1L;
Long propertyId2 = 2L;
Long propertyId3 = 3L;
tester.updateVersionStatus(Version.fromString("5.1"));
// Create and deploy one application for each of three tenants.
Application app1 = tester.createApplication("application1", "tenant1", projectId1, propertyId1);
Application app2 = tester.createApplication("application2", "tenant2", projectId2, propertyId2);
Application app3 = tester.createApplication("application3", "tenant3", projectId3, propertyId3);
// NOTE: All maintenance should be idempotent within a small enough time interval, so maintain is called twice in succession throughout.
// apps 1 and 3 have one failure each.
tester.jobCompletion(component).application(app1).uploadArtifact(applicationPackage).submit();
tester.deployAndNotify(app1, applicationPackage, true, systemTest);
tester.deployAndNotify(app1, applicationPackage, false, stagingTest);
// app2 is successful, but will fail later.
tester.deployCompletely(app2, canaryPackage);
tester.jobCompletion(component).application(app3).uploadArtifact(applicationPackage).submit();
tester.deployAndNotify(app3, applicationPackage, true, systemTest);
tester.deployAndNotify(app3, applicationPackage, true, stagingTest);
tester.deployAndNotify(app3, applicationPackage, false, productionCorpUsEast1);
reporter.maintain();
reporter.maintain();
assertEquals("No deployments are detected as failing for a long time initially.", 0, issues.size());
// Advance to where deployment issues should be detected.
tester.clock().advance(maxFailureAge.plus(Duration.ofDays(1)));
reporter.maintain();
reporter.maintain();
assertTrue("One issue is produced for app1.", issues.isOpenFor(app1.id()));
assertFalse("No issues are produced for app2.", issues.isOpenFor(app2.id()));
assertTrue("One issue is produced for app3.", issues.isOpenFor(app3.id()));
// app3 closes their issue prematurely; see that it is refiled.
issues.closeFor(app3.id());
assertFalse("No issue is open for app3.", issues.isOpenFor(app3.id()));
reporter.maintain();
reporter.maintain();
assertTrue("Issue is re-filed for app3.", issues.isOpenFor(app3.id()));
// Some time passes; tenant1 leaves her issue unattended, while tenant3 starts work and updates the issue.
tester.clock().advance(maxInactivity.plus(maxFailureAge));
issues.touchFor(app3.id());
reporter.maintain();
reporter.maintain();
assertEquals("The issue for app1 is escalated once.", 1, issues.escalationLevelFor(app1.id()));
// app3 fixes their problems, but the ticket for app3 is left open; see the resolved ticket is not escalated when another escalation period has passed.
tester.deployAndNotify(app3, applicationPackage, true, productionCorpUsEast1);
tester.clock().advance(maxInactivity.plus(Duration.ofDays(1)));
reporter.maintain();
reporter.maintain();
assertFalse("We no longer have a platform issue.", issues.platformIssue());
assertEquals("The issue for app1 is escalated once more.", 2, issues.escalationLevelFor(app1.id()));
assertEquals("The issue for app3 is not escalated.", 0, issues.escalationLevelFor(app3.id()));
// app3 now has a new failure past max failure age; see that a new issue is filed.
tester.jobCompletion(component).application(app3).nextBuildNumber().uploadArtifact(applicationPackage).submit();
tester.deployAndNotify(app3, applicationPackage, false, systemTest);
tester.clock().advance(maxInactivity.plus(maxFailureAge));
reporter.maintain();
reporter.maintain();
assertTrue("A new issue is filed for app3.", issues.isOpenFor(app3.id()));
// Bump system version to 5.2 to upgrade canary app2.
Version version = Version.fromString("5.2");
tester.updateVersionStatus(version);
assertEquals(version, tester.controller().versionStatus().systemVersion().get().versionNumber());
tester.upgrader().maintain();
tester.readyJobTrigger().maintain();
tester.completeUpgradeWithError(app2, version, canaryPackage, systemTest);
tester.updateVersionStatus(version);
assertEquals(VespaVersion.Confidence.broken, tester.controller().versionStatus().systemVersion().get().confidence());
assertFalse("We have no platform issues initially.", issues.platformIssue());
reporter.maintain();
reporter.maintain();
assertFalse("We have no platform issue before the grace period is out for the failing canary.", issues.platformIssue());
tester.clock().advance(upgradeGracePeriod.plus(upgradeGracePeriod));
reporter.maintain();
reporter.maintain();
assertTrue("We get a platform issue when confidence is broken", issues.platformIssue());
assertFalse("No deployment issue is filed for app2, which has a version upgrade failure.", issues.isOpenFor(app2.id()));
}
use of com.yahoo.component.Version in project vespa by vespa-engine.
the class ConfidenceOverrideSerializer method fromSlime.
public Map<Version, Confidence> fromSlime(Slime slime) {
Cursor root = slime.get();
Cursor overridesObject = root.field(overridesField);
Map<Version, Confidence> overrides = new LinkedHashMap<>();
overridesObject.traverse((ObjectTraverser) (name, value) -> {
overrides.put(Version.fromString(name), Confidence.valueOf(value.asString()));
});
return Collections.unmodifiableMap(overrides);
}
Aggregations