summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/MockBillingController.java11
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerV2.java15
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ServiceRegistryMock.java2
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerV2Test.java8
4 files changed, 27 insertions, 9 deletions
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/MockBillingController.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/MockBillingController.java
index b24d532d4a3..ab2d8b8dce5 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/MockBillingController.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/MockBillingController.java
@@ -5,7 +5,9 @@ import com.yahoo.config.provision.TenantName;
import com.yahoo.vespa.hosted.controller.api.integration.user.User;
import java.math.BigDecimal;
+import java.time.Clock;
import java.time.LocalDate;
+import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Collection;
@@ -21,6 +23,7 @@ import java.util.stream.Collectors;
*/
public class MockBillingController implements BillingController {
+ private final Clock clock;
Map<TenantName, PlanId> plans = new HashMap<>();
Map<TenantName, PaymentInstrument> activeInstruments = new HashMap<>();
Map<TenantName, List<Invoice>> committedInvoices = new HashMap<>();
@@ -28,6 +31,10 @@ public class MockBillingController implements BillingController {
Map<TenantName, List<Invoice.LineItem>> unusedLineItems = new HashMap<>();
Map<TenantName, CollectionMethod> collectionMethod = new HashMap<>();
+ public MockBillingController(Clock clock) {
+ this.clock = clock;
+ }
+
@Override
public PlanId getPlan(TenantName tenant) {
return plans.getOrDefault(tenant, PlanId.from("trial"));
@@ -192,6 +199,8 @@ public class MockBillingController implements BillingController {
}
private Invoice emptyInvoice() {
- return new Invoice(Invoice.Id.of("empty"), TenantName.defaultName(), Invoice.StatusHistory.open(), List.of(), ZonedDateTime.now(), ZonedDateTime.now());
+ var start = clock.instant().atZone(ZoneOffset.UTC);
+ var end = clock.instant().atZone(ZoneOffset.UTC);
+ return new Invoice(Invoice.Id.of("empty"), TenantName.defaultName(), Invoice.StatusHistory.open(), List.of(), start, end);
}
}
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 d288ed48517..2ad0dece8d9 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,7 +27,9 @@ import javax.ws.rs.ForbiddenException;
import java.io.IOException;
import java.math.BigDecimal;
import java.security.Principal;
+import java.time.Clock;
import java.time.LocalDate;
+import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Optional;
import java.util.List;
@@ -42,12 +44,14 @@ public class BillingApiHandlerV2 extends RestApiRequestHandler<BillingApiHandler
private final ApplicationController applications;
private final TenantController tenants;
private final BillingController billing;
+ private final Clock clock;
public BillingApiHandlerV2(LoggingRequestHandler.Context context, Controller controller) {
super(context, BillingApiHandlerV2::createRestApi);
this.applications = controller.applications();
this.tenants = controller.tenants();
this.billing = controller.serviceRegistry().billingController();
+ this.clock = controller.serviceRegistry().clock();
}
private static RestApi createRestApi(BillingApiHandlerV2 self) {
@@ -60,9 +64,9 @@ public class BillingApiHandlerV2 extends RestApiRequestHandler<BillingApiHandler
.patch(Slime.class, self::patchTenant))
.addRoute(RestApi.route("/billing/v2/tenant/{tenant}/usage")
.get(self::tenantUsage))
- .addRoute(RestApi.route("/billing/v2/tenant/{tenant}/invoice")
+ .addRoute(RestApi.route("/billing/v2/tenant/{tenant}/bill")
.get(self::tenantInvoiceList))
- .addRoute(RestApi.route("/billing/v2/tenant/{tenant}/invoice/{invoice}")
+ .addRoute(RestApi.route("/billing/v2/tenant/{tenant}/bill/{invoice}")
.get(self::tenantInvoice))
/*
* This is the API that is created for accountant role in Vespa Cloud
@@ -149,7 +153,7 @@ public class BillingApiHandlerV2 extends RestApiRequestHandler<BillingApiHandler
var invoice = billing.getInvoicesForTenant(tenant.name()).stream()
.filter(inv -> inv.id().value().equals(invoiceId))
.findAny()
- .orElseThrow(RestApiException.NotFoundException::new);
+ .orElseThrow(RestApiException.NotFound::new);
if (format.equals("json")) {
var slime = new Slime();
@@ -177,8 +181,9 @@ public class BillingApiHandlerV2 extends RestApiRequestHandler<BillingApiHandler
var tenant = tenants.require(tenantName, CloudTenant.class);
var untilAt = requestContext.queryParameters().getString("until")
.map(LocalDate::parse)
- .orElseGet(() -> LocalDate.now().plusDays(1));
- var usage = billing.createUncommittedInvoice(tenant.name(), untilAt);
+ .map(date -> date.plusDays(1).atStartOfDay(ZoneOffset.UTC).toInstant())
+ .orElseGet(clock::instant);
+ var usage = billing.createUncommittedInvoice(tenant.name(), untilAt.atZone(ZoneOffset.UTC).toLocalDate());
var slime = new Slime();
usageToSlime(slime.setObject(), usage);
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ServiceRegistryMock.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ServiceRegistryMock.java
index 326928b9463..09b48b8fbf0 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ServiceRegistryMock.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ServiceRegistryMock.java
@@ -67,7 +67,7 @@ public class ServiceRegistryMock extends AbstractComponent implements ServiceReg
private final MockRunDataStore mockRunDataStore = new MockRunDataStore();
private final MockResourceTagger mockResourceTagger = new MockResourceTagger();
private final RoleService roleService = new NoopRoleService();
- private final BillingController billingController = new MockBillingController();
+ private final BillingController billingController = new MockBillingController(clock);
private final ContainerRegistryMock containerRegistry = new ContainerRegistryMock();
private final NoopTenantSecretService tenantSecretService = new NoopTenantSecretService();
private final ArchiveService archiveService = new MockArchiveService();
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 ae7f09e327f..8122c4c9679 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
@@ -2,6 +2,7 @@ package com.yahoo.vespa.hosted.controller.restapi.billing;
import com.yahoo.application.container.handler.Request;
import com.yahoo.config.provision.TenantName;
+import com.yahoo.test.ManualClock;
import com.yahoo.vespa.hosted.controller.api.integration.billing.MockBillingController;
import com.yahoo.vespa.hosted.controller.api.role.Role;
import com.yahoo.vespa.hosted.controller.restapi.ContainerTester;
@@ -11,6 +12,7 @@ import com.yahoo.vespa.hosted.controller.security.CloudTenantSpec;
import org.junit.Before;
import org.junit.Test;
+import java.time.Instant;
import java.util.Set;
/**
@@ -38,6 +40,8 @@ public class BillingApiHandlerV2Test extends ControllerContainerCloudTest {
public void before() {
tester = new ContainerTester(container, responseFiles);
tester.controller().tenants().create(new CloudTenantSpec(tenant, ""), new Auth0Credentials(() -> "foo", Set.of(Role.hostedOperator())));
+ var clock = (ManualClock) tester.controller().serviceRegistry().clock();
+ clock.setInstant(Instant.parse("2021-04-13T00:00:00Z"));
billingController = (MockBillingController) tester.serviceRegistry().billingController();
billingController.addInvoice(tenant, BillingApiHandlerTest.createInvoice(), true);
}
@@ -99,10 +103,10 @@ public class BillingApiHandlerV2Test extends ControllerContainerCloudTest {
@Test
public void require_tenant_invoice() {
- var listRequest = request("/billing/v2/tenant/" + tenant + "/invoice").roles(tenantReader);
+ var listRequest = request("/billing/v2/tenant/" + tenant + "/bill").roles(tenantReader);
tester.assertResponse(listRequest, "{\"invoices\":[{\"id\":\"id-1\",\"from\":\"2020-05-23\",\"to\":\"2020-05-23\",\"total\":\"123.00\",\"status\":\"OPEN\"}]}");
- var singleRequest = request("/billing/v2/tenant/" + tenant + "/invoice/id-1").roles(tenantReader);
+ var singleRequest = request("/billing/v2/tenant/" + tenant + "/bill/id-1").roles(tenantReader);
tester.assertResponse(singleRequest, "{\"id\":\"id-1\",\"from\":\"2020-05-23\",\"to\":\"2020-05-23\",\"total\":\"123.00\",\"status\":\"OPEN\",\"statusHistory\":[{\"at\":\"2020-05-23T00:00:00+02:00\",\"status\":\"OPEN\"}],\"items\":[{\"id\":\"some-id\",\"description\":\"description\",\"amount\":\"123.00\",\"plan\":\"some-plan\",\"planName\":\"Plan with id: some-plan\",\"cpu\":{},\"memory\":{},\"disk\":{}}]}");
}
}