aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Musum <musum@yahooinc.com>2023-10-13 15:14:48 +0200
committerHarald Musum <musum@yahooinc.com>2023-10-13 15:14:48 +0200
commit1fe61e8329e25b41576286b24e867f822226c778 (patch)
tree6f293914c7691d74c955616c45ee2dac0dbd13e5
parent4941bdf24e4ab4ac09348f9d50d65bb4d8112c50 (diff)
Remove support for legacy price calculations from API
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/MockPricingController.java20
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/pricing/ApplicationResources.java13
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/pricing/PricingController.java4
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/pricing/PricingInfo.java9
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/pricing/PricingApiHandler.java63
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/pricing/PricingApiHandlerTest.java54
6 files changed, 24 insertions, 139 deletions
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/MockPricingController.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/MockPricingController.java
index 8ea1882bff6..0aa07e93010 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/MockPricingController.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/MockPricingController.java
@@ -1,7 +1,6 @@
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller.api.integration;
-import com.yahoo.config.provision.ClusterResources;
import com.yahoo.vespa.hosted.controller.api.integration.billing.Plan;
import com.yahoo.vespa.hosted.controller.api.integration.pricing.ApplicationResources;
import com.yahoo.vespa.hosted.controller.api.integration.pricing.PriceInformation;
@@ -18,25 +17,6 @@ import static java.math.BigDecimal.valueOf;
public class MockPricingController implements PricingController {
- // TODO: Remove when not in use anymore
- @Override
- public PriceInformation price(List<ClusterResources> clusterResources, PricingInfo pricingInfo, Plan plan) {
- BigDecimal listPrice = valueOf(clusterResources.stream()
- .mapToDouble(resources -> resources.nodes() *
- (resources.nodeResources().vcpu() * 1000 +
- resources.nodeResources().memoryGb() * 100 +
- resources.nodeResources().diskGb() * 10))
- .sum());
-
- BigDecimal supportLevelCost = pricingInfo.supportLevel() == BASIC ? new BigDecimal("-160.00") : new BigDecimal("800.00");
- BigDecimal listPriceWithSupport = listPrice.add(supportLevelCost);
- BigDecimal enclaveDiscount = pricingInfo.enclave() ? new BigDecimal("-15.1234") : BigDecimal.ZERO;
- BigDecimal volumeDiscount = new BigDecimal("-5.64315634");
- BigDecimal committedAmountDiscount = new BigDecimal("-1.23");
- BigDecimal totalAmount = listPrice.add(supportLevelCost).add(enclaveDiscount).add(volumeDiscount).add(committedAmountDiscount);
- return new PriceInformation("default", listPriceWithSupport, volumeDiscount, committedAmountDiscount, enclaveDiscount, totalAmount);
- }
-
@Override
public Prices priceForApplications(List<ApplicationResources> applicationResources, PricingInfo pricingInfo, Plan plan) {
ApplicationResources resources = applicationResources.get(0);
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/pricing/ApplicationResources.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/pricing/ApplicationResources.java
index 5c6de406a55..fa742c27486 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/pricing/ApplicationResources.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/pricing/ApplicationResources.java
@@ -2,6 +2,8 @@ package com.yahoo.vespa.hosted.controller.api.integration.pricing;
import java.math.BigDecimal;
+import static java.math.BigDecimal.ZERO;
+
/**
* @param applicationName name of the application
* @param vcpu vcpus summed over all clusters, instances, zones
@@ -17,5 +19,14 @@ public record ApplicationResources(String applicationName, BigDecimal vcpu, BigD
BigDecimal gpuMemoryGb, BigDecimal enclaveVcpu, BigDecimal enclaveMemoryGb,
BigDecimal enclaveDiskGb, BigDecimal enclaveGpuMemoryGb) {
-}
+ public static ApplicationResources create(String applicationName, BigDecimal vcpu, BigDecimal memoryGb,
+ BigDecimal diskGb, BigDecimal gpuMemoryGb) {
+ return new ApplicationResources(applicationName, vcpu, memoryGb, diskGb, gpuMemoryGb, ZERO, ZERO, ZERO, ZERO);
+ }
+ public static ApplicationResources createEnclave(String applicationName, BigDecimal vcpu, BigDecimal memoryGb,
+ BigDecimal diskGb, BigDecimal gpuMemoryGb) {
+ return new ApplicationResources(applicationName, ZERO, ZERO, ZERO, ZERO, vcpu, memoryGb, diskGb, gpuMemoryGb);
+ }
+
+}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/pricing/PricingController.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/pricing/PricingController.java
index 23d5f81dfb7..7b082932588 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/pricing/PricingController.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/pricing/PricingController.java
@@ -1,7 +1,6 @@
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller.api.integration.pricing;
-import com.yahoo.config.provision.ClusterResources;
import com.yahoo.vespa.hosted.controller.api.integration.billing.Plan;
import java.util.List;
@@ -13,9 +12,6 @@ import java.util.List;
*/
public interface PricingController {
- // TODO: Legacy, will be removed when not in use anymore
- PriceInformation price(List<ClusterResources> clusterResources, PricingInfo pricingInfo, Plan plan);
-
/**
*
* @param applicationResources resources used by an application
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/pricing/PricingInfo.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/pricing/PricingInfo.java
index 1ab149d083f..ba6f1939fc5 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/pricing/PricingInfo.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/pricing/PricingInfo.java
@@ -1,11 +1,14 @@
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller.api.integration.pricing;
-// TODO: Use BigDecimal for committedHourlyAmount
-public record PricingInfo(boolean enclave, SupportLevel supportLevel, double committedHourlyAmount) {
+import java.math.BigDecimal;
+
+import static java.math.BigDecimal.ZERO;
+
+public record PricingInfo(SupportLevel supportLevel, BigDecimal committedHourlyAmount) {
public enum SupportLevel { BASIC, COMMERCIAL, ENTERPRISE }
- public static PricingInfo empty() { return new PricingInfo(false, SupportLevel.COMMERCIAL, 0); }
+ public static PricingInfo empty() { return new PricingInfo(SupportLevel.COMMERCIAL, ZERO); }
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/pricing/PricingApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/pricing/PricingApiHandler.java
index 7cff6e951c6..48ddd59e3f2 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/pricing/PricingApiHandler.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/pricing/PricingApiHandler.java
@@ -83,19 +83,8 @@ public class PricingApiHandler extends ThreadedHttpRequestHandler {
private HttpResponse pricing(HttpRequest request) {
String rawQuery = request.getUri().getRawQuery();
var priceParameters = parseQuery(rawQuery);
- boolean isLegacy = priceParameters.appResources() == null;
- if (isLegacy) {
- PriceInformation price = calculateLegacyPrice(priceParameters);
- return legacyResponse(price, priceParameters);
- } else {
- Prices price = calculatePrice(priceParameters);
- return response(price, priceParameters);
- }
- }
-
- private PriceInformation calculateLegacyPrice(PriceParameters priceParameters) {
- var priceCalculator = controller.serviceRegistry().pricingController();
- return priceCalculator.price(priceParameters.clusterResources, priceParameters.pricingInfo, priceParameters.plan);
+ Prices price = calculatePrice(priceParameters);
+ return response(price, priceParameters);
}
private Prices calculatePrice(PriceParameters priceParameters) {
@@ -106,35 +95,7 @@ public class PricingApiHandler extends ThreadedHttpRequestHandler {
private PriceParameters parseQuery(String rawQuery) {
if (rawQuery == null) throw new IllegalArgumentException("No price information found in query");
List<String> elements = Arrays.stream(URLDecoder.decode(rawQuery, UTF_8).split("&")).toList();
-
- if (keysAndValues(elements).stream().map(Pair::getFirst).toList().contains("resources"))
- return parseQueryLegacy(elements);
- else
- return parseQuery(elements);
- }
-
- private PriceParameters parseQueryLegacy(List<String> elements) {
- var supportLevel = SupportLevel.BASIC;
- var enclave = false;
- var committedSpend = ZERO;
- var plan = controller.serviceRegistry().planRegistry().defaultPlan(); // fallback to default plan if not supplied
- List<ClusterResources> clusterResources = new ArrayList<>();
-
- for (Pair<String, String> entry : keysAndValues(elements)) {
- var value = entry.getSecond();
- switch (entry.getFirst().toLowerCase()) {
- case "committedspend" -> committedSpend = new BigDecimal(value);
- case "enclave" -> enclave = Boolean.parseBoolean(value);
- case "planid" -> plan = plan(value).orElseThrow(() -> new IllegalArgumentException("Unknown plan id " + value));
- case "supportlevel" -> supportLevel = SupportLevel.valueOf(value.toUpperCase());
- case "resources" -> clusterResources.add(clusterResources(value));
- default -> throw new IllegalArgumentException("Unknown query parameter '" + entry.getFirst() + '\'');
- }
- }
- if (clusterResources.isEmpty()) throw new IllegalArgumentException("No cluster resources found in query");
-
- PricingInfo pricingInfo = new PricingInfo(enclave, supportLevel, committedSpend.doubleValue());
- return new PriceParameters(clusterResources, pricingInfo, plan, null);
+ return parseQuery(elements);
}
private PriceParameters parseQuery(List<String> elements) {
@@ -157,8 +118,7 @@ public class PricingApiHandler extends ThreadedHttpRequestHandler {
}
if (appResources.isEmpty()) throw new IllegalArgumentException("No application resources found in query");
- // TODO: enclave does not make sense in PricingInfo anymore, remove when legacy method is removed
- PricingInfo pricingInfo = new PricingInfo(false, supportLevel, committedSpend.doubleValue());
+ PricingInfo pricingInfo = new PricingInfo(supportLevel, committedSpend);
return new PriceParameters(List.of(), pricingInfo, plan, appResources);
}
@@ -239,21 +199,6 @@ public class PricingApiHandler extends ThreadedHttpRequestHandler {
return controller.serviceRegistry().planRegistry().plan(element);
}
- private static SlimeJsonResponse legacyResponse(PriceInformation priceInfo, PriceParameters priceParameters) {
- var slime = new Slime();
- Cursor cursor = slime.setObject();
-
- var array = cursor.setArray("priceInfo");
- addItem(array, supportLevelDescription(priceParameters), priceInfo.listPriceWithSupport());
- addItem(array, "Enclave", priceInfo.enclaveDiscount());
- addItem(array, "Volume discount", priceInfo.volumeDiscount());
- addItem(array, "Committed spend", priceInfo.committedAmountDiscount());
-
- setBigDecimal(cursor, "totalAmount", priceInfo.totalAmount());
-
- return new SlimeJsonResponse(slime);
- }
-
private static SlimeJsonResponse response(Prices prices, PriceParameters priceParameters) {
var slime = new Slime();
Cursor cursor = slime.setObject();
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/pricing/PricingApiHandlerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/pricing/PricingApiHandlerTest.java
index 321e582437a..6262697f0c3 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/pricing/PricingApiHandlerTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/pricing/PricingApiHandlerTest.java
@@ -22,25 +22,6 @@ public class PricingApiHandlerTest extends ControllerContainerCloudTest {
private static final String responseFiles = "src/test/java/com/yahoo/vespa/hosted/controller/restapi/pricing/responses/";
@Test
- void testPricingInfoBasicLegacy() {
- ContainerTester tester = new ContainerTester(container, responseFiles);
- assertEquals(SystemName.Public, tester.controller().system());
-
- var request = request("/pricing/v1/pricing?" + urlEncodedPriceInformationLegacy(BASIC, false));
- tester.assertJsonResponse(request, """
- {
- "priceInfo": [
- {"description": "Basic support unit price", "amount": "2240.00"},
- {"description": "Volume discount", "amount": "-5.64"},
- {"description": "Committed spend", "amount": "-1.23"}
- ],
- "totalAmount": "2233.13"
- }
- """,
- 200);
- }
-
- @Test
void testPricingInfoBasic() {
ContainerTester tester = new ContainerTester(container, responseFiles);
assertEquals(SystemName.Public, tester.controller().system());
@@ -94,26 +75,6 @@ public class PricingApiHandlerTest extends ControllerContainerCloudTest {
}
@Test
- void testPricingInfoCommercialEnclaveLegacy() {
- ContainerTester tester = new ContainerTester(container, responseFiles);
- assertEquals(SystemName.Public, tester.controller().system());
-
- var request = request("/pricing/v1/pricing?" + urlEncodedPriceInformationLegacy(COMMERCIAL, true));
- tester.assertJsonResponse(request, """
- {
- "priceInfo": [
- {"description": "Commercial support unit price", "amount": "3200.00"},
- {"description": "Enclave", "amount": "-15.12"},
- {"description": "Volume discount", "amount": "-5.64"},
- {"description": "Committed spend", "amount": "-1.23"}
- ],
- "totalAmount": "3178.00"
- }
- """,
- 200);
- }
-
- @Test
void testPricingInfoCommercialEnclave() {
ContainerTester tester = new ContainerTester(container, responseFiles);
assertEquals(SystemName.Public, tester.controller().system());
@@ -198,23 +159,12 @@ public class PricingApiHandlerTest extends ControllerContainerCloudTest {
tester.assertJsonResponse(request("/pricing/v1/pricing?supportLevel=basic&committedSpend=0&key=value"),
"{\"error-code\":\"BAD_REQUEST\",\"message\":\"Unknown query parameter 'key'\"}",
400);
- tester.assertJsonResponse(request("/pricing/v1/pricing?supportLevel=basic&committedSpend=0&resources=key%3Dvalue"),
- "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Unknown resource type 'key'\"}",
+ tester.assertJsonResponse(request("/pricing/v1/pricing?supportLevel=basic&committedSpend=0&application=key%3Dvalue"),
+ "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Unknown key 'key'\"}",
400);
}
/**
- * 2 clusters, with each having 1 node, with 1 vcpu, 1 Gb memory, 10 Gb disk and no GPU
- * price will be 20000 + 2000 + 200
- */
- String urlEncodedPriceInformationLegacy(PricingInfo.SupportLevel supportLevel, boolean enclave) {
- String resources = URLEncoder.encode("nodes=1,vcpu=1,memoryGb=1,diskGb=10,gpuMemoryGb=0", UTF_8);
- return "supportLevel=" + supportLevel.name().toLowerCase() + "&committedSpend=100&enclave=" + enclave +
- "&resources=" + resources +
- "&resources=" + resources;
- }
-
- /**
* 1 app, with 2 clusters (with total resources for all clusters with each having
* 1 node, with 1 vcpu, 1 Gb memory, 10 Gb disk and no GPU,
* price will be 20000 + 2000 + 200