diff options
author | Ola Aunrønning <olaa@verizonmedia.com> | 2020-08-06 13:46:10 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-08-06 13:46:10 +0200 |
commit | 192827812e31a044248d31a0febe21439a8a6f23 (patch) | |
tree | 442e78e83844aff6026ae4c3d1be1e88f974a82d | |
parent | 3173a131800b1eb8dadfcb936a16899d0175e8fd (diff) | |
parent | ceb9846ab1f17cfcef957b93076f6de34afdd494 (diff) |
Merge pull request #14002 from vespa-engine/olaa/delete-billing-info
BillingController deletes billing info
4 files changed, 20 insertions, 82 deletions
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillingController.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillingController.java index 2a167ee2962..a21c9f2a40e 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillingController.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillingController.java @@ -3,6 +3,7 @@ package com.yahoo.vespa.hosted.controller.api.integration.billing; import com.yahoo.config.provision.TenantName; import com.yahoo.vespa.hosted.controller.api.identifiers.DeploymentId; +import com.yahoo.vespa.hosted.controller.api.integration.user.User; import java.math.BigDecimal; import java.time.LocalDate; @@ -10,6 +11,7 @@ import java.time.ZonedDateTime; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Set; public interface BillingController { @@ -46,4 +48,6 @@ public interface BillingController { List<Invoice> getInvoices(TenantName tenant); + void deleteBillingInfo(TenantName tenant, Set<User> users, boolean isPrivileged); + }
\ No newline at end of file diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/MockBillingController.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/MockBillingController.java index 3cf571ed30f..24259a94ccf 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/MockBillingController.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/MockBillingController.java @@ -2,6 +2,7 @@ package com.yahoo.vespa.hosted.controller.api.integration.billing; import com.yahoo.config.provision.TenantName; +import com.yahoo.vespa.hosted.controller.api.integration.user.User; import java.math.BigDecimal; import java.time.LocalDate; @@ -11,6 +12,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Set; /** * @author olaa @@ -125,6 +127,9 @@ public class MockBillingController implements BillingController { return committedInvoices.getOrDefault(tenant, List.of()); } + @Override + public void deleteBillingInfo(TenantName tenant, Set<User> users, boolean isPrivileged) {} + private PaymentInstrument createInstrument(String id) { return new PaymentInstrument(id, "name", 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 320b376c2ae..4f410f60204 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 @@ -10,7 +10,6 @@ import com.yahoo.vespa.flags.Flags; 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.organization.BillingInfo; 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; @@ -22,9 +21,8 @@ import com.yahoo.vespa.hosted.controller.tenant.CloudTenant; import com.yahoo.vespa.hosted.controller.tenant.Tenant; import javax.ws.rs.ForbiddenException; -import java.math.BigDecimal; -import java.time.LocalDate; import java.util.List; +import java.util.stream.Collectors; import static com.yahoo.vespa.hosted.controller.api.role.RoleDefinition.*; @@ -101,19 +99,11 @@ public class CloudAccessControl implements AccessControl { @Override public void deleteTenant(TenantName tenant, Credentials credentials) { - if(!(allowedByPrivilegedRole((Auth0Credentials) credentials) || noOutstandingCharges(tenant))) - throw new ForbiddenException("Please contact the Vespa team for assistance in deleting tenants with outstanding charges"); - + deleteBillingInfo(tenant, credentials); for (TenantRole role : Roles.tenantRoles(tenant)) userManagement.deleteRole(role); } - private boolean noOutstandingCharges(TenantName tenant) { - return billingController.createUncommittedInvoice(tenant, LocalDate.now()).sum().compareTo(BigDecimal.ZERO) == 0 && - billingController.getUnusedLineItems(tenant).size() == 0 && - billingController.getPlan(tenant).value().equals("trial"); - } - @Override public void createApplication(TenantAndApplicationId id, Credentials credentials) { for (Role role : Roles.applicationRoles(id.tenant(), id.application())) @@ -126,4 +116,13 @@ public class CloudAccessControl implements AccessControl { userManagement.deleteRole(role); } + private void deleteBillingInfo(TenantName tenant, Credentials credentials) { + var users = Roles.tenantRoles(tenant) + .stream() + .flatMap(role -> userManagement.listUsers(role).stream()) + .collect(Collectors.toSet()); + var isPrivileged = allowedByPrivilegedRole((Auth0Credentials) credentials); + billingController.deleteBillingInfo(tenant, users, isPrivileged); + } + } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/security/CloudAccessControlTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/security/CloudAccessControlTest.java deleted file mode 100644 index baf7d3826f1..00000000000 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/security/CloudAccessControlTest.java +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.hosted.controller.security; - -import com.yahoo.config.provision.TenantName; -import com.yahoo.vespa.flags.FlagSource; -import com.yahoo.vespa.flags.InMemoryFlagSource; -import com.yahoo.vespa.hosted.controller.api.integration.ServiceRegistry; -import com.yahoo.vespa.hosted.controller.api.integration.billing.Invoice; -import com.yahoo.vespa.hosted.controller.api.integration.billing.MockBillingController; -import com.yahoo.vespa.hosted.controller.api.integration.billing.PlanId; -import com.yahoo.vespa.hosted.controller.api.integration.stubs.MockUserManagement; -import com.yahoo.vespa.hosted.controller.api.integration.user.UserManagement; -import com.yahoo.vespa.hosted.controller.integration.ServiceRegistryMock; -import org.junit.Test; - -import javax.ws.rs.ForbiddenException; -import java.math.BigDecimal; -import java.security.Principal; -import java.util.HashSet; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -/** - * @author olaa - */ -public class CloudAccessControlTest { - - private final UserManagement userManagement = new MockUserManagement(); - private final FlagSource flagSource = new InMemoryFlagSource(); - private final ServiceRegistry serviceRegistry = new ServiceRegistryMock(); - private final MockBillingController billingController = (MockBillingController) serviceRegistry.billingController(); - private final CloudAccessControl cloudAccessControl = new CloudAccessControl(userManagement, flagSource, serviceRegistry); - - @Test - public void tenant_deletion_fails_when_outstanding_charges() { - // First verify that it works with no outstanding charges - var tenant = TenantName.defaultName(); - var principal = mock(Principal.class); - var credentials = new Auth0Credentials(principal, new HashSet<>()); - cloudAccessControl.deleteTenant(tenant, credentials); - - // Forbidden if plan != trial - billingController.setPlan(tenant, PlanId.from("subscription"), false); - try { - cloudAccessControl.deleteTenant(tenant, credentials); - fail(); - } catch (ForbiddenException ignored) {} - billingController.setPlan(tenant, PlanId.from("trial"), false); - - // Forbidden if outstanding lineitems - billingController.addLineItem(tenant, "Some expense", BigDecimal.TEN, "agent"); - try { - cloudAccessControl.deleteTenant(tenant, credentials); - fail(); - } catch (ForbiddenException ignored) {} - billingController.deleteLineItem("line-item-id"); - - // Forbidden if uncommited invoice exists - var invoice = mock(Invoice.class); - when(invoice.sum()).thenReturn(BigDecimal.TEN); - billingController.addInvoice(tenant, invoice, false); - try { - cloudAccessControl.deleteTenant(tenant, credentials); - fail(); - } catch (ForbiddenException ignored) {} - - } -}
\ No newline at end of file |