summaryrefslogtreecommitdiffstats
path: root/controller-server
diff options
context:
space:
mode:
authorØyvind Grønnesby <oyving@vespa.ai>2023-10-19 16:26:51 +0200
committerØyvind Grønnesby <oyving@vespa.ai>2023-10-19 16:26:51 +0200
commit9adabfa8339d818d0e90e624112469188b9d30b4 (patch)
tree27caca630471a84aa0978b2bab182a7c3ac739e5 /controller-server
parent5e02a90eb9a74228e1dcc6728cbb3b2c730c3486 (diff)
Billing system information for a tenant
Diffstat (limited to 'controller-server')
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerV2.java47
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerV2Test.java8
2 files changed, 55 insertions, 0 deletions
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerV2.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerV2.java
index f32388b388a..cbf26e81f98 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerV2.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerV2.java
@@ -27,6 +27,7 @@ import com.yahoo.vespa.hosted.controller.api.integration.billing.Quota;
import com.yahoo.vespa.hosted.controller.api.role.Role;
import com.yahoo.vespa.hosted.controller.api.role.SecurityContext;
import com.yahoo.vespa.hosted.controller.restapi.ErrorResponses;
+import com.yahoo.vespa.hosted.controller.tenant.BillingReference;
import com.yahoo.vespa.hosted.controller.tenant.CloudTenant;
import com.yahoo.vespa.hosted.controller.tenant.Tenant;
@@ -90,6 +91,8 @@ public class BillingApiHandlerV2 extends RestApiRequestHandler<BillingApiHandler
.addRoute(RestApi.route("/billing/v2/accountant/preview/tenant/{tenant}")
.get(self::previewBill)
.post(Slime.class, self::createBill))
+ .addRoute(RestApi.route("/billing/v2/accountant/tenant/{tenant}")
+ .get(self::accountantTenant))
.addRoute(RestApi.route("/billing/v2/accountant/tenant/{tenant}/preview")
.get(self::previewBill)
.post(Slime.class, self::createBill))
@@ -427,6 +430,23 @@ public class BillingApiHandlerV2 extends RestApiRequestHandler<BillingApiHandler
return slime;
}
+ private Slime accountantTenant(RestApi.RequestContext requestContext) {
+ var tenantName = TenantName.from(requestContext.pathParameters().getStringOrThrow("tenant"));
+ var tenant = tenants.require(tenantName, CloudTenant.class);
+
+ var slime = new Slime();
+ var root = slime.setObject();
+
+ var planId = billing.getPlan(tenant.name());
+ var plan = planRegistry.plan(planId);
+
+ var collection = billing.getCollectionMethod(tenant.name());
+
+ toSlime(root, tenant, planId, plan, collection);
+
+ return slime;
+ }
+
// --------- INVOICE RENDERING ----------
private void invoicesSummaryToSlime(Cursor slime, List<Bill> bills) {
@@ -498,6 +518,33 @@ public class BillingApiHandlerV2 extends RestApiRequestHandler<BillingApiHandler
cost.ifPresent(c -> slime.setString("cost", c.toString()));
}
+ private void toSlime(Cursor slime, CloudTenant tenant, PlanId planId, Optional<Plan> plan, CollectionMethod method) {
+ slime.setString("tenant", tenant.name().value());
+ toSlime(slime.setObject("plan"), planId, plan);
+ toSlime(slime.setObject("billing"), tenant.billingReference());
+ slime.setString("collection", method.name());
+ }
+
+ private void toSlime(Cursor slime, PlanId planId, Optional<Plan> plan) {
+ slime.setString("id", planId.value());
+ if (plan.isPresent()) {
+ slime.setString("name", plan.get().displayName());
+ slime.setBool("billed", plan.get().isBilled());
+ slime.setBool("supported", plan.get().isSupported());
+ } else {
+ slime.setString("name", "UNKNOWN");
+ slime.setBool("billed", false);
+ slime.setBool("supported", false);
+ }
+ }
+
+ private void toSlime(Cursor slime, Optional<BillingReference> billingReference) {
+ if (billingReference.isPresent()) {
+ slime.setString("id", billingReference.get().reference());
+ slime.setLong("lastUpdated", billingReference.get().updated().toEpochMilli());
+ }
+ }
+
private List<Object[]> toCsv(Bill bill) {
return List.<Object[]>of(new Object[]{
bill.id().value(), bill.tenant().value(),
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerV2Test.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerV2Test.java
index b7c86246158..4d3297ddb0c 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerV2Test.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerV2Test.java
@@ -237,4 +237,12 @@ public class BillingApiHandlerV2Test extends ControllerContainerCloudTest {
{"collection":"INVOICE"}""");
}
}
+
+ @Test
+ void require_accountant_tenant() {
+ var accountantRequest = request("/billing/v2/accountant/tenant/tenant1")
+ .roles(Role.hostedAccountant());
+ tester.assertResponse(accountantRequest, """
+ {"tenant":"tenant1","plan":{"id":"trial","name":"Free Trial - for testing purposes","billed":false,"supported":false},"billing":{},"collection":"AUTO"}""");
+ }
}