From 12375b621d185f5873ffa69e68a9d792ae9af6ad Mon Sep 17 00:00:00 2001 From: Morten Tokle Date: Tue, 4 May 2021 15:14:46 +0200 Subject: Maintain iam roles for tenants with prod deployment --- .../maintenance/TenantRoleMaintainer.java | 16 ++++-- .../integration/ServiceRegistryMock.java | 3 +- .../maintenance/TenantRoleMaintainerTest.java | 58 ++++++++++++++++++++++ 3 files changed, 71 insertions(+), 6 deletions(-) create mode 100644 controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/TenantRoleMaintainerTest.java (limited to 'controller-server') diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/TenantRoleMaintainer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/TenantRoleMaintainer.java index e8b50a6b604..e3a7d91d7cc 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/TenantRoleMaintainer.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/TenantRoleMaintainer.java @@ -2,22 +2,23 @@ package com.yahoo.vespa.hosted.controller.maintenance; +import com.yahoo.config.provision.TenantName; import com.yahoo.vespa.flags.BooleanFlag; import com.yahoo.vespa.flags.FetchVector; import com.yahoo.vespa.flags.Flags; +import com.yahoo.vespa.hosted.controller.Application; import com.yahoo.vespa.hosted.controller.Controller; import com.yahoo.vespa.hosted.controller.tenant.Tenant; import java.time.Duration; +import java.util.List; +import java.util.Map; import java.util.stream.Collectors; public class TenantRoleMaintainer extends ControllerMaintainer { - private final BooleanFlag provisionTenantRoles; - public TenantRoleMaintainer(Controller controller, Duration tenantRoleMaintainer) { super(controller, tenantRoleMaintainer); - provisionTenantRoles = Flags.PROVISION_TENANT_ROLES.bindTo(controller.flagSource()); } @Override @@ -26,10 +27,15 @@ public class TenantRoleMaintainer extends ControllerMaintainer { var tenants = controller().tenants().asList(); var tenantsWithRoles = tenants.stream() .map(Tenant::name) - // Only maintain a subset of the tenants - .filter(name -> provisionTenantRoles.with(FetchVector.Dimension.TENANT_ID, name.value()).value()) + .filter(this::hasProductionDeployment) .collect(Collectors.toList()); roleService.maintainRoles(tenantsWithRoles); return true; } + + private boolean hasProductionDeployment(TenantName tenant) { + return controller().applications().asList(tenant).stream() + .map(Application::productionInstances) + .noneMatch(Map::isEmpty); + } } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ServiceRegistryMock.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ServiceRegistryMock.java index 326928b9463..c11c6ba155a 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ServiceRegistryMock.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ServiceRegistryMock.java @@ -9,6 +9,7 @@ import com.yahoo.test.ManualClock; import com.yahoo.vespa.hosted.controller.api.integration.ServiceRegistry; import com.yahoo.vespa.hosted.controller.api.integration.archive.ArchiveService; import com.yahoo.vespa.hosted.controller.api.integration.archive.MockArchiveService; +import com.yahoo.vespa.hosted.controller.api.integration.aws.MockRoleService; import com.yahoo.vespa.hosted.controller.api.integration.aws.RoleService; import com.yahoo.vespa.hosted.controller.api.integration.aws.MockAwsEventFetcher; import com.yahoo.vespa.hosted.controller.api.integration.aws.MockResourceTagger; @@ -66,7 +67,7 @@ public class ServiceRegistryMock extends AbstractComponent implements ServiceReg private final ApplicationStoreMock applicationStoreMock = new ApplicationStoreMock(); private final MockRunDataStore mockRunDataStore = new MockRunDataStore(); private final MockResourceTagger mockResourceTagger = new MockResourceTagger(); - private final RoleService roleService = new NoopRoleService(); + private final RoleService roleService = new MockRoleService(); private final BillingController billingController = new MockBillingController(); private final ContainerRegistryMock containerRegistry = new ContainerRegistryMock(); private final NoopTenantSecretService tenantSecretService = new NoopTenantSecretService(); diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/TenantRoleMaintainerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/TenantRoleMaintainerTest.java new file mode 100644 index 00000000000..c023ec9b43d --- /dev/null +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/TenantRoleMaintainerTest.java @@ -0,0 +1,58 @@ +// 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.maintenance; + +import com.yahoo.config.provision.TenantName; +import com.yahoo.vespa.hosted.controller.Instance; +import com.yahoo.vespa.hosted.controller.api.integration.aws.MockRoleService; +import com.yahoo.vespa.hosted.controller.api.integration.deployment.JobType; +import com.yahoo.vespa.hosted.controller.application.ApplicationPackage; +import com.yahoo.vespa.hosted.controller.deployment.ApplicationPackageBuilder; +import com.yahoo.vespa.hosted.controller.deployment.DeploymentTester; +import org.junit.Test; + +import java.time.Duration; +import java.util.List; + +import static org.junit.Assert.assertEquals; + +/** + * @author mortent + */ +public class TenantRoleMaintainerTest { + + private final DeploymentTester tester = new DeploymentTester(); + + @Test + public void maintains_iam_roles_for_tenants_in_production() { + var devApp = tester.newDeploymentContext("tenant1", "app1", "default"); + var prodApp = tester.newDeploymentContext("tenant2", "app2", "default"); + ApplicationPackage appPackage = new ApplicationPackageBuilder() + .region("us-west-1") + .build(); + + // Deploy dev + devApp.runJob(JobType.devUsEast1, appPackage); + + // Deploy prod + prodApp.submit(appPackage).deploy(); + assertEquals(1, permanentDeployments(devApp.instance())); + assertEquals(1, permanentDeployments(prodApp.instance())); + + var maintainer = new TenantRoleMaintainer(tester.controller(), Duration.ofDays(1)); + maintainer.maintain(); + + var roleService = tester.controller().serviceRegistry().roleService(); + List tenantNames = ((MockRoleService) roleService).maintainedTenants(); + + assertEquals(1, tenantNames.size()); + assertEquals(prodApp.application().id().tenant(), tenantNames.get(0)); + } + + private long permanentDeployments(Instance instance) { + return tester.controller().applications().requireInstance(instance.id()).deployments().values().stream() + .filter(deployment -> !deployment.zone().environment().isTest()) + .count(); + } + +} -- cgit v1.2.3