summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/ServiceRegistry.java9
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillingController.java71
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillingDatabaseClient.java135
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillingDatabaseClientMock.java178
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/Invoice.java (renamed from controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/Bill.java)18
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/MockBillingController.java60
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/PlanRegistry.java23
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/PlanRegistryMock.java122
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/resource/ResourceDatabaseClient.java51
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/resource/ResourceDatabaseClientMock.java146
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/resource/ResourceSnapshot.java4
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandler.java94
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerV2.java80
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ServiceRegistryMock.java24
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerTest.java57
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerV2Test.java2
16 files changed, 163 insertions, 911 deletions
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/ServiceRegistry.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/ServiceRegistry.java
index 93e3f5585c8..4714b74ba94 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/ServiceRegistry.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/ServiceRegistry.java
@@ -7,8 +7,6 @@ import com.yahoo.vespa.hosted.controller.api.integration.aws.RoleService;
import com.yahoo.vespa.hosted.controller.api.integration.aws.CloudEventFetcher;
import com.yahoo.vespa.hosted.controller.api.integration.aws.ResourceTagger;
import com.yahoo.vespa.hosted.controller.api.integration.billing.BillingController;
-import com.yahoo.vespa.hosted.controller.api.integration.billing.BillingDatabaseClient;
-import com.yahoo.vespa.hosted.controller.api.integration.billing.PlanRegistry;
import com.yahoo.vespa.hosted.controller.api.integration.certificates.EndpointCertificateProvider;
import com.yahoo.vespa.hosted.controller.api.integration.certificates.EndpointCertificateValidator;
import com.yahoo.vespa.hosted.controller.api.integration.configserver.ConfigServer;
@@ -27,7 +25,6 @@ import com.yahoo.vespa.hosted.controller.api.integration.organization.OwnershipI
import com.yahoo.vespa.hosted.controller.api.integration.organization.SystemMonitor;
import com.yahoo.vespa.hosted.controller.api.integration.resource.CostReportConsumer;
import com.yahoo.vespa.hosted.controller.api.integration.resource.MeteringClient;
-import com.yahoo.vespa.hosted.controller.api.integration.resource.ResourceDatabaseClient;
import com.yahoo.vespa.hosted.controller.api.integration.routing.GlobalRoutingService;
import com.yahoo.vespa.hosted.controller.api.integration.secrets.TenantSecretService;
import com.yahoo.vespa.hosted.controller.api.integration.vcmr.ChangeRequestClient;
@@ -91,10 +88,6 @@ public interface ServiceRegistry {
BillingController billingController();
- ResourceDatabaseClient resourceDatabase();
-
- BillingDatabaseClient billingDatabase();
-
ContainerRegistry containerRegistry();
TenantSecretService tenantSecretService();
@@ -106,6 +99,4 @@ public interface ServiceRegistry {
AccessControlService accessControlService();
HorizonClient horizonClient();
-
- PlanRegistry planRegistry();
}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillingController.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillingController.java
index 61f8844482c..91916975146 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillingController.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillingController.java
@@ -12,112 +12,55 @@ import java.util.Map;
import java.util.Optional;
import java.util.Set;
-/**
- * A service that controls creation of bills based on the resource usage of a tenant, controls the quota for a
- * tenant, and controls the plan the tenant is on.
- *
- * @author ogronnesby
- * @author olaa
- */
public interface BillingController {
- /**
- * Get the plan ID for the given tenant.
- * This method will not fail if the tenant does not exist, it will return the default plan for that tenant instead.
- */
PlanId getPlan(TenantName tenant);
- /**
- * Return the list of tenants with the given plan.
- * @param existing All existing tenants in the system
- * @param planId The ID of the plan to filter existing tenants on.
- * @return The tenants that have the given plan.
- */
List<TenantName> tenantsWithPlan(List<TenantName> existing, PlanId planId);
- /** The display name of the given plan */
String getPlanDisplayName(PlanId planId);
- /**
- * The quota for the given tenant.
- * This method will return default quota for tenants that do not exist.
- */
Quota getQuota(TenantName tenant);
/**
- * Set the plan for the current tenant. Checks some pre-conditions to see if the tenant is eligible for the
- * given plan.
- * @param tenant The name of the tenant.
- * @param planId The ID of the plan to change to.
- * @param hasDeployments Does the tenant have active deployments.
* @return String containing error message if something went wrong. Empty otherwise
*/
PlanResult setPlan(TenantName tenant, PlanId planId, boolean hasDeployments);
- /**
- * Create a bill of unbilled use for the given tenant in the given time period.
- * @param tenant The name of the tenant.
- * @param startTime The start of the billing period
- * @param endTime The end of the billing period
- * @param agent The agent that creates the bill
- * @return The ID of the new bill.
- */
- Bill.Id createBillForPeriod(TenantName tenant, ZonedDateTime startTime, ZonedDateTime endTime, String agent);
+ Invoice.Id createInvoiceForPeriod(TenantName tenant, ZonedDateTime startTime, ZonedDateTime endTime, String agent);
- /**
- * Create an unpersisted bill of unbilled use for the given tenant from the end of last bill until the given date.
- * This is used to show "unbilled use" in the Console.
- * @param tenant The name of the tenant.
- * @param until The end date of the unbilled use period.
- * @return A bill with the resource use and cost.
- */
- Bill createUncommittedBill(TenantName tenant, LocalDate until);
+ Invoice createUncommittedInvoice(TenantName tenant, LocalDate until);
- /** Run {createUncommittedBill} for all tenants with unbilled use */
- Map<TenantName, Bill> createUncommittedBills(LocalDate until);
+ Map<TenantName, Invoice> createUncommittedInvoices(LocalDate until);
- /** Get line items that have been manually added to a tenant, but is not yet part of a bill */
- List<Bill.LineItem> getUnusedLineItems(TenantName tenant);
+ List<Invoice.LineItem> getUnusedLineItems(TenantName tenant);
- /** Get the payment instrument for the given tenant */
Optional<PaymentInstrument> getDefaultInstrument(TenantName tenant);
- /** Get the auth token needed to talk to payment services */
String createClientToken(String tenant, String userId);
- /** Delete a payment instrument from the list of the tenant's instruments */
boolean deleteInstrument(TenantName tenant, String userId, String instrumentId);
- /** Change the status of the given bill */
- void updateBillStatus(Bill.Id billId, String agent, String status);
+ void updateInvoiceStatus(Invoice.Id invoiceId, String agent, String status);
- /** Add a line item to the given bill */
void addLineItem(TenantName tenant, String description, BigDecimal amount, String agent);
- /** Delete a line item - only available for unused line items */
void deleteLineItem(String lineItemId);
- /** Set the given payment instrument as the active instrument for the tenant */
boolean setActivePaymentInstrument(InstrumentOwner paymentInstrument);
- /** List the payment instruments from the tenant */
InstrumentList listInstruments(TenantName tenant, String userId);
- /** Get all bills for the given tenant */
- List<Bill> getBillsForTenant(TenantName tenant);
+ List<Invoice> getInvoicesForTenant(TenantName tenant);
- /** Get all bills from the system */
- List<Bill> getBills();
+ List<Invoice> getInvoices();
- /** Delete billing contact information from the tenant */
void deleteBillingInfo(TenantName tenant, Set<User> users, boolean isPrivileged);
- /** Get the bill collection method for the given tenant */
default CollectionMethod getCollectionMethod(TenantName tenant) {
return CollectionMethod.NONE;
}
- /** Set the bill collection method for the given tenant */
default CollectionResult setCollectionMethod(TenantName tenant, CollectionMethod method) {
return CollectionResult.error("Method not implemented");
}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillingDatabaseClient.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillingDatabaseClient.java
deleted file mode 100644
index 4891fe0ffa7..00000000000
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillingDatabaseClient.java
+++ /dev/null
@@ -1,135 +0,0 @@
-// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.hosted.controller.api.integration.billing;
-
-import com.yahoo.config.provision.TenantName;
-
-import java.time.ZonedDateTime;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-
-/**
- * Interface that talks about bills in the billing API. It is a layer on top of the SQL
- * database where we store data about bills.
- *
- * @author olaa
- * @author ogronnesby
- */
-public interface BillingDatabaseClient {
-
- boolean setActivePaymentInstrument(InstrumentOwner paymentInstrument);
-
- Optional<InstrumentOwner> getDefaultPaymentInstrumentForTenant(TenantName from);
-
- /**
- * Create a completely new Bill in the open state with no LineItems.
- *
- * @param tenant The name of the tenant the bill is for
- * @param agent The agent that created the bill
- * @return The Id of the new bill
- */
- Bill.Id createBill(TenantName tenant, ZonedDateTime startTime, ZonedDateTime endTime, String agent);
-
- /**
- * Read the given bill from the data source
- *
- * @param billId The Id of the bill to retrieve
- * @return The Bill if it exists, Optional.empty() if not.
- */
- Optional<Bill> readBill(Bill.Id billId);
-
- /**
- * Get all bills for a given tenant, ordered by date
- *
- * @param tenant The name of the tenant
- * @return List of all bills ordered by date
- */
- List<Bill> readBillsForTenant(TenantName tenant);
-
- /**
- * Read all bills, ordered by date
- * @return List of all bills ordered by date
- */
- List<Bill> readBills();
-
- /**
- * Add a line item to an open bill
- *
- * @param lineItem
- * @param billId The optional ID of the bill this line item is for
- * @return The Id of the new line item
- * @throws RuntimeException if the bill is not in OPEN state
- */
- String addLineItem(TenantName tenantName, Bill.LineItem lineItem, Optional<Bill.Id> billId);
-
- /**
- * Set status for the given bill
- *
- * @param billId The ID of the bill this status is for
- * @param agent The agent that added the status
- * @param status The new status of the bill
- */
- void setStatus(Bill.Id billId, String agent, String status);
-
- List<Bill.LineItem> getUnusedLineItems(TenantName tenantName);
-
- /**
- * Delete a line item
- * This is only allowed if the line item has not yet been associated with an bill
- *
- * @param lineItemId The ID of the line item
- * @throws RuntimeException if the line item is associated with an bill
- */
- void deleteLineItem(String lineItemId);
-
- /**
- * Associate all uncommitted line items to a given bill
- * This is only allowed if the line item has not already been associated with an bill
- *
- * @param tenantName The tenant we want to commit line items for
- * @param billId The ID of the line item
- * @throws RuntimeException if the line item is already associated with an bill
- */
- void commitLineItems(TenantName tenantName, Bill.Id billId);
-
- /**
- * Return the plan for the given tenant
- *
- * @param tenantName The tenant to retrieve the plan for
- * @return Optional.of the plan if present in DN, else Optional.empty
- */
- Optional<Plan> getPlan(TenantName tenantName);
-
- /**
- * Return the plan for the given tenants if present.
- * If the database does not know of the tenant, the tenant is not included in the result.
- */
- Map<TenantName, Optional<Plan>> getPlans(List<TenantName> tenants);
-
- /**
- * Set the current plan for the given tenant
- *
- * @param tenantName The tenant to set the plan for
- * @param plan The plan to use
- */
- void setPlan(TenantName tenantName, Plan plan);
-
- /**
- * Deactivates the default payment instrument for a tenant, if it exists.
- * Used during tenant deletion
- */
- void deactivateDefaultPaymentInstrument(TenantName tenant);
-
- /**
- * Get the current collection method for the tenant - if one has persisted
- * @return Optional.empty if no collection method has been persisted for the tenant
- */
- Optional<CollectionMethod> getCollectionMethod(TenantName tenantName);
-
- /**
- * Set the collection method for the tenant
- * @param tenantName The name of the tenant to set collection method for
- * @param collectionMethod The collection method for the tenant
- */
- void setCollectionMethod(TenantName tenantName, CollectionMethod collectionMethod);
-}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillingDatabaseClientMock.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillingDatabaseClientMock.java
deleted file mode 100644
index f53025a2e6d..00000000000
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillingDatabaseClientMock.java
+++ /dev/null
@@ -1,178 +0,0 @@
-// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.hosted.controller.api.integration.billing;
-
-import com.yahoo.config.provision.TenantName;
-
-import java.time.Clock;
-import java.time.LocalDate;
-import java.time.ZoneId;
-import java.time.ZonedDateTime;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.UUID;
-import java.util.stream.Collectors;
-
-/**
- * @author olaa
- */
-public class BillingDatabaseClientMock implements BillingDatabaseClient {
- private final Clock clock;
- private final PlanRegistry planRegistry;
- private final Map<TenantName, Plan> tenantPlans = new HashMap<>();
- private final Map<Bill.Id, TenantName> invoices = new HashMap<>();
- private final Map<Bill.Id, List<Bill.LineItem>> lineItems = new HashMap<>();
- private final Map<TenantName, List<Bill.LineItem>> uncommittedLineItems = new HashMap<>();
-
- private final Map<Bill.Id, Bill.StatusHistory> statuses = new HashMap<>();
- private final Map<Bill.Id, ZonedDateTime> startTimes = new HashMap<>();
- private final Map<Bill.Id, ZonedDateTime> endTimes = new HashMap<>();
-
- private final ZonedDateTime startTime = LocalDate.of(2020, 4, 1).atStartOfDay(ZoneId.of("UTC"));
- private final ZonedDateTime endTime = LocalDate.of(2020, 5, 1).atStartOfDay(ZoneId.of("UTC"));
-
- private final List<InstrumentOwner> paymentInstruments = new ArrayList<>();
- private final Map<TenantName, CollectionMethod> collectionMethods = new HashMap<>();
-
- public BillingDatabaseClientMock(Clock clock, PlanRegistry planRegistry) {
- this.clock = clock;
- this.planRegistry = planRegistry;
- }
-
- @Override
- public boolean setActivePaymentInstrument(InstrumentOwner paymentInstrument) {
- return paymentInstruments.add(paymentInstrument);
- }
-
- @Override
- public Optional<InstrumentOwner> getDefaultPaymentInstrumentForTenant(TenantName tenantName) {
- return paymentInstruments.stream()
- .filter(paymentInstrument -> paymentInstrument.getTenantName().equals(tenantName))
- .findFirst();
- }
-
- public String getStatus(Bill.Id invoiceId) {
- return statuses.get(invoiceId).current();
- }
-
- @Override
- public Bill.Id createBill(TenantName tenant, ZonedDateTime startTime, ZonedDateTime endTime, String agent) {
- var invoiceId = Bill.Id.generate();
- invoices.put(invoiceId, tenant);
- statuses.computeIfAbsent(invoiceId, l -> Bill.StatusHistory.open(clock));
- startTimes.put(invoiceId, startTime);
- endTimes.put(invoiceId, endTime);
- return invoiceId;
- }
-
- @Override
- public Optional<Bill> readBill(Bill.Id billId) {
- var invoice = Optional.ofNullable(invoices.get(billId));
- var lines = lineItems.getOrDefault(billId, List.of());
- var status = statuses.getOrDefault(billId, Bill.StatusHistory.open(clock));
- var start = startTimes.getOrDefault(billId, startTime);
- var end = endTimes.getOrDefault(billId, endTime);
- return invoice.map(tenant -> new Bill(billId, tenant, status, lines, start, end));
- }
-
- @Override
- public String addLineItem(TenantName tenantName, Bill.LineItem lineItem, Optional<Bill.Id> invoiceId) {
- var lineItemId = UUID.randomUUID().toString();
- invoiceId.ifPresentOrElse(
- invoice -> lineItems.computeIfAbsent(invoice, l -> new ArrayList<>()).add(lineItem),
- () -> uncommittedLineItems.computeIfAbsent(tenantName, l -> new ArrayList<>()).add(lineItem)
- );
- return lineItemId;
- }
-
- @Override
- public void setStatus(Bill.Id invoiceId, String agent, String status) {
- statuses.computeIfAbsent(invoiceId, k -> Bill.StatusHistory.open(clock))
- .getHistory()
- .put(ZonedDateTime.now(), status);
- }
-
- @Override
- public List<Bill.LineItem> getUnusedLineItems(TenantName tenantName) {
- return uncommittedLineItems.getOrDefault(tenantName, new ArrayList<>());
- }
-
- @Override
- public void deleteLineItem(String lineItemId) {
- uncommittedLineItems.values()
- .forEach(list ->
- list.removeIf(lineItem -> lineItem.id().equals(lineItemId))
- );
- }
-
- @Override
- public void commitLineItems(TenantName tenantName, Bill.Id invoiceId) {
-
- }
-
- @Override
- public Optional<Plan> getPlan(TenantName tenantName) {
- return Optional.ofNullable(tenantPlans.get(tenantName));
- }
-
- @Override
- public Map<TenantName, Optional<Plan>> getPlans(List<TenantName> tenants) {
- return tenantPlans.entrySet().stream()
- .filter(entry -> tenants.contains(entry.getKey()))
- .collect(Collectors.toMap(
- entry -> entry.getKey(),
- entry -> planRegistry.plan(entry.getValue().id())
- ));
- }
-
- @Override
- public void setPlan(TenantName tenantName, Plan plan) {
- tenantPlans.put(tenantName, plan);
- }
-
- @Override
- public void deactivateDefaultPaymentInstrument(TenantName tenant) {
- paymentInstruments.removeIf(instrumentOwner -> instrumentOwner.getTenantName().equals(tenant));
- }
-
- @Override
- public Optional<CollectionMethod> getCollectionMethod(TenantName tenantName) {
- return Optional.ofNullable(collectionMethods.get(tenantName));
- }
-
- @Override
- public void setCollectionMethod(TenantName tenantName, CollectionMethod collectionMethod) {
- collectionMethods.put(tenantName, collectionMethod);
- }
-
- @Override
- public List<Bill> readBillsForTenant(TenantName tenant) {
- return invoices.entrySet().stream()
- .filter(entry -> entry.getValue().equals(tenant))
- .map(Map.Entry::getKey)
- .map(invoiceId -> {
- var items = lineItems.getOrDefault(invoiceId, List.of());
- var status = statuses.get(invoiceId);
- var start = startTimes.get(invoiceId);
- var end = endTimes.get(invoiceId);
- return new Bill(invoiceId, tenant, status, items, start, end);
- })
- .collect(Collectors.toList());
- }
-
- @Override
- public List<Bill> readBills() {
- return invoices.keySet().stream()
- .map(invoiceId -> {
- var tenant = invoices.get(invoiceId);
- var items = lineItems.getOrDefault(invoiceId, List.of());
- var status = statuses.get(invoiceId);
- var start = startTimes.get(invoiceId);
- var end = endTimes.get(invoiceId);
- return new Bill(invoiceId, tenant, status, items, start, end);
- })
- .collect(Collectors.toList());
- }
-}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/Bill.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/Invoice.java
index d1af5b428de..3789021ae8e 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/Bill.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/Invoice.java
@@ -20,18 +20,18 @@ import java.util.function.Function;
/**
- * An Bill is an identifier with a status (with history) and line items. A line item is the meat and
- * potatoes of the content of the bill, and are a history of items. Most line items are connected to
+ * An Invoice is an identifier with a status (with history) and line items. A line item is the meat and
+ * potatoes of the content of the invoice, and are a history of items. Most line items are connected to
* a given deployment in Vespa Cloud, but they can also be manually added to e.g. give a discount or represent
* support.
* <p>
* All line items have a Plan associated with them - which was used to map from utilization to an actual price.
* <p>
- * The bill has a status history, but only the latest status is exposed through this API.
+ * The invoice has a status history, but only the latest status is exposed through this API.
*
* @author ogronnesby
*/
-public class Bill {
+public class Invoice {
private static final BigDecimal SCALED_ZERO = new BigDecimal("0.00");
private final Id id;
@@ -41,7 +41,7 @@ public class Bill {
private final ZonedDateTime startTime;
private final ZonedDateTime endTime;
- public Bill(Id id, TenantName tenant, StatusHistory statusHistory, List<LineItem> lineItems, ZonedDateTime startTime, ZonedDateTime endTime) {
+ public Invoice(Id id, TenantName tenant, StatusHistory statusHistory, List<LineItem> lineItems, ZonedDateTime startTime, ZonedDateTime endTime) {
this.id = id;
this.tenant = tenant;
this.lineItems = List.copyOf(lineItems);
@@ -141,8 +141,8 @@ public class Bill {
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
- Id billId = (Id) o;
- return value.equals(billId.value);
+ Id invoiceId = (Id) o;
+ return value.equals(invoiceId.value);
}
@Override
@@ -152,14 +152,14 @@ public class Bill {
@Override
public String toString() {
- return "BillId{" +
+ return "InvoiceId{" +
"value='" + value + '\'' +
'}';
}
}
/**
- * Represents a chargeable line on a bill.
+ * Represents a chargeable line on an invoice.
*/
public static class LineItem {
private final String id;
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 f4d3577aeec..8816c4eb57b 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
@@ -26,9 +26,9 @@ public class MockBillingController implements BillingController {
private final Clock clock;
Map<TenantName, PlanId> plans = new HashMap<>();
Map<TenantName, PaymentInstrument> activeInstruments = new HashMap<>();
- Map<TenantName, List<Bill>> committedBills = new HashMap<>();
- Map<TenantName, Bill> uncommittedBills = new HashMap<>();
- Map<TenantName, List<Bill.LineItem>> unusedLineItems = new HashMap<>();
+ Map<TenantName, List<Invoice>> committedInvoices = new HashMap<>();
+ Map<TenantName, Invoice> uncommittedInvoices = new HashMap<>();
+ Map<TenantName, List<Invoice.LineItem>> unusedLineItems = new HashMap<>();
Map<TenantName, CollectionMethod> collectionMethod = new HashMap<>();
public MockBillingController(Clock clock) {
@@ -64,32 +64,32 @@ public class MockBillingController implements BillingController {
}
@Override
- public Bill.Id createBillForPeriod(TenantName tenant, ZonedDateTime startTime, ZonedDateTime endTime, String agent) {
- var billId = Bill.Id.of("id-123");
- committedBills.computeIfAbsent(tenant, l -> new ArrayList<>())
- .add(new Bill(
- billId,
+ public Invoice.Id createInvoiceForPeriod(TenantName tenant, ZonedDateTime startTime, ZonedDateTime endTime, String agent) {
+ var invoiceId = Invoice.Id.of("id-123");
+ committedInvoices.computeIfAbsent(tenant, l -> new ArrayList<>())
+ .add(new Invoice(
+ invoiceId,
tenant,
- Bill.StatusHistory.open(clock),
+ Invoice.StatusHistory.open(clock),
List.of(),
startTime,
endTime
));
- return billId;
+ return invoiceId;
}
@Override
- public Bill createUncommittedBill(TenantName tenant, LocalDate until) {
- return uncommittedBills.getOrDefault(tenant, emptyBill());
+ public Invoice createUncommittedInvoice(TenantName tenant, LocalDate until) {
+ return uncommittedInvoices.getOrDefault(tenant, emptyInvoice());
}
@Override
- public Map<TenantName, Bill> createUncommittedBills(LocalDate until) {
- return uncommittedBills;
+ public Map<TenantName, Invoice> createUncommittedInvoices(LocalDate until) {
+ return uncommittedInvoices;
}
@Override
- public List<Bill.LineItem> getUnusedLineItems(TenantName tenant) {
+ public List<Invoice.LineItem> getUnusedLineItems(TenantName tenant) {
return unusedLineItems.getOrDefault(tenant, List.of());
}
@@ -110,18 +110,18 @@ public class MockBillingController implements BillingController {
}
@Override
- public void updateBillStatus(Bill.Id billId, String agent, String status) {
+ public void updateInvoiceStatus(Invoice.Id invoiceId, String agent, String status) {
var now = clock.instant().atZone(ZoneOffset.UTC);
- committedBills.values().stream()
+ committedInvoices.values().stream()
.flatMap(List::stream)
- .filter(bill -> billId.equals(bill.id()))
- .forEach(bill -> bill.statusHistory().history.put(now, status));
+ .filter(invoice -> invoiceId.equals(invoice.id()))
+ .forEach(invoice -> invoice.statusHistory().history.put(now, status));
}
@Override
public void addLineItem(TenantName tenant, String description, BigDecimal amount, String agent) {
unusedLineItems.computeIfAbsent(tenant, l -> new ArrayList<>())
- .add(new Bill.LineItem(
+ .add(new Invoice.LineItem(
"line-item-id",
description,
amount,
@@ -152,13 +152,13 @@ public class MockBillingController implements BillingController {
}
@Override
- public List<Bill> getBillsForTenant(TenantName tenant) {
- return committedBills.getOrDefault(tenant, List.of());
+ public List<Invoice> getInvoicesForTenant(TenantName tenant) {
+ return committedInvoices.getOrDefault(tenant, List.of());
}
@Override
- public List<Bill> getBills() {
- return committedBills.values().stream().flatMap(Collection::stream).collect(Collectors.toList());
+ public List<Invoice> getInvoices() {
+ return committedInvoices.values().stream().flatMap(Collection::stream).collect(Collectors.toList());
}
@Override
@@ -191,17 +191,17 @@ public class MockBillingController implements BillingController {
"country");
}
- public void addBill(TenantName tenantName, Bill bill, boolean committed) {
+ public void addInvoice(TenantName tenantName, Invoice invoice, boolean committed) {
if (committed)
- committedBills.computeIfAbsent(tenantName, i -> new ArrayList<>())
- .add(bill);
+ committedInvoices.computeIfAbsent(tenantName, i -> new ArrayList<>())
+ .add(invoice);
else
- uncommittedBills.put(tenantName, bill);
+ uncommittedInvoices.put(tenantName, invoice);
}
- private Bill emptyBill() {
+ private Invoice emptyInvoice() {
var start = clock.instant().atZone(ZoneOffset.UTC);
var end = clock.instant().atZone(ZoneOffset.UTC);
- return new Bill(Bill.Id.of("empty"), TenantName.defaultName(), Bill.StatusHistory.open(clock), List.of(), start, end);
+ return new Invoice(Invoice.Id.of("empty"), TenantName.defaultName(), Invoice.StatusHistory.open(clock), List.of(), start, end);
}
}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/PlanRegistry.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/PlanRegistry.java
deleted file mode 100644
index d64d6e3ea04..00000000000
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/PlanRegistry.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.yahoo.vespa.hosted.controller.api.integration.billing;
-
-import java.util.Optional;
-
-/**
- * Registry of all current plans we have support for
- *
- * @author ogronnesby
- */
-public interface PlanRegistry {
-
- /** Get the default plan */
- Plan defaultPlan();
-
- /** Get a plan given a plan ID */
- Optional<Plan> plan(PlanId planId);
-
- /** Get a plan give a plan ID */
- default Optional<Plan> plan(String planId) {
- return plan(PlanId.from(planId));
- }
-
-}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/PlanRegistryMock.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/PlanRegistryMock.java
deleted file mode 100644
index 60eddbd24ff..00000000000
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/PlanRegistryMock.java
+++ /dev/null
@@ -1,122 +0,0 @@
-package com.yahoo.vespa.hosted.controller.api.integration.billing;
-
-import com.yahoo.config.provision.NodeResources;
-import com.yahoo.vespa.hosted.controller.api.integration.resource.CostInfo;
-import com.yahoo.vespa.hosted.controller.api.integration.resource.ResourceUsage;
-
-import java.math.BigDecimal;
-import java.math.RoundingMode;
-import java.util.Optional;
-import java.util.stream.Stream;
-
-public class PlanRegistryMock implements PlanRegistry {
-
- public static final Plan freeTrial = new MockPlan("trial", false, 0, 0, 0, 200, "Free Trial - for testing purposes");
- public static final Plan paidPlan = new MockPlan("paid", true, "0.09", "0.009", "0.0003", 500, "Paid Plan - for testing purposes");
- public static final Plan nonePlan = new MockPlan("none", false, 0, 0, 0, 0, "None Plan - for testing purposes");
-
- @Override
- public Plan defaultPlan() {
- return freeTrial;
- }
-
- @Override
- public Optional<Plan> plan(PlanId planId) {
- return Stream.of(freeTrial, paidPlan, nonePlan)
- .filter(p -> p.id().equals(planId))
- .findAny();
- }
-
- private static class MockPlan implements Plan {
- private final PlanId planId;
- private final String description;
- private final CostCalculator costCalculator;
- private final QuotaCalculator quotaCalculator;
- private final boolean billed;
-
- public MockPlan(String planId, boolean billed, double cpuPrice, double memPrice, double dgbPrice, int quota, String description) {
- this(PlanId.from(planId), billed, new MockCostCalculator(cpuPrice, memPrice, dgbPrice), () -> Quota.unlimited().withBudget(quota), description);
- }
-
- public MockPlan(String planId, boolean billed, String cpuPrice, String memPrice, String dgbPrice, int quota, String description) {
- this(PlanId.from(planId), billed, new MockCostCalculator(cpuPrice, memPrice, dgbPrice), () -> Quota.unlimited().withBudget(quota), description);
- }
-
- public MockPlan(PlanId planId, boolean billed, MockCostCalculator calculator, QuotaCalculator quota, String description) {
- this.planId = planId;
- this.billed = billed;
- this.costCalculator = calculator;
- this.quotaCalculator = quota;
- this.description = description;
- }
-
- @Override
- public PlanId id() {
- return planId;
- }
-
- @Override
- public String displayName() {
- return description;
- }
-
- @Override
- public CostCalculator calculator() {
- return costCalculator;
- }
-
- @Override
- public QuotaCalculator quota() {
- return quotaCalculator;
- }
-
- @Override
- public boolean isBilled() {
- return billed;
- }
- }
-
- private static class MockCostCalculator implements CostCalculator {
- private static final BigDecimal millisPerHour = BigDecimal.valueOf(60 * 60 * 1000);
- private final BigDecimal cpuHourCost;
- private final BigDecimal memHourCost;
- private final BigDecimal dgbHourCost;
-
- public MockCostCalculator(String cpuPrice, String memPrice, String dgbPrice) {
- this(new BigDecimal(cpuPrice), new BigDecimal(memPrice), new BigDecimal(dgbPrice));
- }
-
- public MockCostCalculator(double cpuPrice, double memPrice, double dgbPrice) {
- this(BigDecimal.valueOf(cpuPrice), BigDecimal.valueOf(memPrice), BigDecimal.valueOf(dgbPrice));
- }
-
- public MockCostCalculator(BigDecimal cpuPrice, BigDecimal memPrice, BigDecimal dgbPrice) {
- this.cpuHourCost = cpuPrice;
- this.memHourCost = memPrice;
- this.dgbHourCost = dgbPrice;
- }
-
- @Override
- public CostInfo calculate(ResourceUsage usage) {
- var cpuCost = usage.getCpuMillis().multiply(cpuHourCost).divide(millisPerHour, RoundingMode.HALF_UP).setScale(2, RoundingMode.HALF_UP);
- var memCost = usage.getMemoryMillis().multiply(memHourCost).divide(millisPerHour, RoundingMode.HALF_UP).setScale(2, RoundingMode.HALF_UP);
- var dgbCost = usage.getDiskMillis().multiply(dgbHourCost).divide(millisPerHour, RoundingMode.HALF_UP).setScale(2, RoundingMode.HALF_UP);
-
- return new CostInfo(
- usage.getApplicationId(),
- usage.getZoneId(),
- usage.getCpuMillis().divide(millisPerHour, RoundingMode.HALF_UP),
- usage.getMemoryMillis().divide(millisPerHour, RoundingMode.HALF_UP),
- usage.getDiskMillis().divide(millisPerHour, RoundingMode.HALF_UP),
- cpuCost,
- memCost,
- dgbCost
- );
- }
-
- @Override
- public double calculate(NodeResources resources) {
- return resources.cost();
- }
- }
-}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/resource/ResourceDatabaseClient.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/resource/ResourceDatabaseClient.java
deleted file mode 100644
index 2f277193231..00000000000
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/resource/ResourceDatabaseClient.java
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.hosted.controller.api.integration.resource;
-
-import com.yahoo.config.provision.ApplicationName;
-import com.yahoo.config.provision.TenantName;
-
-import java.time.LocalDate;
-import java.time.YearMonth;
-import java.time.temporal.ChronoUnit;
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
-
-/**
- * @author olaa
- */
-public interface ResourceDatabaseClient {
-
- void writeResourceSnapshots(Collection<ResourceSnapshot> snapshots);
-
- List<ResourceSnapshot> getResourceSnapshotsForMonth(TenantName tenantName, ApplicationName applicationName, YearMonth month);
-
- List<ResourceUsage> getResourceSnapshotsForPeriod(TenantName tenantName, long startTimestamp, long endTimestamp);
-
- void refreshMaterializedView();
-
- Set<YearMonth> getMonthsWithSnapshotsForTenant(TenantName tenantName);
-
- List<ResourceSnapshot> getRawSnapshotHistoryForTenant(TenantName tenantName, YearMonth yearMonth);
-
- Set<TenantName> getTenants();
-
- default List<ResourceUsage> getResourceSnapshotsForMonth(TenantName tenantName, YearMonth month) {
- return getResourceSnapshotsForPeriod(tenantName, getMonthStartTimeStamp(month), getMonthEndTimeStamp(month));
- }
-
- private long getMonthStartTimeStamp(YearMonth month) {
- LocalDate startOfMonth = LocalDate.of(month.getYear(), month.getMonth(), 1);
- return startOfMonth.atStartOfDay(java.time.ZoneId.of("UTC"))
- .toInstant()
- .toEpochMilli();
- }
- private long getMonthEndTimeStamp(YearMonth month) {
- LocalDate startOfMonth = LocalDate.of(month.getYear(), month.getMonth(), 1);
- return startOfMonth.plus(1, ChronoUnit.MONTHS)
- .atStartOfDay(java.time.ZoneId.of("UTC"))
- .toInstant()
- .toEpochMilli();
- }
-
-}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/resource/ResourceDatabaseClientMock.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/resource/ResourceDatabaseClientMock.java
deleted file mode 100644
index 5a4d250ea9d..00000000000
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/resource/ResourceDatabaseClientMock.java
+++ /dev/null
@@ -1,146 +0,0 @@
-// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.hosted.controller.api.integration.resource;
-
-import com.yahoo.config.provision.ApplicationName;
-import com.yahoo.config.provision.TenantName;
-import com.yahoo.vespa.hosted.controller.api.integration.billing.Plan;
-import com.yahoo.vespa.hosted.controller.api.integration.billing.PlanRegistry;
-
-import java.math.BigDecimal;
-import java.time.Duration;
-import java.time.Instant;
-import java.time.LocalDate;
-import java.time.YearMonth;
-import java.time.ZoneId;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Collectors;
-import java.util.stream.IntStream;
-
-/**
- * @author olaa
- */
-public class ResourceDatabaseClientMock implements ResourceDatabaseClient {
-
- PlanRegistry planRegistry;
- Map<TenantName, Plan> planMap = new HashMap<>();
- List<ResourceSnapshot> resourceSnapshots = new ArrayList<>();
- private boolean hasRefreshedMaterializedView = false;
-
- public ResourceDatabaseClientMock(PlanRegistry planRegistry) {
- this.planRegistry = planRegistry;
- }
-
- @Override
- public void writeResourceSnapshots(Collection<ResourceSnapshot> items) {
- this.resourceSnapshots.addAll(items);
- }
-
- @Override
- public List<ResourceSnapshot> getResourceSnapshotsForMonth(TenantName tenantName, ApplicationName applicationName, YearMonth month) {
- return resourceSnapshots.stream()
- .filter(resourceSnapshot -> {
- LocalDate snapshotDate = LocalDate.ofInstant(resourceSnapshot.getTimestamp(), ZoneId.of("UTC"));
- return YearMonth.from(snapshotDate).equals(month) &&
- snapshotDate.getYear() == month.getYear() &&
- resourceSnapshot.getApplicationId().tenant().equals(tenantName) &&
- resourceSnapshot.getApplicationId().application().equals(applicationName);
- })
- .collect(Collectors.toList());
- }
-
- @Override
- public Set<YearMonth> getMonthsWithSnapshotsForTenant(TenantName tenantName) {
- return Collections.emptySet();
- }
-
- @Override
- public List<ResourceSnapshot> getRawSnapshotHistoryForTenant(TenantName tenantName, YearMonth yearMonth) {
- return resourceSnapshots;
- }
-
- @Override
- public Set<TenantName> getTenants() {
- return resourceSnapshots.stream()
- .map(snapshot -> snapshot.getApplicationId().tenant())
- .collect(Collectors.toSet());
- }
-
- private List<ResourceUsage> resourceUsageFromSnapshots(Plan plan, List<ResourceSnapshot> snapshots) {
- snapshots.sort(Comparator.comparing(ResourceSnapshot::getTimestamp));
-
- return IntStream.range(0, snapshots.size())
- .mapToObj(idx -> {
- var a = snapshots.get(idx);
- var b = (idx + 1) < snapshots.size() ? snapshots.get(idx + 1) : null;
- var start = a.getTimestamp();
- var end = Optional.ofNullable(b).map(ResourceSnapshot::getTimestamp).orElse(start.plusSeconds(120));
- var d = BigDecimal.valueOf(Duration.between(start, end).toMillis());
- return new ResourceUsage(
- a.getApplicationId(),
- a.getZoneId(),
- plan,
- BigDecimal.valueOf(a.getCpuCores()).multiply(d),
- BigDecimal.valueOf(a.getMemoryGb()).multiply(d),
- BigDecimal.valueOf(a.getDiskGb()).multiply(d)
- );
- })
- .collect(Collectors.toList());
- }
-
- private ResourceUsage resourceUsageAdd(ResourceUsage a, ResourceUsage b) {
- assert a.getApplicationId().equals(b.getApplicationId());
- assert a.getZoneId().equals(b.getZoneId());
- assert a.getPlan().equals(b.getPlan());
- return new ResourceUsage(
- a.getApplicationId(),
- a.getZoneId(),
- a.getPlan(),
- a.getCpuMillis().add(b.getCpuMillis()),
- a.getMemoryMillis().add(b.getMemoryMillis()),
- a.getDiskMillis().add(b.getDiskMillis())
- );
- }
-
- @Override
- public List<ResourceUsage> getResourceSnapshotsForPeriod(TenantName tenantName, long start, long end) {
- var tenantPlan = planMap.getOrDefault(tenantName, planRegistry.defaultPlan());
-
- var snapshotsPerDeployment = resourceSnapshots.stream()
- .filter(snapshot -> snapshot.getTimestamp().isAfter(Instant.ofEpochMilli(start)))
- .filter(snapshot -> snapshot.getTimestamp().isBefore(Instant.ofEpochMilli(end)))
- .filter(snapshot -> snapshot.getApplicationId().tenant().equals(tenantName))
- .collect(Collectors.groupingBy(
- usage -> Objects.hash(usage.getApplicationId(), usage.getZoneId(), tenantPlan.id().value())
- ))
- .values().stream()
- .map(snapshots -> resourceUsageFromSnapshots(tenantPlan, snapshots))
- .map(usages -> usages.stream().reduce(this::resourceUsageAdd))
- .filter(Optional::isPresent)
- .map(Optional::get)
- .collect(Collectors.toList());
-
- return snapshotsPerDeployment;
- }
-
- @Override
- public void refreshMaterializedView() {
- hasRefreshedMaterializedView = true;
- }
-
- public void setPlan(TenantName tenant, Plan plan) {
- planMap.put(tenant, plan);
- }
-
- public boolean hasRefreshedMaterializedView() {
- return hasRefreshedMaterializedView;
- }
-}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/resource/ResourceSnapshot.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/resource/ResourceSnapshot.java
index 319b9239ae4..a8d9c4b1f8a 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/resource/ResourceSnapshot.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/resource/ResourceSnapshot.java
@@ -31,10 +31,6 @@ public class ResourceSnapshot {
this.zoneId = zoneId;
}
- public static ResourceSnapshot from(ApplicationId applicationId, int nodes, double cpuCores, double memoryGb, double diskGb, Instant timestamp, ZoneId zoneId) {
- return new ResourceSnapshot(applicationId, cpuCores * nodes, memoryGb * nodes, diskGb * nodes, timestamp, zoneId);
- }
-
public static ResourceSnapshot from(List<Node> nodes, Instant timestamp, ZoneId zoneId) {
Set<ApplicationId> applicationIds = nodes.stream()
.filter(node -> node.owner().isPresent())
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandler.java
index b8c8ce4e63a..b595d3fbe17 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandler.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandler.java
@@ -18,9 +18,9 @@ import com.yahoo.slime.SlimeUtils;
import com.yahoo.vespa.hosted.controller.ApplicationController;
import com.yahoo.vespa.hosted.controller.Controller;
import com.yahoo.vespa.hosted.controller.TenantController;
-import com.yahoo.vespa.hosted.controller.api.integration.billing.Bill;
import com.yahoo.vespa.hosted.controller.api.integration.billing.CollectionMethod;
import com.yahoo.vespa.hosted.controller.api.integration.billing.PaymentInstrument;
+import com.yahoo.vespa.hosted.controller.api.integration.billing.Invoice;
import com.yahoo.vespa.hosted.controller.api.integration.billing.InstrumentOwner;
import com.yahoo.vespa.hosted.controller.api.integration.billing.BillingController;
import com.yahoo.vespa.hosted.controller.api.integration.billing.PlanId;
@@ -99,23 +99,23 @@ public class BillingApiHandler extends LoggingRequestHandler {
if (path.matches("/billing/v1/tenant/{tenant}/billing")) return getBilling(path.get("tenant"), request.getProperty("until"));
if (path.matches("/billing/v1/tenant/{tenant}/plan")) return getPlan(path.get("tenant"));
if (path.matches("/billing/v1/billing")) return getBillingAllTenants(request.getProperty("until"));
- if (path.matches("/billing/v1/invoice/export")) return getAllBills();
+ if (path.matches("/billing/v1/invoice/export")) return getAllInvoices();
if (path.matches("/billing/v1/invoice/tenant/{tenant}/line-item")) return getLineItems(path.get("tenant"));
return ErrorResponse.notFoundError("Nothing at " + path);
}
- private HttpResponse getAllBills() {
- var bills = billingController.getBills();
+ private HttpResponse getAllInvoices() {
+ var invoices = billingController.getInvoices();
var headers = new String[]{ "ID", "Tenant", "From", "To", "CpuHours", "MemoryHours", "DiskHours", "Cpu", "Memory", "Disk", "Additional" };
- var rows = bills.stream()
- .map(bill -> {
+ var rows = invoices.stream()
+ .map(invoice -> {
return new Object[] {
- bill.id().value(), bill.tenant().value(),
- bill.getStartTime().format(DateTimeFormatter.ISO_LOCAL_DATE),
- bill.getEndTime().format(DateTimeFormatter.ISO_LOCAL_DATE),
- bill.sumCpuHours(), bill.sumMemoryHours(), bill.sumDiskHours(),
- bill.sumCpuCost(), bill.sumMemoryCost(), bill.sumDiskCost(),
- bill.sumAdditionalCost()
+ invoice.id().value(), invoice.tenant().value(),
+ invoice.getStartTime().format(DateTimeFormatter.ISO_LOCAL_DATE),
+ invoice.getEndTime().format(DateTimeFormatter.ISO_LOCAL_DATE),
+ invoice.sumCpuHours(), invoice.sumMemoryHours(), invoice.sumDiskHours(),
+ invoice.sumCpuCost(), invoice.sumMemoryCost(), invoice.sumDiskCost(),
+ invoice.sumAdditionalCost()
};
})
.collect(Collectors.toList());
@@ -138,8 +138,8 @@ public class BillingApiHandler extends LoggingRequestHandler {
}
private HttpResponse handlePOST(Path path, HttpRequest request, String userId) {
- if (path.matches("/billing/v1/invoice")) return createBill(request, userId);
- if (path.matches("/billing/v1/invoice/{invoice-id}/status")) return setBillStatus(request, path.get("invoice-id"));
+ if (path.matches("/billing/v1/invoice")) return createInvoice(request, userId);
+ if (path.matches("/billing/v1/invoice/{invoice-id}/status")) return setInvoiceStatus(request, path.get("invoice-id"));
if (path.matches("/billing/v1/invoice/tenant/{tenant}/line-item")) return addLineItem(request, path.get("tenant"));
return ErrorResponse.notFoundError("Nothing at " + path);
@@ -190,7 +190,7 @@ public class BillingApiHandler extends LoggingRequestHandler {
private HttpResponse getBillingAllTenants(String until) {
try {
var untilDate = untilParameter(until);
- var uncommittedBills = billingController.createUncommittedBills(untilDate);
+ var uncommittedInvoices = billingController.createUncommittedInvoices(untilDate);
var slime = new Slime();
var root = slime.setObject();
@@ -198,12 +198,12 @@ public class BillingApiHandler extends LoggingRequestHandler {
var tenants = root.setArray("tenants");
tenantController.asList().stream().sorted(Comparator.comparing(Tenant::name)).forEach(tenant -> {
- var bill = uncommittedBills.get(tenant.name());
+ var invoice = uncommittedInvoices.get(tenant.name());
var tc = tenants.addObject();
tc.setString("tenant", tenant.name().value());
getPlanForTenant(tc, tenant.name());
getCollectionForTenant(tc, tenant.name());
- renderCurrentUsage(tc.setObject("current"), bill);
+ renderCurrentUsage(tc.setObject("current"), invoice);
renderAdditionalItems(tc.setObject("additional").setArray("items"), billingController.getUnusedLineItems(tenant.name()));
billingController.getDefaultInstrument(tenant.name()).ifPresent(card ->
@@ -232,14 +232,14 @@ public class BillingApiHandler extends LoggingRequestHandler {
return new MessageResponse("Added line item for tenant " + tenant);
}
- private HttpResponse setBillStatus(HttpRequest request, String billId) {
+ private HttpResponse setInvoiceStatus(HttpRequest request, String invoiceId) {
Inspector inspector = inspectorOrThrow(request);
String status = getInspectorFieldOrThrow(inspector, "status");
- billingController.updateBillStatus(Bill.Id.of(billId), userIdOrThrow(request), status);
- return new MessageResponse("Updated status of invoice " + billId);
+ billingController.updateInvoiceStatus(Invoice.Id.of(invoiceId), userIdOrThrow(request), status);
+ return new MessageResponse("Updated status of invoice " + invoiceId);
}
- private HttpResponse createBill(HttpRequest request, String userId) {
+ private HttpResponse createInvoice(HttpRequest request, String userId) {
Inspector inspector = inspectorOrThrow(request);
TenantName tenantName = TenantName.from(getInspectorFieldOrThrow(inspector, "tenant"));
@@ -248,12 +248,12 @@ public class BillingApiHandler extends LoggingRequestHandler {
ZonedDateTime startTime = startDate.atStartOfDay(ZoneId.of("UTC"));
ZonedDateTime endTime = endDate.atStartOfDay(ZoneId.of("UTC"));
- var billId = billingController.createBillForPeriod(tenantName, startTime, endTime, userId);
+ var invoiceId = billingController.createInvoiceForPeriod(tenantName, startTime, endTime, userId);
Slime slime = new Slime();
Cursor root = slime.setObject();
- root.setString("message", "Created invoice with ID " + billId.value());
- root.setString("id", billId.value());
+ root.setString("message", "Created invoice with ID " + invoiceId.value());
+ root.setString("id", invoiceId.value());
return new SlimeJsonResponse(slime);
}
@@ -278,7 +278,7 @@ public class BillingApiHandler extends LoggingRequestHandler {
getPlanForTenant(root, tenantId);
renderCurrentUsage(root.setObject("current"), getCurrentUsageForTenant(tenantId, untilDate));
renderAdditionalItems(root.setObject("additional").setArray("items"), billingController.getUnusedLineItems(tenantId));
- renderBills(root.setArray("bills"), getBillsForTenant(tenantId));
+ renderInvoices(root.setArray("bills"), getInvoicesForTenant(tenantId));
billingController.getDefaultInstrument(tenantId).ifPresent( card ->
renderInstrument(root.setObject("payment"), card)
@@ -328,7 +328,7 @@ public class BillingApiHandler extends LoggingRequestHandler {
}
- private void renderCurrentUsage(Cursor cursor, Bill currentUsage) {
+ private void renderCurrentUsage(Cursor cursor, Invoice currentUsage) {
if (currentUsage == null) return;
cursor.setString("amount", currentUsage.sum().toPlainString());
cursor.setString("status", "accrued");
@@ -340,46 +340,46 @@ public class BillingApiHandler extends LoggingRequestHandler {
});
}
- private void renderAdditionalItems(Cursor cursor, List<Bill.LineItem> items) {
+ private void renderAdditionalItems(Cursor cursor, List<Invoice.LineItem> items) {
items.forEach(item -> {
renderLineItemToCursor(cursor.addObject(), item);
});
}
- private Bill getCurrentUsageForTenant(TenantName tenant, LocalDate until) {
- return billingController.createUncommittedBill(tenant, until);
+ private Invoice getCurrentUsageForTenant(TenantName tenant, LocalDate until) {
+ return billingController.createUncommittedInvoice(tenant, until);
}
- private List<Bill> getBillsForTenant(TenantName tenant) {
- return billingController.getBillsForTenant(tenant);
+ private List<Invoice> getInvoicesForTenant(TenantName tenant) {
+ return billingController.getInvoicesForTenant(tenant);
}
- private void renderBills(Cursor cursor, List<Bill> bills) {
- bills.forEach(bill -> {
- var billCursor = cursor.addObject();
- renderBillToCursor(billCursor, bill);
+ private void renderInvoices(Cursor cursor, List<Invoice> invoices) {
+ invoices.forEach(invoice -> {
+ var invoiceCursor = cursor.addObject();
+ renderInvoiceToCursor(invoiceCursor, invoice);
});
}
- private void renderBillToCursor(Cursor billCursor, Bill bill) {
- billCursor.setString("id", bill.id().value());
- billCursor.setString("from", bill.getStartTime().format(DATE_TIME_FORMATTER));
- billCursor.setString("to", bill.getEndTime().format(DATE_TIME_FORMATTER));
+ private void renderInvoiceToCursor(Cursor invoiceCursor, Invoice invoice) {
+ invoiceCursor.setString("id", invoice.id().value());
+ invoiceCursor.setString("from", invoice.getStartTime().format(DATE_TIME_FORMATTER));
+ invoiceCursor.setString("to", invoice.getEndTime().format(DATE_TIME_FORMATTER));
- billCursor.setString("amount", bill.sum().toString());
- billCursor.setString("status", bill.status());
- var statusCursor = billCursor.setArray("statusHistory");
- renderStatusHistory(statusCursor, bill.statusHistory());
+ invoiceCursor.setString("amount", invoice.sum().toString());
+ invoiceCursor.setString("status", invoice.status());
+ var statusCursor = invoiceCursor.setArray("statusHistory");
+ renderStatusHistory(statusCursor, invoice.statusHistory());
- var lineItemsCursor = billCursor.setArray("items");
- bill.lineItems().forEach(lineItem -> {
+ var lineItemsCursor = invoiceCursor.setArray("items");
+ invoice.lineItems().forEach(lineItem -> {
var itemCursor = lineItemsCursor.addObject();
renderLineItemToCursor(itemCursor, lineItem);
});
}
- private void renderStatusHistory(Cursor cursor, Bill.StatusHistory statusHistory) {
+ private void renderStatusHistory(Cursor cursor, Invoice.StatusHistory statusHistory) {
statusHistory.getHistory()
.entrySet()
.stream()
@@ -390,7 +390,7 @@ public class BillingApiHandler extends LoggingRequestHandler {
});
}
- private void renderLineItemToCursor(Cursor cursor, Bill.LineItem lineItem) {
+ private void renderLineItemToCursor(Cursor cursor, Invoice.LineItem lineItem) {
cursor.setString("id", lineItem.id());
cursor.setString("description", lineItem.description());
cursor.setString("amount", lineItem.amount().toString());
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 630305b0ab4..58afed4143f 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
@@ -15,9 +15,9 @@ import com.yahoo.slime.Type;
import com.yahoo.vespa.hosted.controller.ApplicationController;
import com.yahoo.vespa.hosted.controller.Controller;
import com.yahoo.vespa.hosted.controller.TenantController;
-import com.yahoo.vespa.hosted.controller.api.integration.billing.Bill;
import com.yahoo.vespa.hosted.controller.api.integration.billing.BillingController;
import com.yahoo.vespa.hosted.controller.api.integration.billing.CollectionMethod;
+import com.yahoo.vespa.hosted.controller.api.integration.billing.Invoice;
import com.yahoo.vespa.hosted.controller.api.integration.billing.PlanId;
import com.yahoo.vespa.hosted.controller.api.role.Role;
import com.yahoo.vespa.hosted.controller.api.role.SecurityContext;
@@ -138,7 +138,7 @@ public class BillingApiHandlerV2 extends RestApiRequestHandler<BillingApiHandler
var tenant = tenants.require(tenantName, CloudTenant.class);
var slime = new Slime();
- invoicesSummaryToSlime(slime.setObject().setArray("invoices"), billing.getBillsForTenant(tenant.name()));
+ invoicesSummaryToSlime(slime.setObject().setArray("invoices"), billing.getInvoicesForTenant(tenant.name()));
return slime;
}
@@ -148,7 +148,7 @@ public class BillingApiHandlerV2 extends RestApiRequestHandler<BillingApiHandler
var invoiceId = requestContext.pathParameters().getStringOrThrow("invoice");
var format = requestContext.queryParameters().getString("format").orElse("json");
- var invoice = billing.getBillsForTenant(tenant.name()).stream()
+ var invoice = billing.getInvoicesForTenant(tenant.name()).stream()
.filter(inv -> inv.id().value().equals(invoiceId))
.findAny()
.orElseThrow(RestApiException.NotFound::new);
@@ -178,7 +178,7 @@ public class BillingApiHandlerV2 extends RestApiRequestHandler<BillingApiHandler
var tenantName = TenantName.from(requestContext.pathParameters().getStringOrThrow("tenant"));
var tenant = tenants.require(tenantName, CloudTenant.class);
var untilAt = untilParameter(requestContext);
- var usage = billing.createUncommittedBill(tenant.name(), untilAt.atZone(ZoneOffset.UTC).toLocalDate());
+ var usage = billing.createUncommittedInvoice(tenant.name(), untilAt.atZone(ZoneOffset.UTC).toLocalDate());
var slime = new Slime();
usageToSlime(slime.setObject(), usage);
@@ -189,7 +189,7 @@ public class BillingApiHandlerV2 extends RestApiRequestHandler<BillingApiHandler
private Slime accountant(RestApi.RequestContext requestContext) {
var untilAt = untilParameter(requestContext);
- var usagePerTenant = billing.createUncommittedBills(untilAt.atZone(ZoneOffset.UTC).toLocalDate());
+ var usagePerTenant = billing.createUncommittedInvoices(untilAt.atZone(ZoneOffset.UTC).toLocalDate());
var response = new Slime();
var tenantsResponse = response.setObject().setArray("tenants");
@@ -199,8 +199,8 @@ public class BillingApiHandlerV2 extends RestApiRequestHandler<BillingApiHandler
tenantResponse.setString("tenant", tenant.name().value());
tenantResponse.setString("plan", billing.getPlan(tenant.name()).value());
tenantResponse.setString("collection", billing.getCollectionMethod(tenant.name()).name());
- tenantResponse.setString("lastBill", usage.map(Bill::getStartTime).map(DateTimeFormatter.ISO_DATE::format).orElse(null));
- tenantResponse.setString("unbilled", usage.map(Bill::sum).map(BigDecimal::toPlainString).orElse("0.00"));
+ tenantResponse.setString("lastBill", usage.map(Invoice::getStartTime).map(DateTimeFormatter.ISO_DATE::format).orElse(null));
+ tenantResponse.setString("unbilled", usage.map(Invoice::sum).map(BigDecimal::toPlainString).orElse("0.00"));
});
return response;
@@ -211,7 +211,7 @@ public class BillingApiHandlerV2 extends RestApiRequestHandler<BillingApiHandler
var tenant = tenants.require(tenantName, CloudTenant.class);
var untilAt = untilParameter(requestContext);
- var usage = billing.createUncommittedBill(tenant.name(), untilAt.atZone(ZoneOffset.UTC).toLocalDate());
+ var usage = billing.createUncommittedInvoice(tenant.name(), untilAt.atZone(ZoneOffset.UTC).toLocalDate());
var slime = new Slime();
toSlime(slime.setObject(), usage);
@@ -230,7 +230,7 @@ public class BillingApiHandlerV2 extends RestApiRequestHandler<BillingApiHandler
var startAt = LocalDate.parse(getInspectorFieldOrThrow(body, "from")).atStartOfDay(ZoneOffset.UTC);
var endAt = LocalDate.parse(getInspectorFieldOrThrow(body, "to")).atStartOfDay(ZoneOffset.UTC);
- var invoiceId = billing.createBillForPeriod(tenant.name(), startAt, endAt, security.principal().getName());
+ var invoiceId = billing.createInvoiceForPeriod(tenant.name(), startAt, endAt, security.principal().getName());
// TODO: Make a redirect to the bill itself
return new MessageResponse("Created bill " + invoiceId.value());
@@ -239,36 +239,36 @@ public class BillingApiHandlerV2 extends RestApiRequestHandler<BillingApiHandler
// --------- INVOICE RENDERING ----------
- private void invoicesSummaryToSlime(Cursor slime, List<Bill> bills) {
- bills.forEach(invoice -> invoiceSummaryToSlime(slime.addObject(), invoice));
+ private void invoicesSummaryToSlime(Cursor slime, List<Invoice> invoices) {
+ invoices.forEach(invoice -> invoiceSummaryToSlime(slime.addObject(), invoice));
}
- private void invoiceSummaryToSlime(Cursor slime, Bill bill) {
- slime.setString("id", bill.id().value());
- slime.setString("from", bill.getStartTime().format(DateTimeFormatter.ISO_LOCAL_DATE));
- slime.setString("to", bill.getStartTime().format(DateTimeFormatter.ISO_LOCAL_DATE));
- slime.setString("total", bill.sum().toString());
- slime.setString("status", bill.status());
+ private void invoiceSummaryToSlime(Cursor slime, Invoice invoice) {
+ slime.setString("id", invoice.id().value());
+ slime.setString("from", invoice.getStartTime().format(DateTimeFormatter.ISO_LOCAL_DATE));
+ slime.setString("to", invoice.getStartTime().format(DateTimeFormatter.ISO_LOCAL_DATE));
+ slime.setString("total", invoice.sum().toString());
+ slime.setString("status", invoice.status());
}
- private void usageToSlime(Cursor slime, Bill bill) {
- slime.setString("from", bill.getStartTime().format(DateTimeFormatter.ISO_LOCAL_DATE));
- slime.setString("to", bill.getStartTime().format(DateTimeFormatter.ISO_LOCAL_DATE));
- slime.setString("total", bill.sum().toString());
- toSlime(slime.setArray("items"), bill.lineItems());
+ private void usageToSlime(Cursor slime, Invoice invoice) {
+ slime.setString("from", invoice.getStartTime().format(DateTimeFormatter.ISO_LOCAL_DATE));
+ slime.setString("to", invoice.getStartTime().format(DateTimeFormatter.ISO_LOCAL_DATE));
+ slime.setString("total", invoice.sum().toString());
+ toSlime(slime.setArray("items"), invoice.lineItems());
}
- private void toSlime(Cursor slime, Bill bill) {
- slime.setString("id", bill.id().value());
- slime.setString("from", bill.getStartTime().format(DateTimeFormatter.ISO_LOCAL_DATE));
- slime.setString("to", bill.getStartTime().format(DateTimeFormatter.ISO_LOCAL_DATE));
- slime.setString("total", bill.sum().toString());
- slime.setString("status", bill.status());
- toSlime(slime.setArray("statusHistory"), bill.statusHistory());
- toSlime(slime.setArray("items"), bill.lineItems());
+ private void toSlime(Cursor slime, Invoice invoice) {
+ slime.setString("id", invoice.id().value());
+ slime.setString("from", invoice.getStartTime().format(DateTimeFormatter.ISO_LOCAL_DATE));
+ slime.setString("to", invoice.getStartTime().format(DateTimeFormatter.ISO_LOCAL_DATE));
+ slime.setString("total", invoice.sum().toString());
+ slime.setString("status", invoice.status());
+ toSlime(slime.setArray("statusHistory"), invoice.statusHistory());
+ toSlime(slime.setArray("items"), invoice.lineItems());
}
- private void toSlime(Cursor slime, Bill.StatusHistory history) {
+ private void toSlime(Cursor slime, Invoice.StatusHistory history) {
history.getHistory().forEach((key, value) -> {
var c = slime.addObject();
c.setString("at", key.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME));
@@ -276,11 +276,11 @@ public class BillingApiHandlerV2 extends RestApiRequestHandler<BillingApiHandler
});
}
- private void toSlime(Cursor slime, List<Bill.LineItem> items) {
+ private void toSlime(Cursor slime, List<Invoice.LineItem> items) {
items.forEach(item -> toSlime(slime.addObject(), item));
}
- private void toSlime(Cursor slime, Bill.LineItem item) {
+ private void toSlime(Cursor slime, Invoice.LineItem item) {
slime.setString("id", item.id());
slime.setString("description", item.description());
slime.setString("amount",item.amount().toString());
@@ -304,14 +304,14 @@ public class BillingApiHandlerV2 extends RestApiRequestHandler<BillingApiHandler
cost.ifPresent(c -> slime.setString("cost", c.toString()));
}
- private List<Object[]> toCsv(Bill bill) {
+ private List<Object[]> toCsv(Invoice invoice) {
return List.<Object[]>of(new Object[]{
- bill.id().value(), bill.tenant().value(),
- bill.getStartTime().format(DateTimeFormatter.ISO_DATE),
- bill.getEndTime().format(DateTimeFormatter.ISO_DATE),
- bill.sumCpuHours(), bill.sumMemoryHours(), bill.sumDiskHours(),
- bill.sumCpuCost(), bill.sumMemoryCost(), bill.sumDiskCost(),
- bill.sumAdditionalCost()
+ invoice.id().value(), invoice.tenant().value(),
+ invoice.getStartTime().format(DateTimeFormatter.ISO_DATE),
+ invoice.getEndTime().format(DateTimeFormatter.ISO_DATE),
+ invoice.sumCpuHours(), invoice.sumMemoryHours(), invoice.sumDiskHours(),
+ invoice.sumCpuCost(), invoice.sumMemoryCost(), invoice.sumDiskCost(),
+ invoice.sumAdditionalCost()
});
}
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 f64c54ff24d..6ddf0ec76ed 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
@@ -17,11 +17,7 @@ import com.yahoo.vespa.hosted.controller.api.integration.aws.MockCloudEventFetch
import com.yahoo.vespa.hosted.controller.api.integration.aws.MockResourceTagger;
import com.yahoo.vespa.hosted.controller.api.integration.aws.ResourceTagger;
import com.yahoo.vespa.hosted.controller.api.integration.billing.BillingController;
-import com.yahoo.vespa.hosted.controller.api.integration.billing.BillingDatabaseClient;
import com.yahoo.vespa.hosted.controller.api.integration.billing.MockBillingController;
-import com.yahoo.vespa.hosted.controller.api.integration.billing.BillingDatabaseClientMock;
-import com.yahoo.vespa.hosted.controller.api.integration.billing.PlanRegistry;
-import com.yahoo.vespa.hosted.controller.api.integration.billing.PlanRegistryMock;
import com.yahoo.vespa.hosted.controller.api.integration.certificates.EndpointCertificateMock;
import com.yahoo.vespa.hosted.controller.api.integration.certificates.EndpointCertificateValidator;
import com.yahoo.vespa.hosted.controller.api.integration.certificates.EndpointCertificateValidatorMock;
@@ -32,8 +28,6 @@ import com.yahoo.vespa.hosted.controller.api.integration.horizon.MockHorizonClie
import com.yahoo.vespa.hosted.controller.api.integration.organization.MockContactRetriever;
import com.yahoo.vespa.hosted.controller.api.integration.organization.MockIssueHandler;
import com.yahoo.vespa.hosted.controller.api.integration.resource.CostReportConsumerMock;
-import com.yahoo.vespa.hosted.controller.api.integration.resource.ResourceDatabaseClientMock;
-import com.yahoo.vespa.hosted.controller.api.integration.resource.ResourceDatabaseClient;
import com.yahoo.vespa.hosted.controller.api.integration.routing.GlobalRoutingService;
import com.yahoo.vespa.hosted.controller.api.integration.routing.MemoryGlobalRoutingService;
import com.yahoo.vespa.hosted.controller.api.integration.secrets.NoopTenantSecretService;
@@ -83,9 +77,6 @@ public class ServiceRegistryMock extends AbstractComponent implements ServiceReg
private final MockChangeRequestClient changeRequestClient = new MockChangeRequestClient();
private final AccessControlService accessControlService = new MockAccessControlService();
private final HorizonClient horizonClient = new MockHorizonClient();
- private final PlanRegistry planRegistry = new PlanRegistryMock();
- private final ResourceDatabaseClient resourceDb = new ResourceDatabaseClientMock(planRegistry);
- private final BillingDatabaseClient billingDb = new BillingDatabaseClientMock(clock, planRegistry);
public ServiceRegistryMock(SystemName system) {
this.zoneRegistryMock = new ZoneRegistryMock(system);
@@ -252,21 +243,6 @@ public class ServiceRegistryMock extends AbstractComponent implements ServiceReg
return horizonClient;
}
- @Override
- public PlanRegistry planRegistry() {
- return planRegistry;
- }
-
- @Override
- public ResourceDatabaseClient resourceDatabase() {
- return resourceDb;
- }
-
- @Override
- public BillingDatabaseClient billingDatabase() {
- return billingDb;
- }
-
public ConfigServerMock configServerMock() {
return configServerMock;
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerTest.java
index 3c4ed8bc8df..8bc32d262f1 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerTest.java
@@ -3,8 +3,8 @@ package com.yahoo.vespa.hosted.controller.restapi.billing;
import com.yahoo.config.provision.SystemName;
import com.yahoo.config.provision.TenantName;
-import com.yahoo.vespa.hosted.controller.api.integration.billing.Bill;
import com.yahoo.vespa.hosted.controller.api.integration.billing.CollectionMethod;
+import com.yahoo.vespa.hosted.controller.api.integration.billing.Invoice;
import com.yahoo.vespa.hosted.controller.api.integration.billing.MockBillingController;
import com.yahoo.vespa.hosted.controller.api.integration.billing.PlanId;
import com.yahoo.vespa.hosted.controller.api.role.Role;
@@ -19,6 +19,7 @@ import org.junit.Test;
import java.io.File;
import java.math.BigDecimal;
import java.time.LocalDate;
+import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.List;
@@ -94,10 +95,10 @@ public class BillingApiHandlerTest extends ControllerContainerCloudTest {
@Test
public void response_list_bills() {
- var bill = createBill();
+ var invoice = createInvoice();
- billingController.addBill(tenant, bill, true);
- billingController.addBill(tenant, bill, false);
+ billingController.addInvoice(tenant, invoice, true);
+ billingController.addInvoice(tenant, invoice, false);
billingController.setPlan(tenant, PlanId.from("some-plan"), true);
var request = request("/billing/v1/tenant/tenant1/billing?until=2020-05-28").roles(tenantRole);
@@ -106,9 +107,9 @@ public class BillingApiHandlerTest extends ControllerContainerCloudTest {
}
@Test
- public void test_bill_creation() {
- var bills = billingController.getBillsForTenant(tenant);
- assertEquals(0, bills.size());
+ public void test_invoice_creation() {
+ var invoices = billingController.getInvoicesForTenant(tenant);
+ assertEquals(0, invoices.size());
String requestBody = "{\"tenant\":\"tenant1\", \"startTime\":\"2020-04-20\", \"endTime\":\"2020-05-20\"}";
var request = request("/billing/v1/invoice", POST)
@@ -119,11 +120,11 @@ public class BillingApiHandlerTest extends ControllerContainerCloudTest {
request.roles(financeAdmin);
tester.assertResponse(request, new File("invoice-creation-response"));
- bills = billingController.getBillsForTenant(tenant);
- assertEquals(1, bills.size());
- Bill bill = bills.get(0);
- assertEquals(bill.getStartTime().toString(), "2020-04-20T00:00Z[UTC]");
- assertEquals(bill.getEndTime().toString(), "2020-05-20T00:00Z[UTC]");
+ invoices = billingController.getInvoicesForTenant(tenant);
+ assertEquals(1, invoices.size());
+ Invoice invoice = invoices.get(0);
+ assertEquals(invoice.getStartTime().toString(), "2020-04-20T00:00Z[UTC]");
+ assertEquals(invoice.getEndTime().toString(), "2020-05-20T00:00Z[UTC]");
}
@Test
@@ -142,7 +143,7 @@ public class BillingApiHandlerTest extends ControllerContainerCloudTest {
var lineItems = billingController.getUnusedLineItems(tenant);
Assert.assertEquals(1, lineItems.size());
- Bill.LineItem lineItem = lineItems.get(0);
+ Invoice.LineItem lineItem = lineItems.get(0);
assertEquals("some description", lineItem.description());
assertEquals(new BigDecimal("123.45"), lineItem.amount());
@@ -154,7 +155,7 @@ public class BillingApiHandlerTest extends ControllerContainerCloudTest {
@Test
public void adding_new_status() {
- billingController.addBill(tenant, createBill(), true);
+ billingController.addInvoice(tenant, createInvoice(), true);
var requestBody = "{\"status\":\"DONE\"}";
var request = request("/billing/v1/invoice/id-1/status", POST)
@@ -162,21 +163,21 @@ public class BillingApiHandlerTest extends ControllerContainerCloudTest {
.roles(financeAdmin);
tester.assertResponse(request, "{\"message\":\"Updated status of invoice id-1\"}");
- var bill = billingController.getBillsForTenant(tenant).get(0);
- assertEquals("DONE", bill.status());
+ var invoice = billingController.getInvoicesForTenant(tenant).get(0);
+ assertEquals("DONE", invoice.status());
}
@Test
- public void list_all_unbilled_items() {
+ public void list_all_uninvoiced_items() {
tester.controller().tenants().create(new CloudTenantSpec(tenant, ""), new Auth0Credentials(() -> "foo", Set.of(Role.hostedOperator())));
tester.controller().tenants().create(new CloudTenantSpec(tenant2, ""), new Auth0Credentials(() -> "foo", Set.of(Role.hostedOperator())));
- var bill = createBill();
+ var invoice = createInvoice();
billingController.setPlan(tenant, PlanId.from("some-plan"), true);
billingController.setPlan(tenant2, PlanId.from("some-plan"), true);
- billingController.addBill(tenant, bill, false);
+ billingController.addInvoice(tenant, invoice, false);
billingController.addLineItem(tenant, "support", new BigDecimal("42"), "Smith");
- billingController.addBill(tenant2, bill, false);
+ billingController.addInvoice(tenant2, invoice, false);
var request = request("/billing/v1/billing?until=2020-05-28").roles(financeAdmin);
@@ -194,8 +195,8 @@ public class BillingApiHandlerTest extends ControllerContainerCloudTest {
@Test
public void csv_export() {
- var bill = createBill();
- billingController.addBill(tenant, bill, true);
+ var invoice = createInvoice();
+ billingController.addInvoice(tenant, invoice, true);
var csvRequest = request("/billing/v1/invoice/export", GET).roles(financeAdmin);
tester.assertResponse(csvRequest.get(), new File("billing-all-invoices"), 200, false);
}
@@ -221,12 +222,12 @@ public class BillingApiHandlerTest extends ControllerContainerCloudTest {
assertEquals(CollectionMethod.INVOICE, billingController.getCollectionMethod(tenant));
}
- static Bill createBill() {
+ static Invoice createInvoice() {
var start = LocalDate.of(2020, 5, 23).atStartOfDay(ZoneOffset.UTC);
var end = start.plusDays(5);
- var statusHistory = new Bill.StatusHistory(new TreeMap<>(Map.of(start, "OPEN")));
- return new Bill(
- Bill.Id.of("id-1"),
+ var statusHistory = new Invoice.StatusHistory(new TreeMap<>(Map.of(start, "OPEN")));
+ return new Invoice(
+ Invoice.Id.of("id-1"),
TenantName.defaultName(),
statusHistory,
List.of(createLineItem(start)),
@@ -235,8 +236,8 @@ public class BillingApiHandlerTest extends ControllerContainerCloudTest {
);
}
- static Bill.LineItem createLineItem(ZonedDateTime addedAt) {
- return new Bill.LineItem(
+ static Invoice.LineItem createLineItem(ZonedDateTime addedAt) {
+ return new Invoice.LineItem(
"some-id",
"description",
new BigDecimal("123.00"),
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 538e568804b..e733f8e27d6 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
@@ -43,7 +43,7 @@ public class BillingApiHandlerV2Test extends ControllerContainerCloudTest {
var clock = (ManualClock) tester.controller().serviceRegistry().clock();
clock.setInstant(Instant.parse("2021-04-13T00:00:00Z"));
billingController = (MockBillingController) tester.serviceRegistry().billingController();
- billingController.addBill(tenant, BillingApiHandlerTest.createBill(), true);
+ billingController.addInvoice(tenant, BillingApiHandlerTest.createInvoice(), true);
}
@Override