diff options
author | Øyvind Grønnesby <oyving@verizonmedia.com> | 2021-04-29 16:39:16 +0200 |
---|---|---|
committer | Øyvind Grønnesby <oyving@verizonmedia.com> | 2021-04-29 16:39:16 +0200 |
commit | 0d1ae535057f3884fc4c438a5886c2af85347781 (patch) | |
tree | cd8fb0c8dccea0ea6b802b95f90b539a5e5fb6a8 | |
parent | dd2ef6cfc4d3d6e3735d1cb553f7ae2560a7f1ff (diff) |
Inject Clock into BillingApiHandlerV2
- Injects the clock instance to make tests with date output work
- Rename invoice -> bill in the API path
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\":{}}]}"); } } |