diff options
author | Øyvind Grønnesby <oyving@verizonmedia.com> | 2020-12-01 14:41:27 +0100 |
---|---|---|
committer | Øyvind Grønnesby <oyving@verizonmedia.com> | 2020-12-01 14:41:27 +0100 |
commit | 670778c6f081ceb7618d3a49e21bc355fa9458e1 (patch) | |
tree | 8344d9f317d9ff5391242e3215cb281339f0428a /controller-server | |
parent | 9f31d47a80a9d1827be9adc9d4a8a2c0f4aff706 (diff) |
Introduce trial tenant limit
Create a feature flag that has the max nr. of tenants with the trial
plan. If the number is exceeded we fail creation of new tenants (who
are implicitly in the trial plan).
Diffstat (limited to 'controller-server')
2 files changed, 43 insertions, 0 deletions
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/security/CloudAccessControl.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/security/CloudAccessControl.java index 6d2b2d58e78..f7b7f379129 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/security/CloudAccessControl.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/security/CloudAccessControl.java @@ -7,9 +7,11 @@ import com.yahoo.vespa.flags.BooleanFlag; import com.yahoo.vespa.flags.FetchVector; import com.yahoo.vespa.flags.FlagSource; import com.yahoo.vespa.flags.Flags; +import com.yahoo.vespa.flags.IntFlag; import com.yahoo.vespa.hosted.controller.Application; import com.yahoo.vespa.hosted.controller.api.integration.ServiceRegistry; import com.yahoo.vespa.hosted.controller.api.integration.billing.BillingController; +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.UserId; import com.yahoo.vespa.hosted.controller.api.integration.user.UserManagement; @@ -34,18 +36,21 @@ public class CloudAccessControl implements AccessControl { private final UserManagement userManagement; private final BooleanFlag enablePublicSignup; + private final IntFlag maxTrialTenants; private final BillingController billingController; @Inject public CloudAccessControl(UserManagement userManagement, FlagSource flagSource, ServiceRegistry serviceRegistry) { this.userManagement = userManagement; this.enablePublicSignup = Flags.ENABLE_PUBLIC_SIGNUP_FLOW.bindTo(flagSource); + this.maxTrialTenants = Flags.MAX_TRIAL_TENANTS.bindTo(flagSource); billingController = serviceRegistry.billingController(); } @Override public CloudTenant createTenant(TenantSpec tenantSpec, Credentials credentials, List<Tenant> existing) { requireTenantCreationAllowed((Auth0Credentials) credentials); + requireTenantTrialLimitNotReached(existing); CloudTenantSpec spec = (CloudTenantSpec) tenantSpec; CloudTenant tenant = CloudTenant.create(spec.tenant(), credentials.user()); @@ -62,6 +67,18 @@ public class CloudAccessControl implements AccessControl { return tenant; } + private void requireTenantTrialLimitNotReached(List<Tenant> existing) { + var trialPlanId = PlanId.from("trial"); + var tenantNames = existing.stream().map(Tenant::name).collect(Collectors.toList()); + var trialTenants = billingController.getPlans(tenantNames).values().stream() + .filter(trialPlanId::equals) + .count(); + + if (maxTrialTenants.value() >= 0 && maxTrialTenants.value() <= trialTenants) { + throw new ForbiddenException("Too many tenants with trial plans, please contact the Vespa support team"); + } + } + private void requireTenantCreationAllowed(Auth0Credentials auth0Credentials) { if (allowedByPrivilegedRole(auth0Credentials)) return; diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java index 5b33f989163..1da7bdeca19 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java @@ -7,6 +7,7 @@ import com.yahoo.config.provision.TenantName; import com.yahoo.vespa.flags.Flags; import com.yahoo.vespa.flags.InMemoryFlagSource; import com.yahoo.vespa.hosted.controller.ControllerTester; +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.application.TenantAndApplicationId; import com.yahoo.vespa.hosted.controller.deployment.ApplicationPackageBuilder; @@ -19,6 +20,7 @@ import com.yahoo.vespa.hosted.controller.security.Credentials; import org.junit.Before; import org.junit.Test; +import javax.ws.rs.ForbiddenException; import java.util.Collections; import java.util.Set; @@ -26,6 +28,8 @@ import static com.yahoo.application.container.handler.Request.Method.GET; import static com.yahoo.application.container.handler.Request.Method.PUT; import static com.yahoo.application.container.handler.Request.Method.POST; import static com.yahoo.vespa.hosted.controller.restapi.application.ApplicationApiTest.createApplicationSubmissionData; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; public class ApplicationApiCloudTest extends ControllerContainerCloudTest { @@ -94,6 +98,24 @@ public class ApplicationApiCloudTest extends ControllerContainerCloudTest { tester.assertResponse(infoRequest, fullInfo, 200); } + @Test + public void trial_tenant_limit_reached() { + ((InMemoryFlagSource) tester.controller().flagSource()).withIntFlag(Flags.MAX_TRIAL_TENANTS.id(), 1); + tester.controller().serviceRegistry().billingController().setPlan(tenantName, PlanId.from("pay-as-you-go"), false); + + // tests that we can create the one trial tenant the flag says we can have -- and that the tenant created + // in @Before does not count towards that limit. + tester.controller().tenants().create(tenantSpec("tenant1"), credentials("administrator")); + + // tests that exceeding the limit throws a ForbiddenException + try { + tester.controller().tenants().create(tenantSpec("tenant2"), credentials("administrator")); + fail("Should not be allowed to create tenant that exceed trial limit"); + } catch (ForbiddenException e) { + assertEquals("Too many tenants with trial plans, please contact the Vespa support team", e.getMessage()); + } + } + private ApplicationPackageBuilder prodBuilder() { return new ApplicationPackageBuilder() .instances("default") @@ -108,6 +130,10 @@ public class ApplicationApiCloudTest extends ControllerContainerCloudTest { tester.controller().applications().createApplication(appId, credentials("developer@scoober")); } + private static CloudTenantSpec tenantSpec(String name) { + return new CloudTenantSpec(TenantName.from(name), ""); + } + private static Credentials credentials(String name) { return new Auth0Credentials(() -> name, Collections.emptySet()); } |