aboutsummaryrefslogtreecommitdiffstats
path: root/controller-server
diff options
context:
space:
mode:
authorMartin Polden <mpolden@mpolden.no>2018-04-06 09:37:43 +0200
committerMartin Polden <mpolden@mpolden.no>2018-04-06 10:37:45 +0200
commitc9211c079703b1ef161ebf17cc94c15ef867bea2 (patch)
tree3b0c1ccfd60cd45a0d240cd5b443974dcb6aa02b /controller-server
parentf450bfea2e0187278f9e44a53174a757cff8b267 (diff)
Write tenant to ZooKeeper
Diffstat (limited to 'controller-server')
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Controller.java6
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/ControllerDbProxy.java93
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/CuratorDb.java55
3 files changed, 152 insertions, 2 deletions
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Controller.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Controller.java
index b568b1ca6e4..2f33cf6d6ea 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Controller.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Controller.java
@@ -26,6 +26,7 @@ import com.yahoo.vespa.hosted.controller.api.integration.routing.RotationStatus;
import com.yahoo.vespa.hosted.controller.api.integration.routing.RoutingGenerator;
import com.yahoo.vespa.hosted.controller.api.integration.zone.ZoneRegistry;
import com.yahoo.vespa.hosted.controller.persistence.ControllerDb;
+import com.yahoo.vespa.hosted.controller.persistence.ControllerDbProxy;
import com.yahoo.vespa.hosted.controller.persistence.CuratorDb;
import com.yahoo.vespa.hosted.controller.versions.VersionStatus;
import com.yahoo.vespa.hosted.controller.versions.VespaVersion;
@@ -132,11 +133,12 @@ public class Controller extends AbstractComponent {
this.clock = clock;
this.athenzClientFactory = athenzClientFactory;
- applicationController = new ApplicationController(this, db, curator, athenzClientFactory,
+ ControllerDbProxy dbProxy = new ControllerDbProxy(db, curator);
+ applicationController = new ApplicationController(this, dbProxy, curator, athenzClientFactory,
rotationsConfig,
nameService, configServerClient, artifactRepository,
routingGenerator, clock);
- tenantController = new TenantController(this, db, curator, athenzClientFactory);
+ tenantController = new TenantController(this, dbProxy, curator, athenzClientFactory);
}
/** Returns the instance controlling tenants */
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/ControllerDbProxy.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/ControllerDbProxy.java
new file mode 100644
index 00000000000..4424433662e
--- /dev/null
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/ControllerDbProxy.java
@@ -0,0 +1,93 @@
+// 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.persistence;
+
+import com.yahoo.config.provision.ApplicationId;
+import com.yahoo.config.provision.TenantName;
+import com.yahoo.vespa.hosted.controller.Application;
+import com.yahoo.vespa.hosted.controller.tenant.AthenzTenant;
+import com.yahoo.vespa.hosted.controller.tenant.Tenant;
+import com.yahoo.vespa.hosted.controller.tenant.UserTenant;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Controller database implementation that writes to both a ControllerDb and a CuratorDb.
+ *
+ * @author mpolden
+ */
+// TODO: Remove this and ControllerDb and use only CuratorDb
+public class ControllerDbProxy implements ControllerDb {
+
+ private final ControllerDb db;
+ private final CuratorDb curator;
+
+ public ControllerDbProxy(ControllerDb db, CuratorDb curator) {
+ this.db = db;
+ this.curator = curator;
+ }
+
+ @Override
+ public void createTenant(UserTenant tenant) {
+ db.createTenant(tenant);
+ curator.writeTenant(tenant);
+ }
+
+ @Override
+ public void createTenant(AthenzTenant tenant) {
+ db.createTenant(tenant);
+ curator.writeTenant(tenant);
+ }
+
+ @Override
+ public void updateTenant(AthenzTenant tenant) throws PersistenceException {
+ db.updateTenant(tenant);
+ curator.writeTenant(tenant);
+ }
+
+ @Override
+ public void deleteTenant(TenantName name) throws PersistenceException {
+ db.deleteTenant(name);
+ curator.removeTenant(name);
+ }
+
+ @Override
+ public Optional<Tenant> getTenant(TenantName name) throws PersistenceException {
+ return db.getTenant(name);
+ }
+
+ @Override
+ public Optional<AthenzTenant> getAthenzTenant(TenantName name) throws PersistenceException {
+ return db.getAthenzTenant(name);
+ }
+
+ @Override
+ public List<Tenant> listTenants() {
+ return db.listTenants();
+ }
+
+ @Override
+ public void store(Application application) {
+ db.store(application);
+ }
+
+ @Override
+ public void deleteApplication(ApplicationId applicationId) {
+ db.deleteApplication(applicationId);
+ }
+
+ @Override
+ public Optional<Application> getApplication(ApplicationId applicationId) {
+ return db.getApplication(applicationId);
+ }
+
+ @Override
+ public List<Application> listApplications() {
+ return db.listApplications();
+ }
+
+ @Override
+ public List<Application> listApplications(TenantName name) {
+ return db.listApplications(name);
+ }
+}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/CuratorDb.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/CuratorDb.java
index 558e30876df..9c585ad1269 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/CuratorDb.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/CuratorDb.java
@@ -11,6 +11,9 @@ import com.yahoo.vespa.config.SlimeUtils;
import com.yahoo.vespa.curator.Curator;
import com.yahoo.vespa.curator.Lock;
import com.yahoo.vespa.hosted.controller.application.DeploymentJobs;
+import com.yahoo.vespa.hosted.controller.tenant.AthenzTenant;
+import com.yahoo.vespa.hosted.controller.tenant.Tenant;
+import com.yahoo.vespa.hosted.controller.tenant.UserTenant;
import com.yahoo.vespa.hosted.controller.versions.VersionStatus;
import com.yahoo.vespa.hosted.controller.versions.VespaVersion;
@@ -29,6 +32,7 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
+import java.util.stream.Collectors;
/**
* Curator backed database for storing working state shared between controller servers.
@@ -44,12 +48,15 @@ public class CuratorDb {
private static final Path lockRoot = root.append("locks");
+ private static final Path tenantRoot = root.append("tenants");
+
private static final Duration defaultLockTimeout = Duration.ofMinutes(5);
private final StringSetSerializer stringSetSerializer = new StringSetSerializer();
private final JobQueueSerializer jobQueueSerializer = new JobQueueSerializer();
private final VersionStatusSerializer versionStatusSerializer = new VersionStatusSerializer();
private final ConfidenceOverrideSerializer confidenceOverrideSerializer = new ConfidenceOverrideSerializer();
+ private final TenantSerializer tenantSerializer = new TenantSerializer();
private final Curator curator;
@@ -188,6 +195,50 @@ public class CuratorDb {
.orElseGet(Collections::emptyMap);
}
+ public void writeTenant(UserTenant tenant) {
+ try {
+ curator.set(tenantPath(tenant.name()), SlimeUtils.toJsonBytes(tenantSerializer.toSlime(tenant)));
+ } catch (IOException e) {
+ throw new UncheckedIOException("Failed to write " + tenant.toString(), e);
+ }
+ }
+
+ public Optional<UserTenant> readUserTenant(TenantName name) {
+ return readSlime(tenantPath(name)).map(tenantSerializer::userTenantFrom);
+ }
+
+ public void writeTenant(AthenzTenant tenant) {
+ try {
+ curator.set(tenantPath(tenant.name()), SlimeUtils.toJsonBytes(tenantSerializer.toSlime(tenant)));
+ } catch (IOException e) {
+ throw new UncheckedIOException("Failed to write " + tenant.toString(), e);
+ }
+ }
+
+ public Optional<AthenzTenant> readAthenzTenant(TenantName name) {
+ return readSlime(tenantPath(name)).map(tenantSerializer::athenzTenantFrom);
+ }
+
+ public Optional<Tenant> readTenant(TenantName name) {
+ if (name.value().startsWith(Tenant.userPrefix)) {
+ return readUserTenant(name).map(Tenant.class::cast);
+ }
+ return readAthenzTenant(name).map(Tenant.class::cast);
+ }
+
+ public List<Tenant> readTenants() {
+ return curator.getChildren(tenantRoot).stream()
+ .map(TenantName::from)
+ .map(this::readTenant)
+ .filter(Optional::isPresent)
+ .map(Optional::get)
+ .collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
+ }
+
+ public void removeTenant(TenantName name) {
+ curator.delete(tenantPath(name));
+ }
+
// The following methods are called by internal code
@SuppressWarnings("unused")
@@ -286,4 +337,8 @@ public class CuratorDb {
private static Path openStackServerPoolPath() {
return root.append("openStackServerPool");
}
+
+ private static Path tenantPath(TenantName name) {
+ return tenantRoot.append(name.value());
+ }
}