summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMorten Tokle <mortent@verizonmedia.com>2021-05-04 17:51:12 +0200
committerGitHub <noreply@github.com>2021-05-04 17:51:12 +0200
commit86d97a12862d0ebb59f132bad0cee3e5b21227bb (patch)
tree5413a1c615e080fa16c4887a24ae40003526ab90
parent1a206c055d516c5775e68a80cdd9338c5633a44a (diff)
parent12375b621d185f5873ffa69e68a9d792ae9af6ad (diff)
Merge pull request #17732 from vespa-engine/mortent/iam-roles-maintain-prod-tenants
Maintain iam roles for tenants with prod deployment
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/aws/MockRoleService.java21
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/TenantRoleMaintainer.java16
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ServiceRegistryMock.java3
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/TenantRoleMaintainerTest.java58
4 files changed, 92 insertions, 6 deletions
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/aws/MockRoleService.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/aws/MockRoleService.java
new file mode 100644
index 00000000000..f7c51f0bbc2
--- /dev/null
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/aws/MockRoleService.java
@@ -0,0 +1,21 @@
+// 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.api.integration.aws;
+
+import com.yahoo.config.provision.TenantName;
+
+import java.util.List;
+
+public class MockRoleService extends NoopRoleService {
+
+ private List<TenantName> maintainedTenants;
+
+ @Override
+ public void maintainRoles(List<TenantName> tenants) {
+ maintainedTenants = List.copyOf(tenants);
+ }
+
+ public List<TenantName> maintainedTenants() {
+ return maintainedTenants;
+ }
+}
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<TenantName> 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();
+ }
+
+}