aboutsummaryrefslogtreecommitdiffstats
path: root/configserver/src/main/java/com
diff options
context:
space:
mode:
Diffstat (limited to 'configserver/src/main/java/com')
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java28
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/TenantHandler.java26
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ConfigServerMaintenance.java29
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/Maintainer.java73
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/TenantsMaintainer.java19
5 files changed, 154 insertions, 21 deletions
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java b/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java
index 4f8d7818316..28718ee7154 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java
@@ -58,6 +58,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
+import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -65,6 +66,7 @@ import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
+import java.util.stream.Collectors;
/**
* The API for managing applications.
@@ -364,6 +366,32 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye
return session.getSessionId();
}
+
+ // ---------------- Tenant operations ----------------------------------------------------------------
+
+ public Set<TenantName> removeUnusedTenants() {
+ Set<TenantName> tenantsToBeDeleted = tenantRepository.getAllTenantNames().stream()
+ .filter(tenantName -> activeApplications(tenantName).isEmpty())
+ .filter(tenantName -> !tenantName.equals(TenantName.defaultName())) // Not allowed to remove 'default' tenant
+ .collect(Collectors.toSet());
+ tenantsToBeDeleted.forEach(tenantRepository::deleteTenant);
+ return tenantsToBeDeleted;
+ }
+
+ public void deleteTenant(TenantName tenantName) {
+ List<ApplicationId> activeApplications = activeApplications(tenantName);
+ if (activeApplications.isEmpty())
+ tenantRepository.deleteTenant(tenantName);
+ else
+ throw new IllegalArgumentException("Cannot delete tenant '" + tenantName + "', it has active applications: " + activeApplications);
+ }
+
+ private List<ApplicationId> activeApplications(TenantName tenantName) {
+ return tenantRepository.getTenant(tenantName).getApplicationRepo().listApplications();
+ }
+
+ // ---------------- Misc operations ----------------------------------------------------------------
+
public Tenant verifyTenantAndApplication(ApplicationId applicationId) {
TenantName tenantName = applicationId.tenant();
if (!tenantRepository.checkThatTenantExists(tenantName)) {
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/TenantHandler.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/TenantHandler.java
index 3857fea9d14..c8e9da1265b 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/TenantHandler.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/TenantHandler.java
@@ -1,18 +1,15 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.config.server.http.v2;
-import java.util.List;
import com.google.inject.Inject;
-import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.TenantName;
import com.yahoo.container.jdisc.HttpRequest;
import com.yahoo.container.jdisc.HttpResponse;
import com.yahoo.jdisc.application.BindingMatch;
-import com.yahoo.vespa.config.server.tenant.Tenant;
+import com.yahoo.vespa.config.server.ApplicationRepository;
import com.yahoo.vespa.config.server.tenant.TenantRepository;
import com.yahoo.yolean.Exceptions;
-import com.yahoo.vespa.config.server.application.TenantApplications;
import com.yahoo.vespa.config.server.http.BadRequestException;
import com.yahoo.vespa.config.server.http.HttpHandler;
import com.yahoo.vespa.config.server.http.InternalServerException;
@@ -27,11 +24,13 @@ public class TenantHandler extends HttpHandler {
private static final String TENANT_NAME_REGEXP = "[\\w-]+";
private final TenantRepository tenantRepository;
+ private final ApplicationRepository applicationRepository;
@Inject
- public TenantHandler(HttpHandler.Context ctx, TenantRepository tenantRepository) {
+ public TenantHandler(Context ctx, TenantRepository tenantRepository, ApplicationRepository applicationRepository) {
super(ctx);
this.tenantRepository = tenantRepository;
+ this.applicationRepository = applicationRepository;
}
@Override
@@ -62,22 +61,7 @@ public class TenantHandler extends HttpHandler {
protected HttpResponse handleDELETE(HttpRequest request) {
final TenantName tenantName = getTenantNameFromRequest(request);
Utils.checkThatTenantExists(tenantRepository, tenantName);
- // TODO: Move logic to ApplicationRepository
- Tenant tenant = tenantRepository.getTenant(tenantName);
- TenantApplications applicationRepo = tenant.getApplicationRepo();
- final List<ApplicationId> activeApplications = applicationRepo.listApplications();
- if (activeApplications.isEmpty()) {
- try {
- tenantRepository.deleteTenant(tenantName);
- } catch (IllegalArgumentException e) {
- throw e;
- } catch (Exception e) {
- throw new InternalServerException(Exceptions.toMessageString(e));
- }
- } else {
- throw new BadRequestException("Cannot delete tenant '" + tenantName + "', as it has active applications: " +
- activeApplications);
- }
+ applicationRepository.deleteTenant(tenantName);
return new TenantDeleteResponse(tenantName);
}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ConfigServerMaintenance.java b/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ConfigServerMaintenance.java
new file mode 100644
index 00000000000..c8b3bc824a8
--- /dev/null
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/ConfigServerMaintenance.java
@@ -0,0 +1,29 @@
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.config.server.maintenance;
+
+import com.yahoo.cloud.config.ConfigserverConfig;
+import com.yahoo.component.AbstractComponent;
+import com.yahoo.vespa.config.server.ApplicationRepository;
+import com.yahoo.vespa.curator.Curator;
+
+import java.time.Duration;
+
+public class ConfigServerMaintenance extends AbstractComponent {
+
+ private final TenantsMaintainer tenantsMaintainer;
+
+ @SuppressWarnings("unused") // instantiated by Dependency Injection
+ public ConfigServerMaintenance(ConfigserverConfig configserverConfig,
+ ApplicationRepository applicationRepository,
+ Curator curator) {
+ tenantsMaintainer = new TenantsMaintainer(applicationRepository,
+ curator,
+ Duration.ofMinutes(configserverConfig.tenantsMaintainerIntervalMinutes()));
+ }
+
+ @Override
+ public void deconstruct() {
+ tenantsMaintainer.deconstruct();
+ }
+
+}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/Maintainer.java b/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/Maintainer.java
new file mode 100644
index 00000000000..ce0811184a3
--- /dev/null
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/Maintainer.java
@@ -0,0 +1,73 @@
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.config.server.maintenance;
+
+import com.google.common.util.concurrent.UncheckedTimeoutException;
+import com.yahoo.component.AbstractComponent;
+import com.yahoo.concurrent.DaemonThreadFactory;
+import com.yahoo.path.Path;
+import com.yahoo.vespa.config.server.ApplicationRepository;
+import com.yahoo.vespa.curator.Curator;
+import com.yahoo.vespa.curator.Lock;
+
+import java.time.Duration;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public abstract class Maintainer extends AbstractComponent implements Runnable {
+
+ protected static final Logger log = Logger.getLogger(Maintainer.class.getName());
+ private static final Path root = Path.fromString("/configserver/v1/");
+ private static final com.yahoo.path.Path lockRoot = root.append("locks");
+
+ private final Duration maintenanceInterval;
+ private final ScheduledExecutorService service;
+ protected final ApplicationRepository applicationRepository;
+ protected final Curator curator;
+
+ Maintainer(ApplicationRepository applicationRepository, Curator curator, Duration interval) {
+ this.applicationRepository = applicationRepository;
+ this.curator = curator;
+ this.maintenanceInterval = interval;
+ service = new ScheduledThreadPoolExecutor(1, new DaemonThreadFactory(name()));
+ service.scheduleAtFixedRate(this, interval.toMillis(), interval.toMillis(), TimeUnit.MILLISECONDS);
+ }
+
+ @Override
+ @SuppressWarnings("try")
+ public void run() {
+ try {
+ Path path = lockRoot.append(name());
+ try (Lock lock = new Lock(path.toString(), curator)) {
+ maintain();
+ }
+ } catch (UncheckedTimeoutException e) {
+ // another config server instance is running this job at the moment; ok
+ } catch (Throwable t) {
+ log.log(Level.WARNING, this + " failed. Will retry in " + maintenanceInterval.toMinutes() + " minutes", t);
+ }
+ }
+
+ @Override
+ public void deconstruct() {
+ this.service.shutdown();
+ }
+
+ /**
+ * Called once each time this maintenance job should run
+ */
+ protected abstract void maintain();
+
+ public String name() { return this.getClass().getSimpleName(); }
+
+ /**
+ * Returns the name of this
+ */
+ @Override
+ public final String toString() {
+ return name();
+ }
+
+}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/TenantsMaintainer.java b/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/TenantsMaintainer.java
new file mode 100644
index 00000000000..e06bf530486
--- /dev/null
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/maintenance/TenantsMaintainer.java
@@ -0,0 +1,19 @@
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.config.server.maintenance;
+
+import com.yahoo.vespa.config.server.ApplicationRepository;
+import com.yahoo.vespa.curator.Curator;
+
+import java.time.Duration;
+
+public class TenantsMaintainer extends Maintainer {
+
+ public TenantsMaintainer(ApplicationRepository applicationRepository, Curator curator, Duration interval) {
+ super(applicationRepository, curator, interval);
+ }
+
+ @Override
+ protected void maintain() {
+ applicationRepository.removeUnusedTenants();
+ }
+}