From dfdbfe1162bd982468a8fa46961d5dcf42ab01a8 Mon Sep 17 00:00:00 2001 From: Martin Polden Date: Fri, 11 Oct 2019 13:04:26 +0200 Subject: Clean up container endpoints cache on application removal --- .../vespa/config/server/ApplicationRepository.java | 6 +- .../modelfactory/ActivatedModelsBuilder.java | 2 - .../server/tenant/ContainerEndpointsCache.java | 32 +++++----- .../vespa/config/server/tenant/Rotations.java | 69 ---------------------- 4 files changed, 20 insertions(+), 89 deletions(-) delete mode 100644 configserver/src/main/java/com/yahoo/vespa/config/server/tenant/Rotations.java (limited to 'configserver') 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 2734e5ad6b8..465344a6d76 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 @@ -53,7 +53,7 @@ import com.yahoo.vespa.config.server.session.RemoteSessionRepo; import com.yahoo.vespa.config.server.session.Session; import com.yahoo.vespa.config.server.session.SessionFactory; import com.yahoo.vespa.config.server.session.SilentDeployLogger; -import com.yahoo.vespa.config.server.tenant.Rotations; +import com.yahoo.vespa.config.server.tenant.ContainerEndpointsCache; import com.yahoo.vespa.config.server.tenant.Tenant; import com.yahoo.vespa.config.server.tenant.TenantRepository; import com.yahoo.vespa.curator.Lock; @@ -70,10 +70,8 @@ import java.time.Duration; import java.time.Instant; import java.util.Arrays; import java.util.Collection; -import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.logging.Level; @@ -370,7 +368,7 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye }).orElse(true); NestedTransaction transaction = new NestedTransaction(); - transaction.add(new Rotations(tenant.getCurator(), tenant.getPath()).delete(applicationId)); // TODO: Not unit tested + transaction.add(new ContainerEndpointsCache(tenant.getPath(), tenant.getCurator()).delete(applicationId)); // TODO: Not unit tested // (When rotations are updated in zk, we need to redeploy the zone app, on the right config server // this is done asynchronously in application maintenance by the node repository) transaction.add(tenantApplications.createDeleteTransaction(applicationId)); diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ActivatedModelsBuilder.java b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ActivatedModelsBuilder.java index 94cd30de28b..bc6419f230f 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ActivatedModelsBuilder.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ActivatedModelsBuilder.java @@ -27,7 +27,6 @@ import com.yahoo.vespa.config.server.provision.HostProvisionerProvider; import com.yahoo.vespa.config.server.session.SessionZooKeeperClient; import com.yahoo.vespa.config.server.session.SilentDeployLogger; import com.yahoo.vespa.config.server.tenant.ContainerEndpointsCache; -import com.yahoo.vespa.config.server.tenant.Rotations; import com.yahoo.vespa.config.server.tenant.TenantRepository; import com.yahoo.vespa.config.server.tenant.TlsSecretsKeys; import com.yahoo.vespa.curator.Curator; @@ -132,7 +131,6 @@ public class ActivatedModelsBuilder extends ModelsBuilder { configserverConfig.athenzDnsSuffix(), configserverConfig.hostedVespa(), zone(), - new Rotations(curator, TenantRepository.getTenantPath(tenant)).readRotationsFromZooKeeper(applicationId), ImmutableSet.copyOf(new ContainerEndpointsCache(TenantRepository.getTenantPath(tenant), curator).read(applicationId)), false, // We may be bootstrapping, but we only know and care during prepare false, // Always false, assume no one uses it when activating diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/ContainerEndpointsCache.java b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/ContainerEndpointsCache.java index 9bce1224d96..65ebb38c2d0 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/ContainerEndpointsCache.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/ContainerEndpointsCache.java @@ -6,6 +6,8 @@ import com.yahoo.config.provision.ApplicationId; import com.yahoo.path.Path; import com.yahoo.vespa.config.SlimeUtils; import com.yahoo.vespa.curator.Curator; +import com.yahoo.vespa.curator.transaction.CuratorOperations; +import com.yahoo.vespa.curator.transaction.CuratorTransaction; import java.io.IOException; import java.io.UncheckedIOException; @@ -13,15 +15,12 @@ import java.util.List; /** - * Persists assignment of rotations to an application to ZooKeeper. + * Persists assignment of rotations to an application in ZooKeeper. + * * The entries are {@link ContainerEndpoint} instances, which keep track of the container * cluster that is the target, the endpoint name, and the rotation used to * give availability to that cluster. * - * This is v2 of that storage in a new directory. Previously we only stored - * the name of the rotation, since all the other information could be - * calculated runtime. - * * @author ogronnesby */ public class ContainerEndpointsCache { @@ -35,27 +34,32 @@ public class ContainerEndpointsCache { } public List read(ApplicationId applicationId) { - final var optionalData = curator.getData(applicationPath(applicationId)); - return optionalData - .map(SlimeUtils::jsonToSlime) - .map(ContainerEndpointSerializer::endpointListFromSlime) - .orElseGet(List::of); + var optionalData = curator.getData(containerEndpointsPath(applicationId)); + return optionalData.map(SlimeUtils::jsonToSlime) + .map(ContainerEndpointSerializer::endpointListFromSlime) + .orElseGet(List::of); } public void write(ApplicationId applicationId, List endpoints) { if (endpoints.isEmpty()) return; - final var slime = ContainerEndpointSerializer.endpointListToSlime(endpoints); + var slime = ContainerEndpointSerializer.endpointListToSlime(endpoints); try { - final var bytes = SlimeUtils.toJsonBytes(slime); - curator.set(applicationPath(applicationId), bytes); + var bytes = SlimeUtils.toJsonBytes(slime); + curator.set(containerEndpointsPath(applicationId), bytes); } catch (IOException e) { throw new UncheckedIOException("Error writing endpoints of: " + applicationId, e); } } - private Path applicationPath(ApplicationId applicationId) { + /** Returns a transaction which deletes these rotations if they exist */ + public CuratorTransaction delete(ApplicationId application) { + if ( ! curator.exists(containerEndpointsPath(application))) return CuratorTransaction.empty(curator); + return CuratorTransaction.from(CuratorOperations.delete(containerEndpointsPath(application).getAbsolute()), curator); + } + + private Path containerEndpointsPath(ApplicationId applicationId) { return cachePath.append(applicationId.serializedForm()); } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/Rotations.java b/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/Rotations.java deleted file mode 100644 index 1fb7e9bacc7..00000000000 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/tenant/Rotations.java +++ /dev/null @@ -1,69 +0,0 @@ -// 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.tenant; - -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.yahoo.config.provision.ApplicationId; -import com.yahoo.config.provision.Rotation; -import com.yahoo.path.Path; - -import com.yahoo.vespa.curator.Curator; -import com.yahoo.vespa.curator.transaction.CuratorOperations; -import com.yahoo.vespa.curator.transaction.CuratorTransaction; - -import java.util.Collections; -import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; - -/** - * Rotations for an application. Persisted in ZooKeeper. - * - * @author hmusum - * @author bratseth - */ -// TODO: This should be owned by the correct Tenant object and the rotations set should be contained in this -public class Rotations { - - private final Path path; - private final Curator curator; - - public Rotations(Curator curator, Path tenantPath) { - this.curator = curator; - this.path = tenantPath.append("rotationsCache/"); - } - - public Set readRotationsFromZooKeeper(ApplicationId application) { - try { - Optional data = curator.getData(rotationsOf(application)); - if ( ! data.isPresent() || data.get().length == 0) return Collections.emptySet(); - Set rotationIds = new ObjectMapper().readValue(data.get(), new TypeReference>() {}); - return rotationIds.stream().map(Rotation::new).collect(Collectors.toSet()); - } catch (Exception e) { - throw new RuntimeException("Error reading rotations of " + application, e); - } - } - - public void writeRotationsToZooKeeper(ApplicationId application, Set rotations) { - if (rotations.isEmpty()) return; - try { - Set rotationIds = rotations.stream().map(Rotation::getId).collect(Collectors.toSet()); - byte[] data = new ObjectMapper().writeValueAsBytes(rotationIds); - curator.set(rotationsOf(application), data); - } catch (Exception e) { - throw new RuntimeException("Could not write rotations of " + application, e); - } - } - - /** Returns a transaction which deletes these rotations if they exist */ - public CuratorTransaction delete(ApplicationId application) { - if ( ! curator.exists(rotationsOf(application))) return CuratorTransaction.empty(curator); - return CuratorTransaction.from(CuratorOperations.delete(rotationsOf(application).getAbsolute()), curator); - } - - /** Returns the path storing the rotations data for an application */ - private Path rotationsOf(ApplicationId application) { - return path.append(application.serializedForm()); - } - -} -- cgit v1.2.3