summaryrefslogtreecommitdiffstats
path: root/controller-server
diff options
context:
space:
mode:
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
commit670778c6f081ceb7618d3a49e21bc355fa9458e1 (patch)
tree8344d9f317d9ff5391242e3215cb281339f0428a /controller-server
parent9f31d47a80a9d1827be9adc9d4a8a2c0f4aff706 (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')
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/security/CloudAccessControl.java17
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java26
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());
}