diff options
author | Øyvind Grønnesby <oyving@verizonmedia.com> | 2021-11-25 14:31:31 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-25 14:31:31 +0100 |
commit | 53599cea91b8adad824a100b3ff42a5b84a29368 (patch) | |
tree | 2249a8088c4ede998f996f9575dccb9457ba9345 | |
parent | 8efdf6eebf3ec7d350d26c0ec2db6dab8a8f2794 (diff) | |
parent | cd91614db66b12e84293b8ba938cf2103aa95b28 (diff) |
Merge pull request #20112 from vespa-engine/ogronnesby/supported-plans
Show support pane in UI for tenants on plans w/support
7 files changed, 92 insertions, 8 deletions
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/Plan.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/Plan.java index 84e36ea75d1..bd4c3c1a56f 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/Plan.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/Plan.java @@ -23,4 +23,7 @@ public interface Plan { /** Is this a plan that is billed */ boolean isBilled(); + + /** Is this a plan that gets on-call support */ + boolean isSupported(); } 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 index 60eddbd24ff..5fb4d853e67 100644 --- 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 @@ -11,9 +11,9 @@ 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"); + public static final Plan freeTrial = new MockPlan("trial", false, false, 0, 0, 0, 200, "Free Trial - for testing purposes"); + public static final Plan paidPlan = new MockPlan("paid", true, true, "0.09", "0.009", "0.0003", 500, "Paid Plan - for testing purposes"); + public static final Plan nonePlan = new MockPlan("none", false, false, 0, 0, 0, 0, "None Plan - for testing purposes"); @Override public Plan defaultPlan() { @@ -33,18 +33,20 @@ public class PlanRegistryMock implements PlanRegistry { private final CostCalculator costCalculator; private final QuotaCalculator quotaCalculator; private final boolean billed; + private final boolean supported; - 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, boolean supported, double cpuPrice, double memPrice, double dgbPrice, int quota, String description) { + this(PlanId.from(planId), billed, supported, 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(String planId, boolean billed, boolean supported, String cpuPrice, String memPrice, String dgbPrice, int quota, String description) { + this(PlanId.from(planId), billed, supported, new MockCostCalculator(cpuPrice, memPrice, dgbPrice), () -> Quota.unlimited().withBudget(quota), description); } - public MockPlan(PlanId planId, boolean billed, MockCostCalculator calculator, QuotaCalculator quota, String description) { + public MockPlan(PlanId planId, boolean billed, boolean supported, MockCostCalculator calculator, QuotaCalculator quota, String description) { this.planId = planId; this.billed = billed; + this.supported = supported; this.costCalculator = calculator; this.quotaCalculator = quota; this.description = description; @@ -74,6 +76,11 @@ public class PlanRegistryMock implements PlanRegistry { public boolean isBilled() { return billed; } + + @Override + public boolean isSupported() { + return supported; + } } private static class MockCostCalculator implements CostCalculator { diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiHandler.java index 0d12b283543..7e9ae036cc7 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiHandler.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiHandler.java @@ -25,6 +25,7 @@ import com.yahoo.vespa.flags.IntFlag; import com.yahoo.vespa.flags.PermanentFlags; import com.yahoo.vespa.hosted.controller.Controller; import com.yahoo.vespa.hosted.controller.LockedTenant; +import com.yahoo.vespa.hosted.controller.api.integration.billing.Plan; import com.yahoo.vespa.hosted.controller.api.integration.billing.PlanId; import com.yahoo.vespa.hosted.controller.api.integration.user.Roles; import com.yahoo.vespa.hosted.controller.api.integration.user.User; @@ -176,6 +177,7 @@ public class UserApiHandler extends LoggingRequestHandler { .sorted() .forEach(tenant -> { Cursor tenantObject = tenants.setObject(tenant.value()); + tenantObject.setBool("supported", hasSupportedPlan(tenant)); Cursor tenantRolesObject = tenantObject.setArray("roles"); tenantRolesByTenantName.getOrDefault(tenant, List.of()) @@ -405,4 +407,11 @@ public class UserApiHandler extends LoggingRequestHandler { .map(clazz::cast) .orElseThrow(() -> new IllegalArgumentException("Attribute '" + attributeName + "' was not set on request")); } + + private boolean hasSupportedPlan(TenantName tenantName) { + var planId = controller.serviceRegistry().billingController().getPlan(tenantName); + return controller.serviceRegistry().planRegistry().plan(planId) + .map(Plan::isSupported) + .orElse(false); + } } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiTest.java index 1d41beb8a99..537f6c48bdf 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiTest.java @@ -8,6 +8,7 @@ import com.yahoo.vespa.flags.Flags; import com.yahoo.vespa.flags.InMemoryFlagSource; import com.yahoo.vespa.flags.PermanentFlags; import com.yahoo.vespa.hosted.controller.ControllerTester; +import com.yahoo.vespa.hosted.controller.api.integration.billing.PlanId; import com.yahoo.vespa.hosted.controller.api.integration.user.User; import com.yahoo.vespa.hosted.controller.api.role.Role; import com.yahoo.vespa.hosted.controller.restapi.ContainerTester; @@ -270,4 +271,27 @@ public class UserApiTest extends ControllerContainerCloudTest { new File("user-without-trial-capacity-cloud.json")); } } + + @Test + public void supportTenant() { + try (Flags.Replacer ignored = Flags.clearFlagsForTesting(PermanentFlags.MAX_TRIAL_TENANTS.id(), PermanentFlags.ENABLE_PUBLIC_SIGNUP_FLOW.id())) { + ContainerTester tester = new ContainerTester(container, responseFiles); + ((InMemoryFlagSource) tester.controller().flagSource()) + .withIntFlag(PermanentFlags.MAX_TRIAL_TENANTS.id(), 10) + .withBooleanFlag(PermanentFlags.ENABLE_PUBLIC_SIGNUP_FLOW.id(), true); + ControllerTester controller = new ControllerTester(tester); + User user = new User("dev@domail", "Joe Developer", "dev", null); + + var tenant1 = controller.createTenant("tenant1", Tenant.Type.cloud); + var tenant2 = controller.createTenant("tenant2", Tenant.Type.cloud); + controller.serviceRegistry().billingController().setPlan(tenant2, PlanId.from("paid"), false); + + tester.assertResponse( + request("/user/v1/user") + .roles(Role.reader(tenant1), Role.reader(tenant2)) + .user(user), + new File("user-with-supported-tenant.json")); + } + + } } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/user-with-applications-athenz.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/user-with-applications-athenz.json index 006c3b98a4d..0211f595ce7 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/user-with-applications-athenz.json +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/user-with-applications-athenz.json @@ -10,6 +10,7 @@ }, "tenants": { "sandbox": { + "supported": (ignore), "roles": [ "administrator", "developer", @@ -17,6 +18,7 @@ ] }, "tenant1": { + "supported": (ignore), "roles": [ "administrator", "developer", @@ -24,6 +26,7 @@ ] }, "tenant2": { + "supported": (ignore), "roles": [ "administrator", "developer", diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/user-with-applications-cloud.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/user-with-applications-cloud.json index 4ae55e97baa..76904bf9bb4 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/user-with-applications-cloud.json +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/user-with-applications-cloud.json @@ -10,17 +10,20 @@ }, "tenants": { "sandbox": { + "supported": false, "roles": [ "developer", "reader" ] }, "tenant1": { + "supported": false, "roles": [ "administrator" ] }, "tenant2": { + "supported": false, "roles": [ "developer" ] diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/user-with-supported-tenant.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/user-with-supported-tenant.json new file mode 100644 index 00000000000..a40354a9e71 --- /dev/null +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/user-with-supported-tenant.json @@ -0,0 +1,35 @@ +{ + "isPublic": true, + "isCd": false, + "hasTrialCapacity": true, + "user": { + "name": "Joe Developer", + "email": "dev@domail", + "nickname": "dev", + "verified": false + }, + "tenants": { + "tenant1": { + "supported": false, + "roles": [ + "reader" + ] + }, + "tenant2": { + "supported": true, + "roles": [ + "reader" + ] + } + }, + "flags": [ + { + "id": "enable-public-signup-flow", + "rules": [ + { + "value": false + } + ] + } + ] +}
\ No newline at end of file |