From eb4f0ab84883e89f6cf397a37b3840719e0843e6 Mon Sep 17 00:00:00 2001 From: Jon Bratseth Date: Wed, 4 May 2022 15:41:57 +0200 Subject: Consolidate allocated hosts from all model versions - Aactivate the superset of hosts allocated from all model versions - Use the version of each host allocated by the newest model version --- .../modelfactory/AllocatedHostsFromAllModels.java | 47 ++++++++ .../config/server/modelfactory/ModelsBuilder.java | 23 ++-- .../config/server/session/SessionPreparer.java | 5 +- .../config/server/session/SessionRepository.java | 6 +- configserver/src/test/apps/hosted/schemas/music.sd | 3 +- .../config/server/ApplicationRepositoryTest.java | 2 +- .../config/server/ConfigServerBootstrapTest.java | 11 +- .../vespa/config/server/deploy/DeployTester.java | 26 +++++ .../deploy/HostedDeployNodeAllocationTest.java | 119 +++++++++++++++++++++ .../config/server/deploy/HostedDeployTest.java | 97 ++++++++--------- .../vespa/config/server/deploy/RedeployTest.java | 9 +- 11 files changed, 264 insertions(+), 84 deletions(-) create mode 100644 configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/AllocatedHostsFromAllModels.java create mode 100644 configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployNodeAllocationTest.java (limited to 'configserver') diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/AllocatedHostsFromAllModels.java b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/AllocatedHostsFromAllModels.java new file mode 100644 index 00000000000..d4a0fcb0644 --- /dev/null +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/AllocatedHostsFromAllModels.java @@ -0,0 +1,47 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.config.server.modelfactory; + +import com.yahoo.collections.Pair; +import com.yahoo.component.Version; +import com.yahoo.config.provision.AllocatedHosts; +import com.yahoo.config.provision.ClusterSpec; +import com.yahoo.config.provision.HostSpec; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * Different model versions being built may disagree on the set of hosts that should be allocated. + * This keeps track of the right set of hosts to finally allocate given such disagreement: + * The superset of hosts allocated on all model versions, with the spec of the newest version allocating it. + * + * @author bratseth + */ +public class AllocatedHostsFromAllModels { + + /** All hosts with the newest model version that allocated it, indexed on hostname */ + private final Map> hosts = new LinkedHashMap<>(); + + /** Adds the nodes allocated for a particular model version. */ + public void add(AllocatedHosts allocatedHosts, Version version) { + for (var newHost : allocatedHosts.getHosts()) { + var presentHost = hosts.get(newHost.hostname()); + if (presentHost == null || version.isAfter(presentHost.getSecond())) + hosts.put(newHost.hostname(), new Pair<>(newHost, version)); + } + } + + public AllocatedHosts toAllocatedHosts() { + // Preserve add order for tests + Set hostSet = new LinkedHashSet<>(); + for (var host : hosts.values()) + hostSet.add(host.getFirst()); + return AllocatedHosts.withHosts(hostSet); + } + +} diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelsBuilder.java b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelsBuilder.java index b270da89e28..f6f6a9ea24c 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelsBuilder.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/ModelsBuilder.java @@ -87,7 +87,7 @@ public abstract class ModelsBuilder { Optional dockerImageRepository, Version wantedNodeVespaVersion, ApplicationPackage applicationPackage, - SettableOptional allocatedHosts, + AllocatedHostsFromAllModels allocatedHosts, Instant now) { Instant start = Instant.now(); log.log(Level.FINE, () -> "Will build models for " + applicationId); @@ -168,7 +168,7 @@ public abstract class ModelsBuilder { Optional wantedDockerImageRepository, Version wantedNodeVespaVersion, ApplicationPackage applicationPackage, - SettableOptional allocatedHosts, + AllocatedHostsFromAllModels allocatedHosts, Instant now, boolean buildLatestModelForThisMajor, int majorVersion) { @@ -182,17 +182,12 @@ public abstract class ModelsBuilder { applicationId, wantedDockerImageRepository, wantedNodeVespaVersion); - allocatedHosts.set(latestModelVersion.getModel().allocatedHosts()); // Update with additional clusters allocated + allocatedHosts.add(latestModelVersion.getModel().allocatedHosts(), latest.get()); builtModelVersions.add(latestModelVersion); } // load old model versions - versions = versionsToBuild(versions, wantedNodeVespaVersion, majorVersion, allocatedHosts.get()); - // TODO: We use the allocated hosts from the newest version when building older model versions. - // This is correct except for the case where an old model specifies a cluster which the new version - // does not. In that case we really want to extend the set of allocated hosts to include those of that - // cluster as well. To do that, create a new provisioner which uses static provisioning for known - // clusters and the node repository provisioner as fallback. + versions = versionsToBuild(versions, wantedNodeVespaVersion, majorVersion, allocatedHosts); for (Version version : versions) { if (latest.isPresent() && version.equals(latest.get())) continue; // already loaded @@ -202,7 +197,7 @@ public abstract class ModelsBuilder { applicationId, wantedDockerImageRepository, wantedNodeVespaVersion); - allocatedHosts.set(modelVersion.getModel().allocatedHosts()); // Update with additional clusters allocated + allocatedHosts.add(modelVersion.getModel().allocatedHosts(), version); builtModelVersions.add(modelVersion); } catch (RuntimeException e) { // allow failure to create old config models if there is a validation override that allow skipping old @@ -220,14 +215,16 @@ public abstract class ModelsBuilder { return builtModelVersions; } - private Set versionsToBuild(Set versions, Version wantedVersion, int majorVersion, AllocatedHosts allocatedHosts) { - versions = keepThoseUsedOn(allocatedHosts, versions); + private Set versionsToBuild(Set versions, Version wantedVersion, int majorVersion, + AllocatedHostsFromAllModels allocatedHosts) { + // TODO: This won't find nodes allocated to the application only on older model versions. + // Correct would be to determine this from all active nodes. + versions = keepThoseUsedOn(allocatedHosts.toAllocatedHosts(), versions); // Make sure we build wanted version if we are building models for this major version and we are on hosted vespa // If not on hosted vespa, we do not want to try to build this version, since we have only one version (the latest) if (hosted && wantedVersion.getMajor() == majorVersion) versions.add(wantedVersion); - return versions; } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionPreparer.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionPreparer.java index 8293871335d..6019f3ff438 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionPreparer.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionPreparer.java @@ -35,6 +35,7 @@ import com.yahoo.vespa.config.server.deploy.ZooKeeperDeployer; import com.yahoo.vespa.config.server.filedistribution.FileDistributionFactory; import com.yahoo.vespa.config.server.host.HostValidator; import com.yahoo.vespa.config.server.http.InvalidApplicationException; +import com.yahoo.vespa.config.server.modelfactory.AllocatedHostsFromAllModels; import com.yahoo.vespa.config.server.modelfactory.LegacyFlags; import com.yahoo.vespa.config.server.modelfactory.ModelFactoryRegistry; import com.yahoo.vespa.config.server.modelfactory.PreparedModelsBuilder; @@ -254,11 +255,11 @@ public class SessionPreparer { } AllocatedHosts buildModels(Instant now) { - SettableOptional allocatedHosts = new SettableOptional<>(); + var allocatedHosts = new AllocatedHostsFromAllModels(); this.modelResultList = preparedModelsBuilder.buildModels(applicationId, dockerImageRepository, vespaVersion, preprocessedApplicationPackage, allocatedHosts, now); checkTimeout("build models"); - return allocatedHosts.get(); + return allocatedHosts.toAllocatedHosts(); } void makeResult(AllocatedHosts allocatedHosts) { diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionRepository.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionRepository.java index ccfe8e31b69..a5305f8f886 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionRepository.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionRepository.java @@ -34,6 +34,7 @@ import com.yahoo.vespa.config.server.filedistribution.FileDirectory; import com.yahoo.vespa.config.server.filedistribution.FileDistributionFactory; import com.yahoo.vespa.config.server.http.UnknownVespaVersionException; import com.yahoo.vespa.config.server.modelfactory.ActivatedModelsBuilder; +import com.yahoo.vespa.config.server.modelfactory.AllocatedHostsFromAllModels; import com.yahoo.vespa.config.server.modelfactory.ModelFactoryRegistry; import com.yahoo.vespa.config.server.monitoring.MetricUpdater; import com.yahoo.vespa.config.server.monitoring.Metrics; @@ -536,14 +537,11 @@ public class SessionRepository { zone, modelFactoryRegistry, configDefinitionRepo); - // Read hosts allocated on the config server instance which created this - SettableOptional allocatedHosts = new SettableOptional<>(applicationPackage.getAllocatedHosts()); - return ApplicationSet.fromList(builder.buildModels(session.getApplicationId(), sessionZooKeeperClient.readDockerImageRepository(), sessionZooKeeperClient.readVespaVersion(), applicationPackage, - allocatedHosts, + new AllocatedHostsFromAllModels(), clock.instant())); } diff --git a/configserver/src/test/apps/hosted/schemas/music.sd b/configserver/src/test/apps/hosted/schemas/music.sd index cb4b860e019..380f6f6b80b 100644 --- a/configserver/src/test/apps/hosted/schemas/music.sd +++ b/configserver/src/test/apps/hosted/schemas/music.sd @@ -1,9 +1,8 @@ # Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -search music { +schema music { document music { field title type string { indexing: index | summary - # index-to: default } } } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/ApplicationRepositoryTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/ApplicationRepositoryTest.java index 26e993c3028..1ad0765a25f 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/ApplicationRepositoryTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/ApplicationRepositoryTest.java @@ -408,7 +408,7 @@ public class ApplicationRepositoryTest { .configDefinitionsDir(temporaryFolder.newFolder("configdefinitions").getAbsolutePath()) .fileReferencesDir(temporaryFolder.newFolder("filedistribution").getAbsolutePath()) .sessionLifetime(60)); - DeployTester tester = new DeployTester.Builder().configserverConfig(configserverConfig).clock(clock).build(); + DeployTester tester = new DeployTester.Builder(temporaryFolder).configserverConfig(configserverConfig).clock(clock).build(); tester.deployApp("src/test/apps/app"); // session 2 (numbering starts at 2) clock.advance(Duration.ofSeconds(10)); diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/ConfigServerBootstrapTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/ConfigServerBootstrapTest.java index 67613d5a806..c3baaf8b118 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/ConfigServerBootstrapTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/ConfigServerBootstrapTest.java @@ -67,8 +67,9 @@ public class ConfigServerBootstrapTest { public void testBootstrap() throws Exception { ConfigserverConfig configserverConfig = createConfigserverConfig(temporaryFolder); InMemoryProvisioner provisioner = new InMemoryProvisioner(7, false); - DeployTester tester = new DeployTester.Builder().modelFactory(createHostedModelFactory()) - .configserverConfig(configserverConfig).hostProvisioner(provisioner).build(); + DeployTester tester = new DeployTester.Builder(temporaryFolder).modelFactory(createHostedModelFactory()) + .configserverConfig(configserverConfig) + .hostProvisioner(provisioner).build(); tester.deployApp("src/test/apps/hosted/"); RpcServer rpcServer = createRpcServer(configserverConfig); @@ -104,7 +105,7 @@ public class ConfigServerBootstrapTest { public void testBootstrapWithVipStatusFile() throws Exception { ConfigserverConfig configserverConfig = createConfigserverConfig(temporaryFolder); InMemoryProvisioner provisioner = new InMemoryProvisioner(7, false); - DeployTester tester = new DeployTester.Builder().modelFactory(createHostedModelFactory()) + DeployTester tester = new DeployTester.Builder(temporaryFolder).modelFactory(createHostedModelFactory()) .configserverConfig(configserverConfig).hostProvisioner(provisioner).build(); tester.deployApp("src/test/apps/hosted/"); @@ -123,7 +124,7 @@ public class ConfigServerBootstrapTest { @Test public void testBootstrapWhenRedeploymentFails() throws Exception { ConfigserverConfig configserverConfig = createConfigserverConfig(temporaryFolder); - DeployTester tester = new DeployTester.Builder().modelFactory(createHostedModelFactory()) + DeployTester tester = new DeployTester.Builder(temporaryFolder).modelFactory(createHostedModelFactory()) .configserverConfig(configserverConfig).build(); tester.deployApp("src/test/apps/hosted/"); @@ -156,7 +157,7 @@ public class ConfigServerBootstrapTest { String vespaVersion = "1.2.3"; List hosts = createHosts(vespaVersion); Curator curator = new MockCurator(); - DeployTester tester = new DeployTester.Builder() + DeployTester tester = new DeployTester.Builder(temporaryFolder) .modelFactory(DeployTester.createModelFactory(Version.fromString(vespaVersion))) .hostProvisioner(new InMemoryProvisioner(new Hosts(hosts), true, false)) .configserverConfig(configserverConfig) diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployTester.java b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployTester.java index 2094c180338..9d01d56d72f 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployTester.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/DeployTester.java @@ -42,8 +42,10 @@ import com.yahoo.vespa.flags.FlagSource; import com.yahoo.vespa.flags.InMemoryFlagSource; import com.yahoo.vespa.model.VespaModel; import com.yahoo.vespa.model.VespaModelFactory; +import org.junit.rules.TemporaryFolder; import java.io.File; +import java.io.IOException; import java.nio.file.Files; import java.time.Clock; import java.time.Duration; @@ -251,6 +253,8 @@ public class DeployTester { } public static class Builder { + + private final TemporaryFolder temporaryFolder; private Clock clock; private Provisioner provisioner; private ConfigserverConfig configserverConfig; @@ -261,6 +265,10 @@ public class DeployTester { private ConfigConvergenceChecker configConvergenceChecker = new ConfigConvergenceChecker(); private FlagSource flagSource = new InMemoryFlagSource(); + public Builder(TemporaryFolder temporaryFolder) { + this.temporaryFolder = temporaryFolder; + } + public DeployTester build() { Clock clock = Optional.ofNullable(this.clock).orElseGet(Clock::systemUTC); Zone zone = Optional.ofNullable(this.zone).orElseGet(Zone::defaultZone); @@ -354,6 +362,24 @@ public class DeployTester { return this; } + public Builder hostedConfigserverConfig(Zone zone) { + try { + this.configserverConfig = new ConfigserverConfig(new ConfigserverConfig.Builder() + .configServerDBDir(temporaryFolder.newFolder().getAbsolutePath()) + .configDefinitionsDir(temporaryFolder.newFolder().getAbsolutePath()) + .fileReferencesDir(temporaryFolder.newFolder().getAbsolutePath()) + .hostedVespa(true) + .multitenant(true) + .region(zone.region().value()) + .environment(zone.environment().value()) + .system(zone.system().value())); + return this; + } + catch (IOException e) { + throw new RuntimeException(e); + } + } + } } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployNodeAllocationTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployNodeAllocationTest.java new file mode 100644 index 00000000000..c8b03a68bf5 --- /dev/null +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployNodeAllocationTest.java @@ -0,0 +1,119 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.config.server.deploy; + +import com.yahoo.component.Version; +import com.yahoo.config.model.api.HostProvisioner; +import com.yahoo.config.model.api.ModelFactory; +import com.yahoo.config.provision.Capacity; +import com.yahoo.config.provision.ClusterMembership; +import com.yahoo.config.provision.ClusterSpec; +import com.yahoo.config.provision.HostSpec; +import com.yahoo.config.provision.NodeResources; +import com.yahoo.config.provision.ProvisionLogger; +import com.yahoo.config.provision.Zone; +import com.yahoo.vespa.config.server.MockProvisioner; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import static com.yahoo.vespa.config.server.deploy.DeployTester.createHostedModelFactory; +import static org.junit.Assert.assertEquals; + +public class HostedDeployNodeAllocationTest { + + @Rule + public TemporaryFolder temporaryFolder = new TemporaryFolder(); + + @Test + public void testDeployMultipleVersionsCreatingDifferentHosts() { + List modelFactories = List.of(createHostedModelFactory(Version.fromString("7.2")), + createHostedModelFactory(Version.fromString("7.3"))); + var provisioner = new VersionProvisioner(); + DeployTester tester = new DeployTester.Builder(temporaryFolder).modelFactories(modelFactories) + .provisioner(new MockProvisioner().hostProvisioner(provisioner)) + .hostedConfigserverConfig(Zone.defaultZone()) + .build(); + tester.deployApp("src/test/apps/hosted/", "7.3"); + + var hosts = containers(tester.getAllocatedHostsOf(tester.applicationId()).getHosts()); + assertEquals("Allocating the superset of hosts of each version", 5, hosts.size()); + assertEquals(resources(3), get("host0", hosts).advertisedResources()); + assertEquals(resources(3), get("host1", hosts).advertisedResources()); + assertEquals(resources(3), get("host2", hosts).advertisedResources()); + assertEquals(resources(2), get("host3", hosts).advertisedResources()); + assertEquals(resources(2), get("host4", hosts).advertisedResources()); + } + + private HostSpec get(String hostname, Set hosts) { + return hosts.stream().filter(host -> host.hostname().equals(hostname)).findAny().orElseThrow(); + } + + private Set containers(Set hosts) { + return hosts.stream().filter(host -> host.membership().get().cluster().type() == ClusterSpec.Type.container).collect(Collectors.toSet()); + } + + private static NodeResources resources(double vcpu) { + return new NodeResources(vcpu, 1, 1, 1); + } + + private static class VersionProvisioner implements HostProvisioner { + + int invocation = 0; + + @Override + public HostSpec allocateHost(String alias) { + throw new RuntimeException(); + } + + @Override + public List prepare(ClusterSpec cluster, Capacity capacity, ProvisionLogger logger) { + if (cluster.id().value().equals("container")) { // the container cluster from the app package: Use this to test + if (invocation == 0) { // Building the latest model version, 7.3: Always first + invocation++; + // Returns nodes which are on both versions to trigger building old versions + return List.of(host("host0", resources(3), 0, "7.3", cluster), + host("host1", resources(3), 1, "7.3", cluster), + host("host2", resources(3), 2, "7.2", cluster)); + } else if (invocation == 1) { // Building 7.2 + invocation++; + return List.of(host("host3", resources(2), 2, "7.2", cluster), + host("host4", resources(2), 3, "7.2", cluster), + host("host4", resources(2), 4, "7.2", cluster)); + } else { + throw new RuntimeException("Unexpected third invocation"); + } + } + else { // for other clusters just return the requested hosts + List hosts = new ArrayList<>(); + for (int i = 0; i < capacity.maxResources().nodes(); i++) { + hosts.add(host(cluster.id().value() + i, + capacity.maxResources().nodeResources(), + i, + cluster.vespaVersion().toString(), + cluster)); + } + return hosts; + } + } + + private HostSpec host(String hostname, NodeResources resources, int index, String version, ClusterSpec cluster) { + var membership = ClusterMembership.from(cluster.with(Optional.of(ClusterSpec.Group.from(index))), index); + return new HostSpec(hostname, + resources, + resources, + resources, + membership, + Optional.of(Version.fromString(version)), + Optional.empty(), + Optional.empty()); + } + + } + +} diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployTest.java index 5df46b94b75..800cf7bad60 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/HostedDeployTest.java @@ -1,7 +1,6 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.config.server.deploy; -import com.yahoo.cloud.config.ConfigserverConfig; import com.yahoo.component.Version; import com.yahoo.config.application.api.ValidationId; import com.yahoo.config.model.api.ConfigChangeAction; @@ -36,7 +35,6 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; -import java.io.IOException; import java.time.Clock; import java.time.Duration; import java.time.Instant; @@ -68,10 +66,10 @@ public class HostedDeployTest { public TemporaryFolder temporaryFolder = new TemporaryFolder(); @Test - public void testRedeployWithVersion() throws IOException { - DeployTester tester = new DeployTester.Builder() + public void testRedeployWithVersion() { + DeployTester tester = new DeployTester.Builder(temporaryFolder) .modelFactory(createHostedModelFactory(Version.fromString("4.5.6"), Clock.systemUTC())) - .configserverConfig(createConfigserverConfig()).build(); + .build(); tester.deployApp("src/test/apps/hosted/", "4.5.6"); Optional deployment = tester.redeployFromLocalActive(tester.applicationId()); @@ -81,10 +79,10 @@ public class HostedDeployTest { } @Test - public void testRedeploy() throws IOException { - DeployTester tester = new DeployTester.Builder() + public void testRedeploy() { + DeployTester tester = new DeployTester.Builder(temporaryFolder) .modelFactory(createHostedModelFactory()) - .configserverConfig(createConfigserverConfig()).build(); + .build(); ApplicationId appId = tester.applicationId(); tester.deployApp("src/test/apps/hosted/"); assertFalse(tester.applicationRepository().getActiveSession(appId).get().getMetaData().isInternalRedeploy()); @@ -96,10 +94,10 @@ public class HostedDeployTest { } @Test - public void testReDeployWithWantedDockerImageRepositoryAndAthenzDomain() throws IOException { - DeployTester tester = new DeployTester.Builder() + public void testReDeployWithWantedDockerImageRepositoryAndAthenzDomain() { + DeployTester tester = new DeployTester.Builder(temporaryFolder) .modelFactory(createHostedModelFactory(Version.fromString("4.5.6"), Clock.systemUTC())) - .configserverConfig(createConfigserverConfig()).build(); + .build(); String dockerImageRepository = "docker.foo.com:4443/bar/baz"; tester.deployApp("src/test/apps/hosted/", new PrepareParams.Builder() .vespaVersion("4.5.6") @@ -115,11 +113,11 @@ public class HostedDeployTest { } @Test - public void testRedeployWithTenantSecretStores() throws IOException { + public void testRedeployWithTenantSecretStores() { List tenantSecretStores = List.of(new TenantSecretStore("foo", "123", "role")); - DeployTester tester = new DeployTester.Builder() + DeployTester tester = new DeployTester.Builder(temporaryFolder) .modelFactory(createHostedModelFactory(Version.fromString("4.5.6"), Clock.systemUTC())) - .configserverConfig(createConfigserverConfig()).build(); + .build(); tester.deployApp("src/test/apps/hosted/", new PrepareParams.Builder() .vespaVersion("4.5.6") .tenantSecretStores(tenantSecretStores)); @@ -131,9 +129,11 @@ public class HostedDeployTest { } @Test - public void testDeployOnUnknownVersion() throws IOException { + public void testDeployOnUnknownVersion() { List modelFactories = List.of(createHostedModelFactory(Version.fromString("1.0.0"))); - DeployTester tester = new DeployTester.Builder().modelFactories(modelFactories).configserverConfig(createConfigserverConfig()).build(); + DeployTester tester = new DeployTester.Builder(temporaryFolder) + .modelFactories(modelFactories) + .build(); // No version requested: OK tester.deployApp("src/test/apps/hosted/", new PrepareParams.Builder()); @@ -156,11 +156,13 @@ public class HostedDeployTest { } @Test - public void testDeployMultipleVersions() throws IOException { + public void testDeployMultipleVersions() { List modelFactories = List.of(createHostedModelFactory(Version.fromString("6.1.0")), createHostedModelFactory(Version.fromString("6.2.0")), createHostedModelFactory(Version.fromString("7.0.0"))); - DeployTester tester = new DeployTester.Builder().modelFactories(modelFactories).configserverConfig(createConfigserverConfig()).build(); + DeployTester tester = new DeployTester.Builder(temporaryFolder).modelFactories(modelFactories) + .hostedConfigserverConfig(Zone.defaultZone()) + .build(); tester.deployApp("src/test/apps/hosted/", "6.2.0"); assertEquals(7, tester.getAllocatedHostsOf(tester.applicationId()).getHosts().size()); } @@ -170,7 +172,7 @@ public class HostedDeployTest { * and the latest version for the latest major) */ @Test - public void testCreateOnlyNeededModelVersions() throws IOException { + public void testCreateOnlyNeededModelVersions() { List hosts = createHosts(7, "6.0.0", "6.1.0", null, "6.1.0"); // Use a host without a version as well. CountingModelFactory factory600 = createHostedModelFactory(Version.fromString("6.0.0")); @@ -201,7 +203,7 @@ public class HostedDeployTest { * the latest major, since nodes are without version) */ @Test - public void testCreateOnlyNeededModelVersionsNewNodes() throws IOException { + public void testCreateOnlyNeededModelVersionsNewNodes() { List hosts = createHosts(7, (String) null); CountingModelFactory factory600 = createHostedModelFactory(Version.fromString("6.0.0")); @@ -225,7 +227,7 @@ public class HostedDeployTest { * (not just the latest one, manually deployed apps always have skipOldConfigModels set to true) */ @Test - public void testCreateNeededModelVersionsForManuallyDeployedApps() throws IOException { + public void testCreateNeededModelVersionsForManuallyDeployedApps() { List hosts = createHosts(5, "7.0.0"); CountingModelFactory factory700 = createHostedModelFactory(Version.fromString("7.0.0"), devZone); @@ -250,7 +252,7 @@ public class HostedDeployTest { * even if creating one of the older model fails */ @Test - public void testCreateModelVersionsForManuallyDeployedAppsWhenCreatingFailsForOneVersion() throws IOException { + public void testCreateModelVersionsForManuallyDeployedAppsWhenCreatingFailsForOneVersion() { List hosts = createHosts(5, "7.0.0"); ModelFactory factory700 = createFailingModelFactory(Version.fromString("7.0.0")); @@ -273,7 +275,7 @@ public class HostedDeployTest { * that are still using features that do not work on version 8.x) */ @Test - public void testCreateLatestMajorOnPreviousMajorIfItFailsOnMajorVersion8() throws IOException { + public void testCreateLatestMajorOnPreviousMajorIfItFailsOnMajorVersion8() { deployWithModelForLatestMajorVersionFailing(8); } @@ -283,7 +285,7 @@ public class HostedDeployTest { * for major version >= 8 (see test above) or when major-version=6 is set in application package. */ @Test(expected = InvalidApplicationException.class) - public void testFailingToCreateModelVersion7FailsDeployment() throws IOException { + public void testFailingToCreateModelVersion7FailsDeployment() { deployWithModelForLatestMajorVersionFailing(7); } @@ -291,7 +293,7 @@ public class HostedDeployTest { * Tests that we create the minimal set of models, but latest model version is created for * previous major if creating latest model version on latest major version fails **/ - private void deployWithModelForLatestMajorVersionFailing(int newestMajorVersion) throws IOException { + private void deployWithModelForLatestMajorVersionFailing(int newestMajorVersion) { int oldestMajorVersion = newestMajorVersion - 1; String oldestVersion = oldestMajorVersion + ".0.0"; String newestOnOldMajorVersion = oldestMajorVersion + ".1.0"; @@ -317,7 +319,7 @@ public class HostedDeployTest { * Tests that we fail deployment if a needed model version fails to be created */ @Test(expected = InvalidApplicationException.class) - public void testDeploymentFailsIfNeededModelVersionFails() throws IOException { + public void testDeploymentFailsIfNeededModelVersionFails() { List hosts = createHosts(7, "7.0.0"); List modelFactories = List.of(createFailingModelFactory(Version.fromString("7.0.0")), @@ -333,7 +335,7 @@ public class HostedDeployTest { * that will be done) */ @Test - public void testCreateOnlyNeededModelVersionsWhenNoHostsAllocated() throws IOException { + public void testCreateOnlyNeededModelVersionsWhenNoHostsAllocated() { CountingModelFactory factory700 = createHostedModelFactory(Version.fromString("7.0.0")); CountingModelFactory factory720 = createHostedModelFactory(Version.fromString("7.2.0")); List modelFactories = List.of(factory700, factory720); @@ -345,7 +347,7 @@ public class HostedDeployTest { } @Test - public void testAccessControlIsOnlyCheckedWhenNoProdDeploymentExists() throws IOException { + public void testAccessControlIsOnlyCheckedWhenNoProdDeploymentExists() { // Provisioner does not reuse hosts, so need twice as many hosts as app requires List hosts = createHosts(14, "6.0.0"); @@ -366,12 +368,13 @@ public class HostedDeployTest { } @Test - public void testRedeployAfterExpiredValidationOverride() throws IOException { + public void testRedeployAfterExpiredValidationOverride() { // Old version of model fails, but application disables loading old models until 2016-10-10, so deployment works ManualClock clock = new ManualClock("2016-10-09T00:00:00"); List modelFactories = List.of(createHostedModelFactory(clock), createFailingModelFactory(Version.fromString("1.0.0"))); // older than default - DeployTester tester = new DeployTester.Builder().modelFactories(modelFactories).configserverConfig(createConfigserverConfig()).build(); + DeployTester tester = new DeployTester.Builder(temporaryFolder).modelFactories(modelFactories) + .build(); tester.deployApp("src/test/apps/validationOverride/"); // Redeployment from local active works @@ -403,7 +406,7 @@ public class HostedDeployTest { } @Test - public void testThatConfigChangeActionsAreCollectedFromAllModels() throws IOException { + public void testThatConfigChangeActionsAreCollectedFromAllModels() { List hosts = createHosts(7, "6.1.0", "6.2.0"); List services = List.of( new ServiceInfo("serviceName", "serviceType", null, new HashMap<>(), "configId", "hostName")); @@ -421,7 +424,7 @@ public class HostedDeployTest { } @Test - public void testThatAllowedConfigChangeActionsAreActedUpon() throws IOException { + public void testThatAllowedConfigChangeActionsAreActedUpon() { List hosts = createHosts(7, "6.1.0"); List services = List.of( new ServiceInfo("serviceName", "serviceType", null, Map.of("clustername", "cluster"), "configId", "hostName")); @@ -433,13 +436,13 @@ public class HostedDeployTest { "reindex please", services, "music"), new VespaRestartAction(ClusterSpec.Id.from("test"), "change", services))); - DeployTester tester = new DeployTester.Builder() + DeployTester tester = new DeployTester.Builder(temporaryFolder) .modelFactories(modelFactories) - .configserverConfig(createConfigserverConfig(prodZone)) .clock(clock) .zone(prodZone) .hostProvisioner(new InMemoryProvisioner(new Hosts(hosts), true, false)) .configConvergenceChecker(new MockConfigConvergenceChecker(2)) + .hostedConfigserverConfig(prodZone) .build(); PrepareResult prepareResult = tester.deployApp("src/test/apps/hosted/", "6.1.0"); @@ -450,24 +453,8 @@ public class HostedDeployTest { tester.tenant().getApplicationRepo().database().readReindexingStatus(tester.applicationId())); } - private ConfigserverConfig createConfigserverConfig() throws IOException { - return createConfigserverConfig(Zone.defaultZone()); - } - - private ConfigserverConfig createConfigserverConfig(Zone zone) throws IOException { - return new ConfigserverConfig(new ConfigserverConfig.Builder() - .configServerDBDir(temporaryFolder.newFolder().getAbsolutePath()) - .configDefinitionsDir(temporaryFolder.newFolder().getAbsolutePath()) - .fileReferencesDir(temporaryFolder.newFolder().getAbsolutePath()) - .hostedVespa(true) - .multitenant(true) - .region(zone.region().value()) - .environment(zone.environment().value()) - .system(zone.system().value())); - } - /** Create the given number of hosts using the supplied versions--the last version is repeated as needed. */ - private List createHosts(int count, String... versions) { + private List createHosts(int count, String ... versions) { return IntStream.rangeClosed(1, count) .mapToObj(i -> createHost("host" + i, versions[Math.min(i, versions.length) - 1])) .collect(toList()); @@ -477,19 +464,19 @@ public class HostedDeployTest { return new Host(hostname, Collections.emptyList(), Optional.empty(), Optional.ofNullable(version).map(Version::fromString)); } - private DeployTester createTester(List hosts, List modelFactories, Zone zone) throws IOException { + private DeployTester createTester(List hosts, List modelFactories, Zone zone) { return createTester(hosts, modelFactories, zone, Clock.systemUTC()); } private DeployTester createTester(List hosts, List modelFactories, - Zone prodZone, Clock clock) throws IOException { - return new DeployTester.Builder() + Zone prodZone, Clock clock) { + return new DeployTester.Builder(temporaryFolder) .modelFactories(modelFactories) - .configserverConfig(createConfigserverConfig(prodZone)) .clock(clock) .zone(prodZone) .hostProvisioner(new InMemoryProvisioner(new Hosts(hosts), true, false)) .configConvergenceChecker(new MockConfigConvergenceChecker(2)) + .hostedConfigserverConfig(prodZone) .build(); } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/RedeployTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/RedeployTest.java index 10e21f1d484..16539a2b63c 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/RedeployTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/RedeployTest.java @@ -6,7 +6,9 @@ import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.ApplicationName; import com.yahoo.config.provision.InstanceName; import com.yahoo.component.Version; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import java.time.Clock; import java.util.List; @@ -25,9 +27,12 @@ import static org.junit.Assert.assertTrue; */ public class RedeployTest { + @Rule + public TemporaryFolder temporaryFolder = new TemporaryFolder(); + @Test public void testRedeploy() { - DeployTester tester = new DeployTester.Builder().build(); + DeployTester tester = new DeployTester.Builder(temporaryFolder).build(); tester.deployApp("src/test/apps/app"); Optional deployment = tester.redeployFromLocalActive(); @@ -45,7 +50,7 @@ public class RedeployTest { public void testNoRedeploy() { List modelFactories = List.of(createModelFactory(Clock.systemUTC()), createFailingModelFactory(Version.fromString("1.0.0"))); - DeployTester tester = new DeployTester.Builder().modelFactories(modelFactories).build(); + DeployTester tester = new DeployTester.Builder(temporaryFolder).modelFactories(modelFactories).build(); ApplicationId id = ApplicationId.from(tester.tenant().getName(), ApplicationName.from("default"), InstanceName.from("default")); -- cgit v1.2.3