use of com.yahoo.vespa.hosted.controller.application.Deployment in project vespa by vespa-engine.
the class ClusterUtilizationMaintainerTest method maintain.
@Test
public void maintain() {
ControllerTester tester = new ControllerTester();
ApplicationId app = tester.createAndDeploy("tenant1", "domain1", "app1", Environment.dev, 123).id();
// Precondition: no cluster info attached to the deployments
Deployment deployment = tester.controller().applications().get(app).get().deployments().values().stream().findAny().get();
Assert.assertEquals(0, deployment.clusterUtils().size());
ClusterUtilizationMaintainer mainainer = new ClusterUtilizationMaintainer(tester.controller(), Duration.ofHours(1), new JobControl(new MockCuratorDb()));
mainainer.maintain();
deployment = tester.controller().applications().get(app).get().deployments().values().stream().findAny().get();
Assert.assertEquals(1, deployment.clusterUtils().size());
Assert.assertEquals(0.5554, deployment.clusterUtils().get(ClusterSpec.Id.from("default")).getCpu(), Double.MIN_VALUE);
}
use of com.yahoo.vespa.hosted.controller.application.Deployment 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.vespa.hosted.controller.application.Deployment 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.vespa.hosted.controller.application.Deployment in project vespa by vespa-engine.
the class ApplicationController method deployApplication.
/**
* Deploys an application. If the application does not exist it is created.
*/
// TODO: Get rid of the options arg
public ActivateResult deployApplication(ApplicationId applicationId, ZoneId zone, Optional<ApplicationPackage> applicationPackageFromDeployer, DeployOptions options) {
try (Lock lock = lock(applicationId)) {
LockedApplication application = get(applicationId).map(app -> new LockedApplication(app, lock)).orElseGet(() -> new LockedApplication(createApplication(applicationId, Optional.empty()), lock));
final boolean canDeployDirectly = canDeployDirectlyTo(zone, options);
// Determine Vespa version to use
Version version;
if (options.deployCurrentVersion) {
version = application.versionIn(zone, controller);
} else if (canDeployDirectlyTo(zone, options)) {
version = options.vespaVersion.map(Version::new).orElse(controller.systemVersion());
} else if (!application.change().isPresent() && !zone.environment().isManuallyDeployed()) {
return unexpectedDeployment(applicationId, zone, applicationPackageFromDeployer);
} else {
version = application.deployVersionIn(zone, controller);
}
// Determine application package to use
Pair<ApplicationPackage, ApplicationVersion> artifact = artifactFor(zone, application, applicationPackageFromDeployer, canDeployDirectly, options.deployCurrentVersion);
ApplicationPackage applicationPackage = artifact.getFirst();
ApplicationVersion applicationVersion = artifact.getSecond();
validate(applicationPackage.deploymentSpec());
// Update application with information from application package
if (!options.deployCurrentVersion) {
// Store information about application package
application = application.with(applicationPackage.deploymentSpec());
application = application.with(applicationPackage.validationOverrides());
// Delete zones not listed in DeploymentSpec, if allowed
// We do this at deployment time to be able to return a validation failure message when necessary
application = deleteRemovedDeployments(application);
// Clean up deployment jobs that are no longer referenced by deployment spec
application = deleteUnreferencedDeploymentJobs(application);
// TODO jvenstad: Store triggering information here, including versions, when job status is read from the build service.
// store missing information even if we fail deployment below
store(application);
}
// Validate the change being deployed
if (!canDeployDirectly) {
validateChange(application, zone, version);
}
// Assign global rotation
application = withRotation(application, zone);
Set<String> rotationNames = new HashSet<>();
Set<String> cnames = new HashSet<>();
application.rotation().ifPresent(applicationRotation -> {
rotationNames.add(applicationRotation.id().asString());
cnames.add(applicationRotation.dnsName());
cnames.add(applicationRotation.secureDnsName());
});
// Carry out deployment
options = withVersion(version, options);
ConfigServerClient.PreparedApplication preparedApplication = configServer.prepare(new DeploymentId(applicationId, zone), options, cnames, rotationNames, applicationPackage.zippedContent());
preparedApplication.activate();
application = application.withNewDeployment(zone, applicationVersion, version, clock.instant());
store(application);
return new ActivateResult(new RevisionId(applicationPackage.hash()), preparedApplication.prepareResponse(), applicationPackage.zippedContent().length);
}
}
use of com.yahoo.vespa.hosted.controller.application.Deployment in project vespa by vespa-engine.
the class LockedApplication method withNewDeployment.
public LockedApplication withNewDeployment(ZoneId zone, ApplicationVersion applicationVersion, Version version, Instant instant) {
// 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());
return with(newDeployment);
}
Aggregations