diff options
3 files changed, 27 insertions, 3 deletions
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/deployment/ApplicationStore.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/deployment/ApplicationStore.java index 28a803fd43d..dd9f8c38802 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/deployment/ApplicationStore.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/deployment/ApplicationStore.java @@ -5,9 +5,9 @@ import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.ApplicationName; import com.yahoo.config.provision.TenantName; import com.yahoo.config.provision.zone.ZoneId; +import com.yahoo.vespa.hosted.controller.api.identifiers.DeploymentId; import java.time.Instant; -import java.util.Collection; import java.util.Optional; /** @@ -59,6 +59,12 @@ public interface ApplicationStore { /** Marks the given application as deleted, and eligible for meta data GC at a later time. */ void putMetaTombstone(TenantName tenant, ApplicationName application, Instant now); + /** Stores the given manual deployment meta data with the current time as part of the path. */ + void putMeta(DeploymentId id, Instant now, byte[] metaZip); + + /** Marks the given manual deployment as deleted, and eligible for meta data GC at a later time. */ + void putMetaTombstone(DeploymentId id, Instant now); + /** Prunes meta data such that only what was active at the given instant, and anything newer, is retained. */ void pruneMeta(Instant oldest); 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 4cd8f56f53d..d8abc77ed06 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 @@ -527,6 +527,11 @@ public class ApplicationController { Optional<Quota> quota = billingController.getQuota(application.tenant(), zone.environment()); + if (zone.environment().isManuallyDeployed()) + controller.applications().applicationStore().putMeta(new DeploymentId(application, zone), + clock.instant(), + applicationPackage.metaDataZip()); + ConfigServer.PreparedApplication preparedApplication = configServer.deploy(new DeploymentData(application, zone, applicationPackage.zippedContent(), platform, endpoints, endpointCertificateMetadata, dockerImageRepo, domain, applicationRoles, quota)); @@ -713,12 +718,14 @@ public class ApplicationController { * @return the application with the deployment in the given zone removed */ private LockedApplication deactivate(LockedApplication application, InstanceName instanceName, ZoneId zone) { + DeploymentId id = new DeploymentId(application.get().id().instance(instanceName), zone); try { - configServer.deactivate(new DeploymentId(application.get().id().instance(instanceName), zone)); + configServer.deactivate(id); } catch (NotFoundException ignored) { // ok; already gone } finally { controller.routing().policies().refresh(application.get().id().instance(instanceName), application.get().deploymentSpec(), zone); + applicationStore.putMetaTombstone(id, clock.instant()); } return application.with(instanceName, instance -> instance.withoutDeploymentIn(zone)); } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ApplicationStoreMock.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ApplicationStoreMock.java index be0cd975190..81bda23146e 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ApplicationStoreMock.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ApplicationStoreMock.java @@ -6,6 +6,7 @@ import com.yahoo.config.provision.ApplicationName; import com.yahoo.config.provision.InstanceName; import com.yahoo.config.provision.TenantName; import com.yahoo.config.provision.zone.ZoneId; +import com.yahoo.vespa.hosted.controller.api.identifiers.DeploymentId; import com.yahoo.vespa.hosted.controller.api.integration.deployment.ApplicationStore; import com.yahoo.vespa.hosted.controller.api.integration.deployment.ApplicationVersion; import com.yahoo.vespa.hosted.controller.api.integration.deployment.TesterId; @@ -14,7 +15,6 @@ import java.time.Instant; import java.util.Map; import java.util.NavigableMap; import java.util.Optional; -import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentSkipListMap; @@ -32,6 +32,7 @@ public class ApplicationStoreMock implements ApplicationStore { private final Map<ApplicationId, Map<ApplicationVersion, byte[]>> store = new ConcurrentHashMap<>(); private final Map<ApplicationId, Map<ZoneId, byte[]>> devStore = new ConcurrentHashMap<>(); private final Map<ApplicationId, NavigableMap<Instant, byte[]>> meta = new ConcurrentHashMap<>(); + private final Map<DeploymentId, NavigableMap<Instant, byte[]>> metaManual = new ConcurrentHashMap<>(); private static ApplicationId appId(TenantName tenant, ApplicationName application) { return ApplicationId.from(tenant, application, InstanceName.defaultName()); @@ -120,6 +121,16 @@ public class ApplicationStoreMock implements ApplicationStore { } @Override + public void putMeta(DeploymentId id, Instant now, byte[] metaZip) { + metaManual.computeIfAbsent(id, __ -> new ConcurrentSkipListMap<>()).put(now, metaZip); + } + + @Override + public void putMetaTombstone(DeploymentId id, Instant now) { + putMeta(id, now, tombstone); + } + + @Override public void pruneMeta(Instant oldest) { for (ApplicationId id : meta.keySet()) { Instant activeAtOldest = meta.get(id).lowerKey(oldest); |