summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Marius Venstad <jvenstad@yahoo-inc.com>2019-03-11 14:31:44 +0100
committerJon Marius Venstad <jvenstad@yahoo-inc.com>2019-03-11 15:25:12 +0100
commitd87bbfbf911674f2e4b739ed711028ae8e507d5b (patch)
treeb5b6099c4f941636c98188f72a7b52a9e9c98ecf
parent805ee314489bf7f0e02051f71b58ca9c7e72b609 (diff)
Subclass LockedTenant like Tenant
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java6
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/LockedTenant.java163
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/TenantController.java34
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ApplicationOwnershipConfirmer.java2
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ContactInformationMaintainer.java20
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentIssueReporter.java4
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java9
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/filter/ControllerAuthorizationFilter.java4
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/AthenzTenant.java6
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/CloudTenant.java5
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/Tenant.java17
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/UserTenant.java5
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java2
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTester.java4
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java5
15 files changed, 193 insertions, 93 deletions
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java
index f51bccff5d1..d53d3137991 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/ApplicationController.java
@@ -227,7 +227,7 @@ public class ApplicationController {
if (asList(id.tenant()).stream().noneMatch(application -> application.id().application().equals(id.application())))
com.yahoo.vespa.hosted.controller.api.identifiers.ApplicationId.validate(id.application().value());
- Optional<Tenant> tenant = controller.tenants().tenant(id.tenant());
+ Optional<Tenant> tenant = controller.tenants().get(id.tenant());
if ( ! tenant.isPresent())
throw new IllegalArgumentException("Could not create '" + id + "': This tenant does not exist");
if (get(id).isPresent())
@@ -555,7 +555,7 @@ public class ApplicationController {
if ( ! application.get().deployments().isEmpty())
throw new IllegalArgumentException("Could not delete '" + application + "': It has active deployments");
- Tenant tenant = controller.tenants().tenant(id.tenant()).get();
+ Tenant tenant = controller.tenants().get(id.tenant()).get();
if (tenant instanceof AthenzTenant && ! token.isPresent())
throw new IllegalArgumentException("Could not delete '" + application + "': No Okta Access Token provided");
@@ -728,7 +728,7 @@ public class ApplicationController {
public void verifyApplicationIdentityConfiguration(TenantName tenantName, ApplicationPackage applicationPackage, Optional<AthenzIdentity> deployingIdentity) {
applicationPackage.deploymentSpec().athenzDomain()
.ifPresent(identityDomain -> {
- Optional<Tenant> tenant = controller.tenants().tenant(tenantName);
+ Optional<Tenant> tenant = controller.tenants().get(tenantName);
if(!tenant.isPresent()) {
throw new IllegalArgumentException("Tenant does not exist");
} else {
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/LockedTenant.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/LockedTenant.java
index 590b18f929d..21690c404de 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/LockedTenant.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/LockedTenant.java
@@ -8,6 +8,8 @@ import com.yahoo.vespa.hosted.controller.api.identifiers.Property;
import com.yahoo.vespa.hosted.controller.api.identifiers.PropertyId;
import com.yahoo.vespa.hosted.controller.tenant.AthenzTenant;
import com.yahoo.vespa.hosted.controller.api.integration.organization.Contact;
+import com.yahoo.vespa.hosted.controller.tenant.BillingInfo;
+import com.yahoo.vespa.hosted.controller.tenant.CloudTenant;
import com.yahoo.vespa.hosted.controller.tenant.Tenant;
import com.yahoo.vespa.hosted.controller.tenant.UserTenant;
@@ -15,79 +17,134 @@ import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
+import static java.util.Objects.deepEquals;
+import static java.util.Objects.requireNonNull;
+
/**
* A tenant that has been locked for modification. Provides methods for modifying a tenant's fields.
*
* @author mpolden
+ * @author jonmv
*/
-public class LockedTenant {
-
- private final Lock lock;
- private final TenantName name;
- private AthenzDomain domain;
- private Property property;
- private Optional<PropertyId> propertyId;
- private final Optional<Contact> contact;
- private final boolean isAthenzTenant;
-
- /**
- * Should never be constructed directly.
- *
- * Use {@link TenantController#lockIfPresent(TenantName, Consumer)} or
- * {@link TenantController#lockOrThrow(TenantName, Consumer)}
- */
- LockedTenant(AthenzTenant tenant, Lock lock) {
- this(lock, tenant.name(), tenant.domain(), tenant.property(), tenant.propertyId(), tenant.contact());
- }
+public abstract class LockedTenant {
- LockedTenant(UserTenant tenant, Lock lock) {
- this(lock, tenant.name(), tenant.contact());
- }
+ final TenantName name;
- private LockedTenant(Lock lock, TenantName name, AthenzDomain domain, Property property,
- Optional<PropertyId> propertyId, Optional<Contact> contact) {
- this.lock = Objects.requireNonNull(lock, "lock must be non-null");
- this.name = Objects.requireNonNull(name, "name must be non-null");
- this.domain = Objects.requireNonNull(domain, "domain must be non-null");
- this.property = Objects.requireNonNull(property, "property must be non-null");
- this.propertyId = Objects.requireNonNull(propertyId, "propertyId must be non-null");
- this.contact = Objects.requireNonNull(contact, "contact must be non-null");
- this.isAthenzTenant = true;
+ private LockedTenant(TenantName name) {
+ this.name = requireNonNull(name);
}
- private LockedTenant(Lock lock, TenantName name, Optional<Contact> contact) {
- this.lock = Objects.requireNonNull(lock, "lock must be non-null");
- this.name = Objects.requireNonNull(name, "name must be non-null");
- this.contact = Objects.requireNonNull(contact, "contact must be non-null");
- this.isAthenzTenant = false;
+ static LockedTenant of(Tenant tenant, Lock lock) {
+ switch (tenant.type()) {
+ case athenz: return new Athenz((AthenzTenant) tenant);
+ case user: return new User((UserTenant) tenant);
+ case cloud: return new Cloud((CloudTenant) tenant);
+ default: throw new IllegalArgumentException("Unexpected tenant type '" + tenant.getClass().getName() + "'.");
+ }
}
/** Returns a read-only copy of this */
- public Tenant get() {
- if (isAthenzTenant) return new AthenzTenant(name, domain, property, propertyId, contact);
- else return new UserTenant(name, contact);
- }
+ public abstract Tenant get();
- public LockedTenant with(AthenzDomain domain) {
- return new LockedTenant(lock, name, domain, property, propertyId, contact);
+ @Override
+ public String toString() {
+ return "tenant '" + name + "'";
}
- public LockedTenant with(Property property) {
- return new LockedTenant(lock, name, domain, property, propertyId, contact);
- }
- public LockedTenant with(PropertyId propertyId) {
- return new LockedTenant(lock, name, domain, property, Optional.of(propertyId), contact);
+ /** A locked AthenzTenant. */
+ public static class Athenz extends LockedTenant {
+
+ private final AthenzDomain domain;
+ private final Property property;
+ private final Optional<PropertyId> propertyId;
+ private final Optional<Contact> contact;
+
+ private Athenz(TenantName name, AthenzDomain domain, Property property, Optional<PropertyId> propertyId, Optional<Contact> contact) {
+ super(name);
+ this.domain = domain;
+ this.property = property;
+ this.propertyId = propertyId;
+ this.contact = contact;
+ }
+
+ private Athenz(AthenzTenant tenant) {
+ this(tenant.name(), tenant.domain(), tenant.property(), tenant.propertyId(), tenant.contact());
+ }
+
+ @Override
+ public AthenzTenant get() {
+ return new AthenzTenant(name, domain, property, propertyId, contact);
+ }
+
+ public Athenz with(AthenzDomain domain) {
+ return new Athenz(name, domain, property, propertyId, contact);
+ }
+
+ public Athenz with(Property property) {
+ return new Athenz(name, domain, property, propertyId, contact);
+ }
+
+ public Athenz with(PropertyId propertyId) {
+ return new Athenz(name, domain, property, Optional.of(propertyId), contact);
+ }
+
+ public Athenz with(Contact contact) {
+ return new Athenz(name, domain, property, propertyId, Optional.of(contact));
+ }
+
}
- public LockedTenant with(Contact contact) {
- if (isAthenzTenant) return new LockedTenant(lock, name, domain, property, propertyId, Optional.of(contact));
- return new LockedTenant(lock, name, Optional.of(contact));
+
+ /** A locked UserTenant. */
+ public static class User extends LockedTenant {
+
+ private final Optional<Contact> contact;
+
+ private User(TenantName name, Optional<Contact> contact) {
+ super(name);
+ this.contact = contact;
+ }
+
+ private User(UserTenant tenant) {
+ this(tenant.name(), tenant.contact());
+ }
+
+ @Override
+ public UserTenant get() {
+ return new UserTenant(name, contact);
+ }
+
+ public User with(Contact contact) {
+ return new User(name, Optional.of(contact));
+ }
+
}
- @Override
- public String toString() {
- return "tenant '" + name + "'";
+
+ /** A locked CloudTenant. */
+ public static class Cloud extends LockedTenant {
+
+ private final BillingInfo billingInfo;
+
+ private Cloud(TenantName name, BillingInfo billingInfo) {
+ super(name);
+ this.billingInfo = billingInfo;
+ }
+
+ private Cloud(CloudTenant tenant) {
+ this(tenant.name(), tenant.billingInfo());
+ }
+
+ @Override
+ public CloudTenant get() {
+ return new CloudTenant(name, billingInfo);
+ }
+
+ public Cloud with(BillingInfo billingInfo) {
+ return new Cloud(name, billingInfo);
+ }
+
}
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/TenantController.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/TenantController.java
index 5b3b7351604..fab5da7733e 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/TenantController.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/TenantController.java
@@ -60,7 +60,7 @@ public class TenantController {
for (TenantName name : curator.readTenantNames()) {
try (Lock lock = lock(name)) {
// Get while holding lock so that we know we're operating on a current version
- Optional<Tenant> optionalTenant = tenant(name);
+ Optional<Tenant> optionalTenant = get(name);
if (!optionalTenant.isPresent()) continue; // Deleted while updating, skip
Tenant tenant = optionalTenant.get();
@@ -97,23 +97,25 @@ public class TenantController {
}
/** Locks a tenant for modification and applies the given action. */
- public void lockIfPresent(TenantName name, Consumer<LockedTenant> action) {
+ public <T extends LockedTenant> void lockIfPresent(TenantName name, Class<T> token, Consumer<T> action) {
try (Lock lock = lock(name)) {
- tenant(name).map(tenant -> {
- tenant = tenant instanceof AthenzTenant ? (AthenzTenant) tenant : (UserTenant) tenant;
- if (tenant instanceof AthenzTenant) return new LockedTenant((AthenzTenant) tenant, lock);
- else return new LockedTenant((UserTenant) tenant, lock);
- }).ifPresent(action);
+ get(name).map(tenant -> LockedTenant.of(tenant, lock))
+ .map(token::cast)
+ .ifPresent(action);
}
}
/** Lock a tenant for modification and apply action. Throws if the tenant does not exist */
- public void lockOrThrow(TenantName name, Consumer<LockedTenant> action) {
+ public <T extends LockedTenant> void lockOrThrow(TenantName name, Class<T> token, Consumer<T> action) {
try (Lock lock = lock(name)) {
- action.accept(new LockedTenant(requireAthenzTenant(name), lock));
+ action.accept(token.cast(LockedTenant.of(require(name), lock)));
}
}
+ public Tenant require(TenantName name) {
+ return get(name).orElseThrow(() -> new IllegalArgumentException("No such tenant '" + name + "'."));
+ }
+
/** Replace and store any previous version of given tenant */
public void store(LockedTenant tenant) {
curator.writeTenant(tenant.get());
@@ -153,13 +155,13 @@ public class TenantController {
}
/** Find tenant by name */
- public Optional<Tenant> tenant(TenantName name) {
+ public Optional<Tenant> get(TenantName name) {
return curator.readTenant(name);
}
/** Find tenant by name */
- public Optional<Tenant> tenant(String name) {
- return tenant(TenantName.from(name));
+ public Optional<Tenant> get(String name) {
+ return get(TenantName.from(name));
}
/** Find Athenz tenant by name */
@@ -173,8 +175,8 @@ public class TenantController {
}
/** Update Athenz domain for tenant. Returns the updated tenant which must be explicitly stored */
- public LockedTenant withDomain(LockedTenant tenant, AthenzDomain newDomain, OktaAccessToken token) {
- AthenzTenant athenzTenant = (AthenzTenant) tenant.get();
+ public LockedTenant.Athenz withDomain(LockedTenant.Athenz tenant, AthenzDomain newDomain, OktaAccessToken token) {
+ AthenzTenant athenzTenant = tenant.get();
AthenzDomain existingDomain = athenzTenant.domain();
if (existingDomain.equals(newDomain)) return tenant;
Optional<Tenant> existingTenantWithNewDomain = tenantIn(newDomain);
@@ -216,10 +218,10 @@ public class TenantController {
}
private void requireNonExistent(TenantName name) {
- if (tenant(name).isPresent() ||
+ if (get(name).isPresent() ||
// Underscores are allowed in existing Athenz tenant names, but tenants with - and _ cannot co-exist. E.g.
// my-tenant cannot be created if my_tenant exists.
- tenant(dashToUnderscore(name.value())).isPresent()) {
+ get(dashToUnderscore(name.value())).isPresent()) {
throw new IllegalArgumentException("Tenant '" + name + "' already exists");
}
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ApplicationOwnershipConfirmer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ApplicationOwnershipConfirmer.java
index d5c84c38e91..ac71fca6de9 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ApplicationOwnershipConfirmer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ApplicationOwnershipConfirmer.java
@@ -105,7 +105,7 @@ public class ApplicationOwnershipConfirmer extends Maintainer {
}
private Tenant tenantOf(ApplicationId applicationId) {
- return controller().tenants().tenant(applicationId.tenant())
+ return controller().tenants().get(applicationId.tenant())
.orElseThrow(() -> new IllegalStateException("No tenant found for application " + applicationId));
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ContactInformationMaintainer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ContactInformationMaintainer.java
index a02f28e371d..efaf872271e 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ContactInformationMaintainer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ContactInformationMaintainer.java
@@ -1,6 +1,8 @@
// Copyright 2018 Yahoo Holdings. 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.vespa.hosted.controller.LockedTenant;
+import com.yahoo.vespa.hosted.controller.TenantController;
import com.yahoo.vespa.hosted.controller.api.identifiers.PropertyId;
import com.yahoo.vespa.hosted.controller.api.integration.organization.Contact;
import com.yahoo.vespa.hosted.controller.api.integration.organization.ContactRetriever;
@@ -35,14 +37,19 @@ public class ContactInformationMaintainer extends Maintainer {
@Override
protected void maintain() {
- for (Tenant tenant : controller().tenants().asList()) {
+ TenantController tenants = controller().tenants();
+ for (Tenant tenant : tenants.asList()) {
try {
- Optional<PropertyId> tenantPropertyId = Optional.empty();
- if (tenant instanceof AthenzTenant) {
- tenantPropertyId = ((AthenzTenant) tenant).propertyId();
+ switch (tenant.type()) {
+ case athenz: tenants.lockIfPresent(tenant.name(), LockedTenant.Athenz.class, lockedTenant ->
+ tenants.store(lockedTenant.with(contactRetriever.getContact(lockedTenant.get().propertyId()))));
+ return;
+ case user: tenants.lockIfPresent(tenant.name(), LockedTenant.User.class, lockedTenant ->
+ tenants.store(lockedTenant.with(contactRetriever.getContact(Optional.empty()))));
+ return;
+ case cloud: return;
+ default: throw new IllegalArgumentException("Unexpected tenant type '" + tenant.type() + "'.");
}
- Contact contact = contactRetriever.getContact(tenantPropertyId);
- controller().tenants().lockIfPresent(tenant.name(), lockedTenant -> controller().tenants().store(lockedTenant.with(contact)));
} catch (Exception e) {
log.log(LogLevel.WARNING, "Failed to update contact information for " + tenant + ": " +
Exceptions.toMessageString(e) + ". Retrying in " +
@@ -51,5 +58,4 @@ public class ContactInformationMaintainer extends Maintainer {
}
}
-
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentIssueReporter.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentIssueReporter.java
index 3f5c2d1f317..06b1a4f9827 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentIssueReporter.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentIssueReporter.java
@@ -6,8 +6,6 @@ import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.SystemName;
import com.yahoo.vespa.hosted.controller.Application;
import com.yahoo.vespa.hosted.controller.Controller;
-import com.yahoo.vespa.hosted.controller.api.identifiers.PropertyId;
-import com.yahoo.vespa.hosted.controller.api.integration.organization.Contact;
import com.yahoo.vespa.hosted.controller.api.integration.organization.DeploymentIssues;
import com.yahoo.vespa.hosted.controller.api.integration.organization.IssueId;
import com.yahoo.vespa.hosted.controller.api.integration.organization.User;
@@ -106,7 +104,7 @@ public class DeploymentIssueReporter extends Maintainer {
}
private Tenant ownerOf(ApplicationId applicationId) {
- return controller().tenants().tenant(applicationId.tenant())
+ return controller().tenants().get(applicationId.tenant())
.orElseThrow(() -> new IllegalStateException("No tenant found for application " + applicationId));
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
index 6fc5cc645e8..37c0847f167 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
@@ -30,6 +30,7 @@ import com.yahoo.vespa.config.SlimeUtils;
import com.yahoo.vespa.hosted.controller.AlreadyExistsException;
import com.yahoo.vespa.hosted.controller.Application;
import com.yahoo.vespa.hosted.controller.Controller;
+import com.yahoo.vespa.hosted.controller.LockedTenant;
import com.yahoo.vespa.hosted.controller.NotExistsException;
import com.yahoo.vespa.hosted.controller.api.ActivateResult;
import com.yahoo.vespa.hosted.controller.api.application.v4.ApplicationResource;
@@ -333,7 +334,7 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
}
private HttpResponse tenant(String tenantName, HttpRequest request) {
- return controller.tenants().tenant(TenantName.from(tenantName))
+ return controller.tenants().get(TenantName.from(tenantName))
.map(tenant -> tenant(tenant, request, true))
.orElseGet(() -> ErrorResponse.notFoundError("Tenant '" + tenantName + "' does not exist"));
}
@@ -756,7 +757,7 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
Inspector requestData = toSlime(request.getData()).get();
OktaAccessToken token = requireOktaAccessToken(request, "Could not update " + tenantName);
- controller.tenants().lockOrThrow(tenant.get().name(), lockedTenant -> {
+ controller.tenants().lockOrThrow(tenant.get().name(), LockedTenant.Athenz.class, lockedTenant -> {
lockedTenant = lockedTenant.with(new Property(mandatory("property", requestData).asString()));
lockedTenant = controller.tenants().withDomain(
lockedTenant,
@@ -983,7 +984,7 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
}
private HttpResponse deleteTenant(String tenantName, HttpRequest request) {
- Optional<Tenant> tenant = controller.tenants().tenant(tenantName);
+ Optional<Tenant> tenant = controller.tenants().get(tenantName);
if ( ! tenant.isPresent()) return ErrorResponse.notFoundError("Could not delete tenant '" + tenantName + "': Tenant not found"); // NOTE: The Jersey implementation would silently ignore this
@@ -1099,7 +1100,7 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
}
private Tenant getTenantOrThrow(String tenantName) {
- return controller.tenants().tenant(tenantName)
+ return controller.tenants().get(tenantName)
.orElseThrow(() -> new NotExistsException(new TenantId(tenantName)));
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/filter/ControllerAuthorizationFilter.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/filter/ControllerAuthorizationFilter.java
index 77e626509b3..3d0e21617c5 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/filter/ControllerAuthorizationFilter.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/filter/ControllerAuthorizationFilter.java
@@ -158,7 +158,7 @@ public class ControllerAuthorizationFilter extends CorsRequestFilterBase {
}
private void verifyIsTenantAdmin(AthenzPrincipal principal, TenantName name) {
- tenantController.tenant(name)
+ tenantController.get(name)
.ifPresent(tenant -> {
if (!isTenantAdmin(principal.getIdentity(), tenant)) {
throw new ForbiddenException("Tenant admin or Vespa operator role required");
@@ -182,7 +182,7 @@ public class ControllerAuthorizationFilter extends CorsRequestFilterBase {
private void verifyIsTenantPipelineOperator(AthenzPrincipal principal,
TenantName name,
ApplicationName application) {
- tenantController.tenant(name)
+ tenantController.get(name)
.ifPresent(tenant -> verifyIsTenantPipelineOperator(principal.getIdentity(), tenant, application));
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/AthenzTenant.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/AthenzTenant.java
index abe09090761..f8edeee5939 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/AthenzTenant.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/AthenzTenant.java
@@ -75,4 +75,10 @@ public class AthenzTenant extends Tenant {
}
return name;
}
+
+ @Override
+ public Type type() {
+ return Type.athenz;
+ }
+
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/CloudTenant.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/CloudTenant.java
index da184f63180..cf68c8f3bf9 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/CloudTenant.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/CloudTenant.java
@@ -29,4 +29,9 @@ public class CloudTenant extends Tenant {
/** Returns the billing info for this tenant. */
public BillingInfo billingInfo() { return billingInfo; }
+ @Override
+ public Type type() {
+ return Type.cloud;
+ }
+
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/Tenant.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/Tenant.java
index a02d3c7afe7..19b7229515b 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/Tenant.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/Tenant.java
@@ -34,6 +34,8 @@ public abstract class Tenant {
return contact;
}
+ public abstract Type type();
+
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -55,4 +57,19 @@ public abstract class Tenant {
}
return name;
}
+
+
+ public enum Type {
+
+ /** Tenant authenticated through Athenz. */
+ athenz,
+
+ /** Tenant authenticated through Okta, as a user. */
+ user,
+
+ /** Tenant authenticated through some cloud identity provider. */
+ cloud;
+
+ }
+
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/UserTenant.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/UserTenant.java
index 47e5580fbe4..ac8b73ff43d 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/UserTenant.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/UserTenant.java
@@ -21,6 +21,11 @@ public class UserTenant extends Tenant {
super(name, contact);
}
+ @Override
+ public Type type() {
+ return Type.user;
+ }
+
public UserTenant(TenantName name) {
super(name, Optional.empty());
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java
index 63a9d0ce905..3e3e58092c3 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java
@@ -114,7 +114,7 @@ public class ControllerTest {
applications = tester.controller().applications();
- assertNotNull(tester.controller().tenants().tenant(TenantName.from("tenant1")));
+ assertNotNull(tester.controller().tenants().get(TenantName.from("tenant1")));
assertNotNull(applications.get(ApplicationId.from(TenantName.from("tenant1"),
ApplicationName.from("application1"),
InstanceName.from("default"))));
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTester.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTester.java
index 615fb017363..e573c12af3b 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTester.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTester.java
@@ -249,14 +249,14 @@ public final class ControllerTester {
public TenantName createTenant(String tenantName, String domainName, Long propertyId, Optional<Contact> contact) {
TenantName name = TenantName.from(tenantName);
- Optional<Tenant> existing = controller().tenants().tenant(name);
+ Optional<Tenant> existing = controller().tenants().get(name);
if (existing.isPresent()) return name;
AthenzTenant tenant = AthenzTenant.create(name, createDomain(domainName), new Property("Property"+propertyId),
Optional.ofNullable(propertyId)
.map(Object::toString)
.map(PropertyId::new), contact);
controller().tenants().create(tenant, new OktaAccessToken("okta-token"));
- assertNotNull(controller().tenants().tenant(name));
+ assertNotNull(controller().tenants().get(name));
return name;
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java
index c0c2d4043d9..705fc8adbac 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java
@@ -22,6 +22,7 @@ import com.yahoo.vespa.athenz.api.OktaAccessToken;
import com.yahoo.vespa.config.SlimeUtils;
import com.yahoo.vespa.hosted.controller.Application;
import com.yahoo.vespa.hosted.controller.ApplicationController;
+import com.yahoo.vespa.hosted.controller.LockedTenant;
import com.yahoo.vespa.hosted.controller.api.application.v4.EnvironmentResource;
import com.yahoo.vespa.hosted.controller.api.identifiers.Property;
import com.yahoo.vespa.hosted.controller.api.identifiers.PropertyId;
@@ -1541,7 +1542,9 @@ public class ApplicationApiTest extends ControllerContainerTest {
private void updateContactInformation() {
Contact contact = new Contact(URI.create("www.contacts.tld/1234"), URI.create("www.properties.tld/1234"), URI.create("www.issues.tld/1234"), List.of(List.of("alice"), List.of("bob")), "queue", Optional.empty());
- tester.controller().tenants().lockIfPresent(TenantName.from("tenant2"), lockedTenant -> tester.controller().tenants().store(lockedTenant.with(contact)));
+ tester.controller().tenants().lockIfPresent(TenantName.from("tenant2"),
+ LockedTenant.Athenz.class,
+ lockedTenant -> tester.controller().tenants().store(lockedTenant.with(contact)));
}
private void registerContact(long propertyId) {