summaryrefslogtreecommitdiffstats
path: root/controller-server
diff options
context:
space:
mode:
authorØyvind Grønnesby <oyving@verizonmedia.com>2019-10-07 15:57:56 +0200
committerØyvind Grønnesby <oyving@verizonmedia.com>2019-10-07 15:57:56 +0200
commit99db3b6dedf9896f1c0ab76d7263328161bb8373 (patch)
tree99cd8115020520a25a68de036564564b97c3fa42 /controller-server
parent385ff3f0d79e76eba8c6cf688bc730fb14b0dd38 (diff)
Initial tenant cost API that is not wired up to any clients yet
Diffstat (limited to 'controller-server')
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java50
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java18
2 files changed, 68 insertions, 0 deletions
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
index 24819fda261..dc44e61ab08 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
@@ -100,6 +100,9 @@ import java.security.PublicKey;
import java.time.DayOfWeek;
import java.time.Duration;
import java.time.Instant;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
import java.util.Arrays;
import java.util.Base64;
import java.util.Comparator;
@@ -198,6 +201,8 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
if (path.matches("/application/v4/user")) return authenticatedUser(request);
if (path.matches("/application/v4/tenant")) return tenants(request);
if (path.matches("/application/v4/tenant/{tenant}")) return tenant(path.get("tenant"), request);
+ if (path.matches("/application/v4/tenant/{tenant}/cost")) return tenantCost(path.get("tenant"), request);
+ if (path.matches("/application/v4/tenant/{tenant}/cost/{month}")) return tenantCost(path.get("tenant"), path.get("month"), request);
if (path.matches("/application/v4/tenant/{tenant}/application")) return applications(path.get("tenant"), Optional.empty(), request);
if (path.matches("/application/v4/tenant/{tenant}/application/{application}")) return application(path.get("tenant"), path.get("application"), "default", request);
if (path.matches("/application/v4/tenant/{tenant}/application/{application}/deploying")) return deploying(path.get("tenant"), path.get("application"), "default", request);
@@ -354,6 +359,51 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
return new SlimeJsonResponse(slime);
}
+ private HttpResponse tenantCost(String tenantName, HttpRequest request) {
+ return controller.tenants().get(TenantName.from(tenantName))
+ .map(tenant -> tenantCost(tenant, request))
+ .orElseGet(() -> ErrorResponse.notFoundError("Tenant '" + tenantName + "' does not exist"));
+ }
+
+ private HttpResponse tenantCost(Tenant tenant, HttpRequest request) {
+ var slime = new Slime();
+ var objectCursor = slime.setObject();
+ var monthsCursor = objectCursor.setArray("months");
+
+ return new SlimeJsonResponse(slime);
+ }
+
+ private HttpResponse tenantCost(String tenantName, String monthString, HttpRequest request) {
+ Optional<Tenant> tenant = controller.tenants().get(TenantName.from(tenantName));
+ Optional<LocalDate> month = tenantCostParseMonth(monthString);
+
+ if (tenant.isEmpty()){
+ return ErrorResponse.notFoundError("Tenant '" + tenantName + "' does not exist");
+ }
+
+ if (month.isEmpty()) {
+ return ErrorResponse.badRequest("Could not parse month '" + monthString + "'");
+ }
+
+ return tenantCost(tenant.get(), month.get(), request);
+ }
+
+ private Optional<LocalDate> tenantCostParseMonth(String monthString) {
+ var formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+
+ try {
+ return Optional.of(LocalDate.parse(monthString, formatter).withDayOfMonth(1));
+ } catch (DateTimeParseException ignored) {
+ return Optional.empty();
+ }
+ }
+
+ private HttpResponse tenantCost(Tenant tenant, LocalDate month, HttpRequest request) {
+ var slime = new Slime();
+ slime.setObject();
+ return new SlimeJsonResponse(slime);
+ }
+
private HttpResponse applications(String tenantName, Optional<String> applicationName, HttpRequest request) {
TenantName tenant = TenantName.from(tenantName);
Slime slime = new Slime();
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java
index fb59a0e51d8..7543d18ad21 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java
@@ -183,6 +183,13 @@ public class ApplicationApiTest extends ControllerContainerTest {
tester.assertResponse(request("/application/v4/tenant/", GET).userIdentity(USER_ID),
new File("tenant-list.json"));
+ // GET list of months for a tenant
+ tester.assertResponse(request("/application/v4/tenant/tenant1/cost", GET).userIdentity(USER_ID).oktaAccessToken(OKTA_AT),
+ "{\"months\":[]}");
+
+ // GET cost for a month for a tenant
+ tester.assertResponse(request("/application/v4/tenant/tenant1/cost/2018-01-01", GET).userIdentity(USER_ID).oktaAccessToken(OKTA_AT),
+ "{}");
// Add another Athens domain, so we can try to create more tenants
createAthenzDomainWithAdmin(ATHENZ_TENANT_DOMAIN_2, USER_ID); // New domain to test tenant w/property ID
@@ -1106,6 +1113,17 @@ public class ApplicationApiTest extends ControllerContainerTest {
"{\"error-code\":\"NOT_FOUND\",\"message\":\"Could not delete instance 'tenant1.application1.instance1': Instance not found\"}",
404);
+ // GET cost of unknown tenant
+ tester.assertResponse(request("/application/v4/tenant/no-such-tenant/cost", GET).userIdentity(USER_ID).oktaAccessToken(OKTA_AT),
+ "{\"error-code\":\"NOT_FOUND\",\"message\":\"Tenant 'no-such-tenant' does not exist\"}", 404);
+
+ tester.assertResponse(request("/application/v4/tenant/no-such-tenant/cost/2018-01-01", GET).userIdentity(USER_ID).oktaAccessToken(OKTA_AT),
+ "{\"error-code\":\"NOT_FOUND\",\"message\":\"Tenant 'no-such-tenant' does not exist\"}", 404);
+
+ // GET cost with invalid date string
+ tester.assertResponse(request("/application/v4/tenant/tenant1/cost/not-a-valid-date", GET).userIdentity(USER_ID).oktaAccessToken(OKTA_AT),
+ "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Could not parse month 'not-a-valid-date'\"}", 400);
+
// DELETE tenant
tester.assertResponse(request("/application/v4/tenant/tenant1", DELETE)
.userIdentity(USER_ID)