aboutsummaryrefslogtreecommitdiffstats
path: root/controller-server
diff options
context:
space:
mode:
authorJon Marius Venstad <jonmv@users.noreply.github.com>2021-03-16 16:52:24 +0100
committerGitHub <noreply@github.com>2021-03-16 16:52:24 +0100
commit0dec30570440a8b5010ab5c24eb1ee4f6b0bf0a3 (patch)
tree9afad298d92bf92ea1da15f8e60929ccc2fd0826 /controller-server
parent218bb1b3d526ceef46c44086af48448a106de69a (diff)
parent1827a83e71affba0cabcda45614f984696bd56d7 (diff)
Merge pull request #16989 from vespa-engine/jonmv/faster-tenant-listing
Jonmv/faster tenant listing
Diffstat (limited to 'controller-server')
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Application.java8
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java46
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/application/DeploymentQuotaCalculatorTest.java38
3 files changed, 29 insertions, 63 deletions
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Application.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Application.java
index ccb9dccdb3b..159e0bb1f0f 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Application.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Application.java
@@ -185,16 +185,14 @@ public class Application {
/** Returns the total quota usage for this application, excluding temporary deployments */
public QuotaUsage quotaUsage() {
return instances().values().stream()
- .filter(instance -> !instance.id().instance().isTester()) // Exclude temporary deployments
- .map(Instance::quotaUsage).reduce(QuotaUsage::add).orElse(QuotaUsage.none);
+ .map(Instance::quotaUsage).reduce(QuotaUsage::add).orElse(QuotaUsage.none);
}
/** Returns the total quota usage for this application, excluding one specific deployment (and temporary deployments) */
public QuotaUsage quotaUsage(ApplicationId application, ZoneId zone) {
return instances().values().stream()
- .filter(instance -> !instance.id().instance().isTester()) // Exclude temporary deployments
- .map(instance -> instance.quotaUsageExcluding(application, zone))
- .reduce(QuotaUsage::add).orElse(QuotaUsage.none);
+ .map(instance -> instance.quotaUsageExcluding(application, zone))
+ .reduce(QuotaUsage::add).orElse(QuotaUsage.none);
}
/** Returns the set of deploy keys for this application. */
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
index f252e532ea8..96fcb1d7f56 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
@@ -36,6 +36,7 @@ import com.yahoo.slime.Inspector;
import com.yahoo.slime.JsonParseException;
import com.yahoo.slime.Slime;
import com.yahoo.slime.SlimeUtils;
+import com.yahoo.vespa.hosted.controller.Application;
import com.yahoo.vespa.hosted.controller.Controller;
import com.yahoo.vespa.hosted.controller.Instance;
import com.yahoo.vespa.hosted.controller.LockedTenant;
@@ -51,7 +52,6 @@ import com.yahoo.vespa.hosted.controller.api.application.v4.model.configserverbi
import com.yahoo.vespa.hosted.controller.api.identifiers.DeploymentId;
import com.yahoo.vespa.hosted.controller.api.identifiers.TenantId;
import com.yahoo.vespa.hosted.controller.api.integration.billing.Quota;
-import com.yahoo.vespa.hosted.controller.api.integration.configserver.Application;
import com.yahoo.vespa.hosted.controller.api.integration.configserver.ApplicationReindexing;
import com.yahoo.vespa.hosted.controller.api.integration.configserver.Cluster;
import com.yahoo.vespa.hosted.controller.api.integration.configserver.ConfigServerException;
@@ -140,6 +140,7 @@ import static com.yahoo.jdisc.Response.Status.INTERNAL_SERVER_ERROR;
import static com.yahoo.jdisc.Response.Status.NOT_FOUND;
import static java.util.Map.Entry.comparingByKey;
import static java.util.stream.Collectors.joining;
+import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toUnmodifiableList;
/**
@@ -345,8 +346,12 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
private HttpResponse recursiveRoot(HttpRequest request) {
Slime slime = new Slime();
Cursor tenantArray = slime.setArray();
+ List<Application> applications = controller.applications().asList();
for (Tenant tenant : controller.tenants().asList())
- toSlime(tenantArray.addObject(), tenant, request);
+ toSlime(tenantArray.addObject(),
+ tenant,
+ applications.stream().filter(app -> app.id().tenant().equals(tenant.name())).collect(toList()),
+ request);
return new SlimeJsonResponse(slime);
}
@@ -372,7 +377,7 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
private HttpResponse tenant(Tenant tenant, HttpRequest request) {
Slime slime = new Slime();
- toSlime(slime.setObject(), tenant, request);
+ toSlime(slime.setObject(), tenant, controller.applications().asList(tenant.name()), request);
return new SlimeJsonResponse(slime);
}
@@ -482,7 +487,7 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
Slime slime = new Slime();
Cursor applicationArray = slime.setArray();
- for (com.yahoo.vespa.hosted.controller.Application application : controller.applications().asList(tenant)) {
+ for (Application application : controller.applications().asList(tenant)) {
if (applicationName.map(application.id().application().value()::equals).orElse(true)) {
Cursor applicationObject = applicationArray.addObject();
applicationObject.setString("tenant", application.id().tenant().value());
@@ -753,7 +758,7 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
return new MessageResponse(messageBuilder.toString());
}
- private com.yahoo.vespa.hosted.controller.Application getApplication(String tenantName, String applicationName) {
+ private Application getApplication(String tenantName, String applicationName) {
TenantAndApplicationId applicationId = TenantAndApplicationId.from(tenantName, applicationName);
return controller.applications().getApplication(applicationId)
.orElseThrow(() -> new NotExistsException(applicationId + " not found"));
@@ -791,7 +796,7 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
private HttpResponse clusters(String tenantName, String applicationName, String instanceName, String environment, String region) {
ApplicationId id = ApplicationId.from(tenantName, applicationName, instanceName);
ZoneId zone = requireZone(environment, region);
- Application application = controller.serviceRegistry().configServer().nodeRepository().getApplication(zone, id);
+ com.yahoo.vespa.hosted.controller.api.integration.configserver.Application application = controller.serviceRegistry().configServer().nodeRepository().getApplication(zone, id);
Slime slime = new Slime();
Cursor clustersObject = slime.setObject().setObject("clusters");
@@ -932,7 +937,7 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
return new MessageResponse(type.jobName() + " for " + id + " resumed");
}
- private void toSlime(Cursor object, com.yahoo.vespa.hosted.controller.Application application, HttpRequest request) {
+ private void toSlime(Cursor object, Application application, HttpRequest request) {
object.setString("tenant", application.id().tenant().value());
object.setString("application", application.id().application().value());
object.setString("deployments", withPath("/application/v4" +
@@ -1070,7 +1075,7 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
}
private void toSlime(Cursor object, Instance instance, DeploymentStatus status, HttpRequest request) {
- com.yahoo.vespa.hosted.controller.Application application = status.application();
+ Application application = status.application();
object.setString("tenant", instance.id().tenant().value());
object.setString("application", instance.id().application().value());
object.setString("instance", instance.id().instance().value());
@@ -1572,7 +1577,7 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
Inspector requestObject = toSlime(request.getData()).get();
TenantAndApplicationId id = TenantAndApplicationId.from(tenantName, applicationName);
Credentials credentials = accessControlRequests.credentials(id.tenant(), requestObject, request.getJDiscRequest());
- com.yahoo.vespa.hosted.controller.Application application = controller.applications().createApplication(id, credentials);
+ Application application = controller.applications().createApplication(id, credentials);
Slime slime = new Slime();
toSlime(id, slime.setObject(), request);
return new SlimeJsonResponse(slime);
@@ -1837,7 +1842,7 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
Optional<ApplicationPackage> applicationPackage = Optional.ofNullable(dataParts.get("applicationZip"))
.map(ApplicationPackage::new);
- Optional<com.yahoo.vespa.hosted.controller.Application> application = controller.applications().getApplication(TenantAndApplicationId.from(applicationId));
+ Optional<Application> application = controller.applications().getApplication(TenantAndApplicationId.from(applicationId));
Inspector sourceRevision = deployOptions.field("sourceRevision");
Inspector buildNumber = deployOptions.field("buildNumber");
@@ -1977,10 +1982,9 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
.orElseThrow(() -> new NotExistsException(new TenantId(tenantName)));
}
- private void toSlime(Cursor object, Tenant tenant, HttpRequest request) {
+ private void toSlime(Cursor object, Tenant tenant, List<Application> applications, HttpRequest request) {
object.setString("tenant", tenant.name().value());
object.setString("type", tenantType(tenant));
- List<com.yahoo.vespa.hosted.controller.Application> applications = controller.applications().asList(tenant.name());
switch (tenant.type()) {
case athenz:
AthenzTenant athenzTenant = (AthenzTenant) tenant;
@@ -2013,7 +2017,7 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
var tenantQuota = controller.serviceRegistry().billingController().getQuota(tenant.name());
var usedQuota = applications.stream()
- .map(com.yahoo.vespa.hosted.controller.Application::quotaUsage)
+ .map(Application::quotaUsage)
.reduce(QuotaUsage.none, QuotaUsage::add);
toSlime(tenantQuota, usedQuota, object.setObject("quota"));
@@ -2024,16 +2028,19 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
}
// TODO jonmv: This should list applications, not instances.
Cursor applicationArray = object.setArray("applications");
- for (com.yahoo.vespa.hosted.controller.Application application : applications) {
- DeploymentStatus status = controller.jobController().deploymentStatus(application);
+ for (Application application : applications) {
+ DeploymentStatus status = null;
for (Instance instance : showOnlyProductionInstances(request) ? application.productionInstances().values()
: application.instances().values())
- if (recurseOverApplications(request))
+ if (recurseOverApplications(request)) {
+ if (status == null) status = controller.jobController().deploymentStatus(application);
toSlime(applicationArray.addObject(), instance, status, request);
- else
+ }
+ else {
toSlime(instance.id(), applicationArray.addObject(), request);
+ }
}
- tenantMetaDataToSlime(tenant, object.setObject("metaData"));
+ tenantMetaDataToSlime(tenant, applications, object.setObject("metaData"));
}
private void toSlime(Quota quota, QuotaUsage usage, Cursor object) {
@@ -2101,8 +2108,7 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
object.setString("url", withPath("/application/v4/tenant/" + tenant.name().value(), requestURI).toString());
}
- private void tenantMetaDataToSlime(Tenant tenant, Cursor object) {
- List<com.yahoo.vespa.hosted.controller.Application> applications = controller.applications().asList(tenant.name());
+ private void tenantMetaDataToSlime(Tenant tenant, List<Application> applications, Cursor object) {
Optional<Instant> lastDev = applications.stream()
.flatMap(application -> application.instances().values().stream())
.flatMap(instance -> controller.jobController().jobs(instance.id()).stream()
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/application/DeploymentQuotaCalculatorTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/application/DeploymentQuotaCalculatorTest.java
index d0de33f30e3..28bbeb63caa 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/application/DeploymentQuotaCalculatorTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/application/DeploymentQuotaCalculatorTest.java
@@ -82,42 +82,4 @@ public class DeploymentQuotaCalculatorTest {
assertEquals(tenantQuota, calculated);
}
- @Test
- public void temporary_deployments_are_excluded() {
- var tenantQuota = Quota.unlimited().withBudget(42);
-
- var instanceInTestEnv = new Instance(ApplicationId.from("default", "default", "foo")).withNewDeployment(
- ZoneId.from("test", "apac1"),
- ApplicationVersion.unknown,
- Version.emptyVersion,
- Instant.EPOCH,
- Map.of(),
- QuotaUsage.create(1));
-
- var testerInstance = new Instance(ApplicationId.from("default", "default", "bar-t")).withNewDeployment(
- ZoneId.from("prod", "apac1"),
- ApplicationVersion.unknown,
- Version.emptyVersion,
- Instant.EPOCH,
- Map.of(),
- QuotaUsage.create(1));
-
- var app = new Application(
- TenantAndApplicationId.from(ApplicationId.defaultId()),
- Instant.EPOCH,
- DeploymentSpec.empty,
- ValidationOverrides.empty,
- Optional.empty(),
- Optional.empty(),
- Optional.empty(),
- OptionalInt.empty(),
- new ApplicationMetrics(100, 100),
- Set.of(),
- OptionalLong.empty(),
- Optional.empty(),
- List.of(instanceInTestEnv, testerInstance));
-
- Quota calculated = DeploymentQuotaCalculator.calculate(tenantQuota, List.of(app), ApplicationId.defaultId(), ZoneId.from("dev", "apac1"), DeploymentSpec.empty);
- assertEquals(tenantQuota, calculated);
- }
}