diff options
29 files changed, 211 insertions, 172 deletions
diff --git a/config-application-package/src/test/java/com/yahoo/config/application/OverrideProcessorTest.java b/config-application-package/src/test/java/com/yahoo/config/application/OverrideProcessorTest.java index b80372ec9ff..32a1c4f847f 100644 --- a/config-application-package/src/test/java/com/yahoo/config/application/OverrideProcessorTest.java +++ b/config-application-package/src/test/java/com/yahoo/config/application/OverrideProcessorTest.java @@ -15,8 +15,7 @@ import java.io.IOException; import java.io.StringReader; /** - * @author lulf - * @since 5.22 + * @author Ulf Lilleengen */ public class OverrideProcessorTest { diff --git a/config-model-api/src/main/java/com/yahoo/config/application/api/ApplicationFile.java b/config-model-api/src/main/java/com/yahoo/config/application/api/ApplicationFile.java index bcc8d222ca5..0384a5c7a1c 100644 --- a/config-model-api/src/main/java/com/yahoo/config/application/api/ApplicationFile.java +++ b/config-model-api/src/main/java/com/yahoo/config/application/api/ApplicationFile.java @@ -11,7 +11,7 @@ import java.util.List; * An application file represents a file within an application package. This class can be used to traverse the entire * application package file structure, as well as read and write files to it, and create directories. * - * @author Ulf Lillengen + * @author Ulf Lilleengen */ public abstract class ApplicationFile implements Comparable<ApplicationFile> { diff --git a/config-model-api/src/main/java/com/yahoo/config/application/api/ApplicationPackage.java b/config-model-api/src/main/java/com/yahoo/config/application/api/ApplicationPackage.java index 795e87b7690..23bbdd511b7 100644 --- a/config-model-api/src/main/java/com/yahoo/config/application/api/ApplicationPackage.java +++ b/config-model-api/src/main/java/com/yahoo/config/application/api/ApplicationPackage.java @@ -228,10 +228,22 @@ public interface ApplicationPackage { throw new UnsupportedOperationException("This application package cannot write its metadata"); } + /** + * Returns the single host allocation info of this, or an empty map if no allocation is available + * + * @deprecated please use #getProvisionInfo + */ + // TODO: Remove on Vespa 7 + @Deprecated default Map<Version, ProvisionInfo> getProvisionInfoMap() { return Collections.emptyMap(); } + /** Returns the host allocation info of this, or empty if no allocation is available */ + default Optional<ProvisionInfo> getProvisionInfo() { + return Optional.empty(); + } + default Map<Version, FileRegistry> getFileRegistryMap() { return Collections.emptyMap(); } diff --git a/config-model-api/src/main/java/com/yahoo/config/model/api/Model.java b/config-model-api/src/main/java/com/yahoo/config/model/api/Model.java index 0c038077fe4..db589ef5d21 100644 --- a/config-model-api/src/main/java/com/yahoo/config/model/api/Model.java +++ b/config-model-api/src/main/java/com/yahoo/config/model/api/Model.java @@ -16,8 +16,7 @@ import java.util.Collection; * A {@link Model} represents the interface towards the model of an entire tenant, and defines methods * for querying this model. * - * @author lulf - * @since 5.1 + * @author Ulf Lilleengen */ public interface Model { @@ -60,9 +59,20 @@ public interface Model { /** * Get the provisioning info for this model. + * * @return {@link ProvisionInfo} instance, if available. + * @deprecated use provisionInfo */ - Optional<ProvisionInfo> getProvisionInfo(); + @Deprecated + // TODO: Remove this (and the implementation below) when no version older than 6.142 is deployed anywhere + default Optional<ProvisionInfo> getProvisionInfo() { + return Optional.of(provisionInfo()); + } + + @SuppressWarnings("deprecation") + default ProvisionInfo provisionInfo() { + return getProvisionInfo().get(); + } /** * Returns whether this application allows serving config request for a different version. @@ -71,11 +81,6 @@ public interface Model { */ default boolean allowModelVersionMismatch(Instant now) { return false; } - /** @deprecated pass now. */ - // TODO: Remove this when no version older than 6.115 is deployed anywhere - @Deprecated - default boolean allowModelVersionMismatch() { return allowModelVersionMismatch(Clock.systemUTC().instant()); } - /** * Returns whether old config models should be loaded (default) or not. * Skipping old config models is a validation override which is useful when the old model @@ -88,9 +93,4 @@ public interface Model { */ default boolean skipOldConfigModels(Instant now) { return false; } - /** @deprecated pass now. */ - // TODO: Remove this when no version older than 6.115 is deployed anywhere - @Deprecated - default boolean skipOldConfigModels() { return skipOldConfigModels(Clock.systemUTC().instant()); } - } diff --git a/config-model-api/src/main/java/com/yahoo/config/model/api/ModelContext.java b/config-model-api/src/main/java/com/yahoo/config/model/api/ModelContext.java index 5afc570d81b..5b79415c132 100644 --- a/config-model-api/src/main/java/com/yahoo/config/model/api/ModelContext.java +++ b/config-model-api/src/main/java/com/yahoo/config/model/api/ModelContext.java @@ -17,7 +17,7 @@ import java.util.Set; /** * Model context containing state provided to model factories. * - * @author lulf + * @author Ulf Lilleengen */ public interface ModelContext { @@ -31,11 +31,6 @@ public interface ModelContext { Properties properties(); default Optional<File> appDir() { return Optional.empty();} - /** @deprecated TODO: Remove this when no config models older than 6.98 are used */ - @SuppressWarnings("unused") - @Deprecated - default Optional<com.yahoo.config.provision.Version> vespaVersion() { return Optional.empty(); } - /** The Vespa version this model is built for */ Version modelVespaVersion(); @@ -50,4 +45,5 @@ public interface ModelContext { Zone zone(); Set<Rotation> rotations(); } + } diff --git a/config-model/src/main/java/com/yahoo/config/model/test/MockApplicationPackage.java b/config-model/src/main/java/com/yahoo/config/model/test/MockApplicationPackage.java index 133d94c745b..8b97eb2503e 100644 --- a/config-model/src/main/java/com/yahoo/config/model/test/MockApplicationPackage.java +++ b/config-model/src/main/java/com/yahoo/config/model/test/MockApplicationPackage.java @@ -25,6 +25,7 @@ import java.util.*; * @author tonytv */ public class MockApplicationPackage implements ApplicationPackage { + public static final String MUSIC_SEARCHDEFINITION = createSearchDefinition("music", "foo"); public static final String BOOK_SEARCHDEFINITION = createSearchDefinition("book", "bar"); diff --git a/config-model/src/main/java/com/yahoo/vespa/model/HostResource.java b/config-model/src/main/java/com/yahoo/vespa/model/HostResource.java index bc890755ca9..5e74a2ebc8a 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/HostResource.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/HostResource.java @@ -22,7 +22,7 @@ import java.util.stream.Collectors; * TODO: Merge with {@link Host} * Host resources are ordered by their host order. * - * @author Ulf Lillengen + * @author Ulf Lilleengen */ public class HostResource implements Comparable<HostResource> { diff --git a/config-model/src/main/java/com/yahoo/vespa/model/VespaModel.java b/config-model/src/main/java/com/yahoo/vespa/model/VespaModel.java index c61435ca831..d790e5c67b5 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/VespaModel.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/VespaModel.java @@ -83,7 +83,7 @@ public final class VespaModel extends AbstractConfigProducerRoot implements Seri public static final Logger log = Logger.getLogger(VespaModel.class.getPackage().toString()); private ConfigModelRepo configModelRepo = new ConfigModelRepo(); - private final Optional<ProvisionInfo> info; + private final ProvisionInfo provisionInfo; /** * The config id for the root config producer @@ -146,7 +146,7 @@ public final class VespaModel extends AbstractConfigProducerRoot implements Seri if (complete) { // create a a completed, frozen model configModelRepo.readConfigModels(deployState, builder, root, configModelRegistry); addServiceClusters(deployState.getApplicationPackage(), builder); - this.info = Optional.of(createProvisionInfo()); // must happen after the two lines above + this.provisionInfo = ProvisionInfo.withHosts(root.getHostSystem().getHostSpecs()); // must happen after the two lines above setupRouting(); this.fileDistributor = root.getFileDistributionConfigProducer().getFileDistributor(); getAdmin().addPerHostServices(getHostSystem().getHosts(), deployState.getProperties()); @@ -157,7 +157,7 @@ public final class VespaModel extends AbstractConfigProducerRoot implements Seri this.deployState = null; } else { // create a model with no services instantiated and the given file distributor - this.info = Optional.of(createProvisionInfo()); + this.provisionInfo = ProvisionInfo.withHosts(root.getHostSystem().getHostSpecs()); this.fileDistributor = fileDistributor; } } @@ -167,10 +167,6 @@ public final class VespaModel extends AbstractConfigProducerRoot implements Seri return new VespaModel(new NullConfigModelRegistry(), deployState, false, new FileDistributor(deployState.getFileRegistry())); } - private ProvisionInfo createProvisionInfo() { - return ProvisionInfo.withHosts(root.getHostSystem().getHostSpecs()); - } - private void validateWrapExceptions() { try { validate(); @@ -421,8 +417,8 @@ public final class VespaModel extends AbstractConfigProducerRoot implements Seri } @Override - public Optional<ProvisionInfo> getProvisionInfo() { - return info; + public ProvisionInfo provisionInfo() { + return provisionInfo; } private static Set<ConfigKey<?>> configsProduced(ConfigProducer cp) { diff --git a/config-model/src/test/java/com/yahoo/vespa/model/test/VespaModelTestCase.java b/config-model/src/test/java/com/yahoo/vespa/model/test/VespaModelTestCase.java index 8102f358830..b35acffaf06 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/test/VespaModelTestCase.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/test/VespaModelTestCase.java @@ -286,7 +286,7 @@ public class VespaModelTestCase { .build()) .build(); VespaModel model = new VespaModel(new NullConfigModelRegistry(), deployState); - ProvisionInfo info = model.getProvisionInfo().get(); + ProvisionInfo info = model.provisionInfo(); assertEquals("Admin version 3 is ignored, and there are no other hosts to borrow for admin services", 0, info.getHosts().size()); } diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/HostSpec.java b/config-provisioning/src/main/java/com/yahoo/config/provision/HostSpec.java index 5d6b3fcaca4..a94660e142e 100644 --- a/config-provisioning/src/main/java/com/yahoo/config/provision/HostSpec.java +++ b/config-provisioning/src/main/java/com/yahoo/config/provision/HostSpec.java @@ -5,11 +5,13 @@ import com.google.common.collect.ImmutableList; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.Optional; /** * A specification of a host and its role. - * The identity of a host is determined by its name. + * This is a value object: Immutable and the identity is determined by all the content. + * Host specs are ordered by host name. * * @author hmusum */ @@ -19,7 +21,7 @@ public class HostSpec implements Comparable<HostSpec> { private final String hostname; /** Aliases of this host */ - private final List<String> aliases; + private final ImmutableList<String> aliases; /** The current membership role of this host in the cluster it belongs to */ private final Optional<ClusterMembership> membership; @@ -70,14 +72,20 @@ public class HostSpec implements Comparable<HostSpec> { @Override public boolean equals(Object o) { + if (o == this) return true; if ( ! (o instanceof HostSpec)) return false; + HostSpec other = (HostSpec) o; - return this.hostname().equals(other.hostname()); + if ( ! this.hostname.equals(other.hostname)) return false; + if ( ! this.aliases.equals(other.aliases)) return false; + if ( ! this.membership.equals(other.membership)) return false; + if ( ! this.flavor.equals(other.flavor)) return false; + return true; } @Override public int hashCode() { - return hostname.hashCode(); + return Objects.hash(hostname, aliases, membership, flavor); } @Override diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/ProvisionInfo.java b/config-provisioning/src/main/java/com/yahoo/config/provision/ProvisionInfo.java index 8bef1f7c9b7..4506f52e085 100644 --- a/config-provisioning/src/main/java/com/yahoo/config/provision/ProvisionInfo.java +++ b/config-provisioning/src/main/java/com/yahoo/config/provision/ProvisionInfo.java @@ -1,6 +1,7 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.config.provision; +import com.google.common.collect.ImmutableSet; import com.yahoo.slime.ArrayTraverser; import com.yahoo.slime.Cursor; import com.yahoo.slime.Inspector; @@ -14,10 +15,12 @@ import java.util.Optional; import java.util.Set; /** - * Information about hosts provisioned for an application, and (de)serialization of this information to/from JSON. + * The hosts allocated to an application (a better name would be "AllocatedHosts"). + * This can be serialized to/from JSON. + * This is immutable. * - * @author lulf - * @since 5.12 + * @author Ulf Lilleengen + * @author bratseth */ public class ProvisionInfo { @@ -28,10 +31,10 @@ public class ProvisionInfo { private static final String hostSpecFlavor = "flavor"; private static final String hostSpecVespaVersion = "vespaVersion"; - private final Set<HostSpec> hosts = new LinkedHashSet<>(); + private final ImmutableSet<HostSpec> hosts; private ProvisionInfo(Set<HostSpec> hosts) { - this.hosts.addAll(hosts); + this.hosts = ImmutableSet.copyOf(hosts); } public static ProvisionInfo withHosts(Set<HostSpec> hosts) { @@ -40,13 +43,11 @@ public class ProvisionInfo { private void toSlime(Cursor cursor) { Cursor array = cursor.setArray(mappingKey); - for (HostSpec host : hosts) { - Cursor object = array.addObject(); - serializeHostSpec(object.setObject(hostSpecKey), host); - } + for (HostSpec host : hosts) + toSlime(host, array.addObject().setObject(hostSpecKey)); } - private void serializeHostSpec(Cursor cursor, HostSpec host) { + private void toSlime(HostSpec host, Cursor cursor) { cursor.setString(hostSpecHostName, host.hostname()); if (host.membership().isPresent()) { cursor.setString(hostSpecMembership, host.membership().get().stringValue()); @@ -56,9 +57,8 @@ public class ProvisionInfo { cursor.setString(hostSpecFlavor, host.flavor().get().name()); } - public Set<HostSpec> getHosts() { - return Collections.unmodifiableSet(hosts); - } + /** Returns the hosts of this allocation */ + public Set<HostSpec> getHosts() { return hosts; } private static ProvisionInfo fromSlime(Inspector inspector, Optional<NodeFlavors> nodeFlavors) { Inspector array = inspector.field(mappingKey); @@ -66,27 +66,27 @@ public class ProvisionInfo { array.traverse(new ArrayTraverser() { @Override public void entry(int i, Inspector inspector) { - hosts.add(deserializeHostSpec(inspector.field(hostSpecKey), nodeFlavors)); + hosts.add(hostsFromSlime(inspector.field(hostSpecKey), nodeFlavors)); } }); return new ProvisionInfo(hosts); } - private static HostSpec deserializeHostSpec(Inspector object, Optional<NodeFlavors> nodeFlavors) { + private static HostSpec hostsFromSlime(Inspector object, Optional<NodeFlavors> nodeFlavors) { Optional<ClusterMembership> membership = - object.field(hostSpecMembership).valid() ? Optional.of(readMembership(object)) : Optional.empty(); + object.field(hostSpecMembership).valid() ? Optional.of(membershipFromSlime(object)) : Optional.empty(); Optional<Flavor> flavor = - object.field(hostSpecFlavor).valid() ? readFlavor(object, nodeFlavors) : Optional.empty(); + object.field(hostSpecFlavor).valid() ? flavorFromSlime(object, nodeFlavors) : Optional.empty(); return new HostSpec(object.field(hostSpecHostName).asString(),Collections.emptyList(), flavor, membership); } - private static ClusterMembership readMembership(Inspector object) { + private static ClusterMembership membershipFromSlime(Inspector object) { return ClusterMembership.from(object.field(hostSpecMembership).asString(), com.yahoo.component.Version.fromString(object.field(hostSpecVespaVersion).asString())); } - private static Optional<Flavor> readFlavor(Inspector object, Optional<NodeFlavors> nodeFlavors) { + private static Optional<Flavor> flavorFromSlime(Inspector object, Optional<NodeFlavors> nodeFlavors) { return nodeFlavors.map(flavorMapper -> flavorMapper.getFlavor(object.field(hostSpecFlavor).asString())) .orElse(Optional.empty()); } @@ -100,12 +100,17 @@ public class ProvisionInfo { public static ProvisionInfo fromJson(byte[] json, Optional<NodeFlavors> nodeFlavors) { return fromSlime(SlimeUtils.jsonToSlime(json).get(), nodeFlavors); } - - public ProvisionInfo merge(ProvisionInfo provisionInfo) { - Set<HostSpec> mergedSet = new LinkedHashSet<>(); - mergedSet.addAll(this.hosts); - mergedSet.addAll(provisionInfo.getHosts()); - return ProvisionInfo.withHosts(mergedSet); + + @Override + public boolean equals(Object other) { + if (other == this) return true; + if ( ! (other instanceof ProvisionInfo)) return false; + return ((ProvisionInfo) other).hosts.equals(this.hosts); + } + + @Override + public int hashCode() { + return hosts.hashCode(); } } diff --git a/config-provisioning/src/test/java/com/yahoo/config/provision/ProvisionInfoTest.java b/config-provisioning/src/test/java/com/yahoo/config/provision/ProvisionInfoTest.java index 4fa69eb77e0..435b6e3a28a 100644 --- a/config-provisioning/src/test/java/com/yahoo/config/provision/ProvisionInfoTest.java +++ b/config-provisioning/src/test/java/com/yahoo/config/provision/ProvisionInfoTest.java @@ -13,8 +13,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; /** - * @author lulf - * @since 5.12 + * @author Ulf Lilleengen */ public class ProvisionInfoTest { @@ -32,19 +31,6 @@ public class ProvisionInfoTest { assertProvisionInfo(info); } - @Test - public void testProvisionInfoMerging() throws IOException { - Set<HostSpec> hostsA = new LinkedHashSet<>(Collections.singleton(h1)); - Set<HostSpec> hostsB = new LinkedHashSet<>(); - hostsB.add(h2); - hostsB.add(h3); - - ProvisionInfo infoA = ProvisionInfo.withHosts(hostsA); - ProvisionInfo infoB = ProvisionInfo.withHosts(hostsB); - assertProvisionInfo(infoA.merge(infoB)); - assertProvisionInfo(infoB.merge(infoA)); - } - private void assertProvisionInfo(ProvisionInfo info) throws IOException { ProvisionInfo serializedInfo = ProvisionInfo.fromJson(info.toJson(), Optional.empty()); assertEquals(info.getHosts().size(), serializedInfo.getHosts().size()); diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClient.java b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClient.java index ea278596e80..b2bcba94662 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClient.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClient.java @@ -25,7 +25,6 @@ import java.util.*; * A class used for reading and writing application data to zookeeper. * * @author hmusum - * @since 5.1 */ public class ZooKeeperClient { @@ -356,9 +355,8 @@ public class ZooKeeperClient { } } - private void feedProvisionInfo(Version version, ProvisionInfo info) throws IOException { - byte[] json = info.toJson(); - configCurator.putData(rootPath.append(ZKApplicationPackage.allocatedHostsNode).append(version.toSerializedForm()).getAbsolute(), json); + public void feedProvisionInfo(ProvisionInfo info) throws IOException { + configCurator.putData(rootPath.append(ZKApplicationPackage.allocatedHostsNode).getAbsolute(), info.toJson()); } public void feedZKFileRegistries(Map<Version, FileRegistry> fileRegistryMap) { @@ -367,9 +365,4 @@ public class ZooKeeperClient { } } - public void feedProvisionInfos(Map<Version, ProvisionInfo> provisionInfoMap) throws IOException { - for (Map.Entry<Version, ProvisionInfo> versionProvisionInfoEntry : provisionInfoMap.entrySet()) { - feedProvisionInfo(versionProvisionInfoEntry.getKey(), versionProvisionInfoEntry.getValue()); - } - } } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ZooKeeperDeployer.java b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ZooKeeperDeployer.java index 246d7226cfd..9c0d7f69d19 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ZooKeeperDeployer.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ZooKeeperDeployer.java @@ -14,7 +14,6 @@ import java.util.Map; * Initialize must be called before each deploy. * * @author lulf - * @since 5.1 */ public class ZooKeeperDeployer { @@ -28,15 +27,16 @@ public class ZooKeeperDeployer { * Deploys an application package to zookeeper. initialize() must be called before calling this method. * * @param applicationPackage The application package to persist. - * @param fileRegistryMap The file registries to persist. - * @param provisionInfoMap The provisioning infos to persist. + * @param fileRegistryMap the file registries to persist. + * @param provisionInfo the provisioning info to persist. * @throws IOException if deploying fails */ - public void deploy(ApplicationPackage applicationPackage, Map<Version, FileRegistry> fileRegistryMap, Map<Version, ProvisionInfo> provisionInfoMap) throws IOException { + public void deploy(ApplicationPackage applicationPackage, Map<Version, FileRegistry> fileRegistryMap, + ProvisionInfo provisionInfo) throws IOException { zooKeeperClient.setupZooKeeper(); zooKeeperClient.feedZooKeeper(applicationPackage); zooKeeperClient.feedZKFileRegistries(fileRegistryMap); - zooKeeperClient.feedProvisionInfos(provisionInfoMap); + zooKeeperClient.feedProvisionInfo(provisionInfo); } public void cleanup() { 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 a805d335c2e..86187a08d17 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 @@ -87,7 +87,7 @@ public class ActivatedModelsBuilder extends ModelsBuilder<Application> { logger, configDefinitionRepo, getForVersionOrLatest(applicationPackage.getFileRegistryMap(), modelFactory.getVersion()).orElse(new MockFileRegistry()), - createHostProvisioner(getForVersionOrLatest(applicationPackage.getProvisionInfoMap(), modelFactory.getVersion())), + createHostProvisioner(applicationPackage.getProvisionInfo()), createModelContextProperties(applicationId), Optional.empty(), new com.yahoo.component.Version(modelFactory.getVersion().toString()), diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSession.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSession.java index a222182f87a..0b8f1f67e79 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSession.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/LocalSession.java @@ -30,8 +30,7 @@ import java.util.Optional; * prepared. Deleting a local session will ensure that the local filesystem state and global zookeeper state is * cleaned for this session. * - * @author lulf - * @since 5.1 + * @author Ulf Lilleengen */ // This is really the store of an application, whether it is active or in an edit session // TODO: Separate the "application store" and "session" aspects - the latter belongs in the HTTP layer 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 0b76c57e142..3b96069c4e7 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 @@ -42,8 +42,7 @@ import javax.xml.transform.TransformerException; /** * A SessionPreparer is responsible for preparing a session given an application package. * - * @author lulf - * @since 5.1 + * @author Ulf Lilleengen */ public class SessionPreparer { @@ -195,7 +194,7 @@ public class SessionPreparer { vespaVersion, logger, prepareResult.getFileRegistries(), - prepareResult.getProvisionInfos()); + prepareResult.getProvisionInfo()); checkTimeout("write state to zookeeper"); } @@ -236,10 +235,10 @@ public class SessionPreparer { com.yahoo.component.Version vespaVersion, DeployLogger deployLogger, Map<Version, FileRegistry> fileRegistryMap, - Map<Version, ProvisionInfo> provisionInfoMap) { + ProvisionInfo provisionInfo) { ZooKeeperDeployer zkDeployer = zooKeeperClient.createDeployer(deployLogger); try { - zkDeployer.deploy(applicationPackage, fileRegistryMap, provisionInfoMap); + zkDeployer.deploy(applicationPackage, fileRegistryMap, provisionInfo); zooKeeperClient.writeApplicationId(applicationId); zooKeeperClient.writeVespaVersion(vespaVersion); } catch (RuntimeException | IOException e) { @@ -252,19 +251,20 @@ public class SessionPreparer { private static class PrepareResult { private final ImmutableList<PreparedModelsBuilder.PreparedModelResult> results; + + private final ReconciliatedHostAllocations reconciliatedHostAllocations; public PrepareResult(List<PreparedModelsBuilder.PreparedModelResult> results) { this.results = ImmutableList.copyOf(results); + reconciliatedHostAllocations = new ReconciliatedHostAllocations(results); } /** Returns the results for each model as an immutable list */ public List<PreparedModelsBuilder.PreparedModelResult> asList() { return results; } - public Map<Version, ProvisionInfo> getProvisionInfos() { - return results.stream() - .filter(result -> result.model.getProvisionInfo().isPresent()) - .collect(Collectors.toMap((prepareResult -> prepareResult.version), - (prepareResult -> prepareResult.model.getProvisionInfo().get()))); + /** Returns the host allocations resulting from this preparation. */ + public ProvisionInfo getProvisionInfo() { + return reconciliatedHostAllocations.allocatedHosts(); } public Map<Version, FileRegistry> getFileRegistries() { @@ -290,4 +290,31 @@ public class SessionPreparer { } + /** + * During model building each model version will request nodes allocated (from the node allocator) + * for each cluster specified by that model. As allocations are stable this should usually + * result in the same allocations for the same clusters across all model versions, + * otherwise we should fail this preparation as such inconsistencies lead to undefined behavior, + * and there is really just one true allocation (for a given cluster) to be activated in the node repository. + * + * However, these disagreements between allocations in each model version are allowed: + * - A node may be retired in some model version but not another. This allows model versions to change cluster sizes, + * and is ok because the system will converge on the latest version's opinion + * - Clusters may be present on some version but not on another. This does not lead to inconsistency + * and allows new model versions to introduce new clusters. + * + * For each cluster, the newest model version which has that cluster decides the correct retirement status of nodes + * (and all model versions having the cluster must have the same nodes). + * + * This class ensures these constraints and returns a reconciliated set of nodes which should be activated, + * given a set of model activation results. + */ + private static final class ReconciliatedHostAllocations { + + public ReconciliatedHostAllocations(List<PreparedModelsBuilder.PreparedModelResult> results) { + + } + + } + } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionZooKeeperClient.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionZooKeeperClient.java index a677c5cb7f9..3bd60d3d96c 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionZooKeeperClient.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionZooKeeperClient.java @@ -190,9 +190,8 @@ public class SessionZooKeeperClient { } ProvisionInfo getProvisionInfo() { - return loadApplicationPackage().getProvisionInfoMap().values().stream() - .reduce((infoA, infoB) -> infoA.merge(infoB)) - .orElseThrow(() -> new IllegalStateException("Trying to read provision info, but no provision info exists")); + return loadApplicationPackage().getProvisionInfo() + .orElseThrow(() -> new IllegalStateException("Provision info does not exists")); } public ZooKeeperDeployer createDeployer(DeployLogger logger) { diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ConfigCurator.java b/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ConfigCurator.java index 80c1c44546f..c09fe5ae4bb 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ConfigCurator.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ConfigCurator.java @@ -146,7 +146,7 @@ public class ConfigCurator { /** * Returns the data at a path, or null if the path does not exist. * - * @param path a String with a pathname. + * @param path a String with a pathname. * @return a byte array with data. */ public byte[] getBytes(String path) { diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationPackage.java b/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationPackage.java index 4f591278a38..4aa4fc32483 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationPackage.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationPackage.java @@ -2,6 +2,7 @@ package com.yahoo.vespa.config.server.zookeeper; import com.google.common.base.Joiner; +import com.yahoo.component.Version; import com.yahoo.config.application.api.ApplicationMetaData; import com.yahoo.config.application.api.ComponentInfo; import com.yahoo.config.application.api.FileRegistry; @@ -12,7 +13,6 @@ import com.yahoo.config.application.api.ApplicationPackage; import com.yahoo.config.model.application.provider.*; import com.yahoo.config.provision.NodeFlavors; import com.yahoo.config.provision.ProvisionInfo; -import com.yahoo.config.provision.Version; import com.yahoo.io.IOUtils; import com.yahoo.path.Path; import com.yahoo.io.reader.NamedReader; @@ -24,7 +24,13 @@ import com.yahoo.vespa.config.util.ConfigUtils; import java.io.File; import java.io.Reader; import java.io.StringReader; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; /** * Represents an application residing in zookeeper. @@ -35,9 +41,9 @@ public class ZKApplicationPackage implements ApplicationPackage { private ZKLiveApp liveApp; - private final Map<Version, PreGeneratedFileRegistry> fileRegistryMap = new HashMap<>(); - private final Map<Version, ProvisionInfo> provisionInfoMap = new HashMap<>(); - private static final Version legacyVersion = Version.fromIntValues(0, 0, 0); + private final Map<com.yahoo.config.provision.Version, PreGeneratedFileRegistry> fileRegistryMap = new HashMap<>(); + private final Optional<ProvisionInfo> provisionInfo; + private static final com.yahoo.config.provision.Version legacyVersion = com.yahoo.config.provision.Version.fromIntValues(0, 0, 0); public static final String fileRegistryNode = "fileregistry"; public static final String allocatedHostsNode = "allocatedHosts"; @@ -48,32 +54,54 @@ public class ZKApplicationPackage implements ApplicationPackage { liveApp = new ZKLiveApp(zk, appPath); metaData = readMetaDataFromLiveApp(liveApp); importFileRegistries(fileRegistryNode); - importProvisionInfos(allocatedHostsNode, nodeFlavors); + provisionInfo = importProvisionInfos(allocatedHostsNode, nodeFlavors); } - private void importProvisionInfos(String allocatedHostsNode, Optional<NodeFlavors> nodeFlavors) { - List<String> provisionInfoNodes = liveApp.getChildren(allocatedHostsNode); - if (provisionInfoNodes.isEmpty()) { - Optional<ProvisionInfo> provisionInfo = importProvisionInfo(allocatedHostsNode, nodeFlavors); - provisionInfo.ifPresent(info -> provisionInfoMap.put(legacyVersion, info)); - } else { - provisionInfoNodes.stream() - .forEach(versionStr -> { - Version version = Version.fromString(versionStr); - Optional<ProvisionInfo> provisionInfo = importProvisionInfo(Joiner.on("/").join(allocatedHostsNode, versionStr), - nodeFlavors); - provisionInfo.ifPresent(info -> provisionInfoMap.put(version, info)); - }); + private Optional<ProvisionInfo> importProvisionInfos(String allocatedHostsPath, Optional<NodeFlavors> nodeFlavors) { + if ( ! liveApp.exists(allocatedHostsPath)) return Optional.empty(); + Optional<ProvisionInfo> provisionInfo = readProvisionInfo(allocatedHostsPath, nodeFlavors); + if ( ! provisionInfo.isPresent()) { // Read from legacy location. TODO: Remove when 6.142 is in production everywhere + List<String> provisionInfoByVersionNodes = liveApp.getChildren(allocatedHostsPath); + provisionInfo = newestOf(readProvisionInfosByVersion(provisionInfoByVersionNodes, nodeFlavors)); } + return provisionInfo; + } + + private Map<Version, ProvisionInfo> readProvisionInfosByVersion(List<String> provisionInfoByVersionNodes, Optional<NodeFlavors> nodeFlavors) { + Map<Version, ProvisionInfo> provisionInfoMap = new HashMap<>(); + provisionInfoByVersionNodes.stream() + .forEach(versionStr -> { + Version version = Version.fromString(versionStr); + Optional<ProvisionInfo> provisionInfo = readProvisionInfo(Joiner.on("/").join(allocatedHostsNode, versionStr), + nodeFlavors); + provisionInfo.ifPresent(info -> provisionInfoMap.put(version, info)); + }); + return provisionInfoMap; } - private Optional<ProvisionInfo> importProvisionInfo(String provisionInfoNode, Optional<NodeFlavors> nodeFlavors) { - try { - if (liveApp.exists(provisionInfoNode)) { - return Optional.of(ProvisionInfo.fromJson(liveApp.getBytes(provisionInfoNode), nodeFlavors)); - } else { - return Optional.empty(); + private Optional<ProvisionInfo> newestOf(Map<Version, ProvisionInfo> provisionInfoMap) { + if (provisionInfoMap.isEmpty()) return Optional.empty(); + Version newestVersion = null; + ProvisionInfo newestInfo = null; + for (Map.Entry<Version, ProvisionInfo> entry : provisionInfoMap.entrySet()) { + if (newestVersion == null || newestVersion.isBefore(entry.getKey())) { + newestVersion = entry.getKey(); + newestInfo = entry.getValue(); } + } + return Optional.of(newestInfo); + } + + /** + * Reads provision info at the given node. + * + * @return the provision info at this node or empty if there is no data at this path + */ + private Optional<ProvisionInfo> readProvisionInfo(String provisionInfoPath, Optional<NodeFlavors> nodeFlavors) { + try { + byte[] data = liveApp.getBytes(provisionInfoPath); + if (data.length == 0) return Optional.empty(); // TODO: Remove this line (and make return non-optional) when 6.142 is in production everywhere + return Optional.of(ProvisionInfo.fromJson(data, nodeFlavors)); } catch (Exception e) { throw new RuntimeException("Unable to read provision info", e); } @@ -85,9 +113,9 @@ public class ZKApplicationPackage implements ApplicationPackage { fileRegistryMap.put(legacyVersion, importFileRegistry(fileRegistryNode)); } else { fileRegistryNodes.stream() - .forEach(versionStr -> { - Version version = Version.fromString(versionStr); - fileRegistryMap.put(version, importFileRegistry(Joiner.on("/").join(fileRegistryNode, versionStr))); + .forEach(version -> { + fileRegistryMap.put(com.yahoo.config.provision.Version.fromString(version), + importFileRegistry(Joiner.on("/").join(fileRegistryNode, version))); }); } } @@ -147,16 +175,16 @@ public class ZKApplicationPackage implements ApplicationPackage { return ret; } - public Map<Version, ProvisionInfo> getProvisionInfoMap() { - return Collections.unmodifiableMap(provisionInfoMap); + public Optional<ProvisionInfo> getProvisionInfo() { + return provisionInfo; } @Override - public Map<Version, FileRegistry> getFileRegistryMap() { + public Map<com.yahoo.config.provision.Version, FileRegistry> getFileRegistryMap() { return Collections.unmodifiableMap(fileRegistryMap); } - private Optional<PreGeneratedFileRegistry> getPreGeneratedFileRegistry(Version vespaVersion) { + private Optional<PreGeneratedFileRegistry> getPreGeneratedFileRegistry(com.yahoo.config.provision.Version vespaVersion) { // Assumes at least one file registry, which we always have. Optional<PreGeneratedFileRegistry> fileRegistry = Optional.ofNullable(fileRegistryMap.get(vespaVersion)); if (!fileRegistry.isPresent()) { @@ -243,7 +271,7 @@ public class ZKApplicationPackage implements ApplicationPackage { } @Override - public List<ComponentInfo> getComponentsInfo(Version vespaVersion) { + public List<ComponentInfo> getComponentsInfo(com.yahoo.config.provision.Version vespaVersion) { List<ComponentInfo> components = new ArrayList<>(); PreGeneratedFileRegistry fileRegistry = getPreGeneratedFileRegistry(vespaVersion).get(); for (String path : fileRegistry.getPaths()) { diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ZKLiveApp.java b/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ZKLiveApp.java index 88748cb7689..8084be1cefa 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ZKLiveApp.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/zookeeper/ZKLiveApp.java @@ -173,14 +173,11 @@ public class ZKLiveApp { * Returns the full list of children (file names) in the given path. * * @param path a path relative to the currently active application - * @return a list of file names + * @return a list of file names, which is empty (never null) if the path does not exist */ public List<String> getChildren(String path) { String fullPath = getFullPath(path); - if (! zk.exists(fullPath)) { - log.fine("ZKApplicationPackage: " + fullPath + " is not a valid dir"); - return Collections.emptyList(); - } + if (! zk.exists(fullPath)) return Collections.emptyList(); return zk.getChildren(fullPath); } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClientTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClientTest.java index ac029c12b17..933c1e1d64d 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClientTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/ZooKeeperClientTest.java @@ -1,6 +1,7 @@ // 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.deploy; +import com.google.common.collect.ImmutableSet; import com.yahoo.config.application.api.ApplicationMetaData; import com.yahoo.config.application.api.ApplicationPackage; import com.yahoo.config.application.api.FileRegistry; @@ -174,23 +175,15 @@ public class ZooKeeperClientTest extends TestWithCurator { Path app = Path.fromString("/1"); ZooKeeperClient zooKeeperClient = new ZooKeeperClient(zk, logger, true, app); zooKeeperClient.setupZooKeeper(); - zooKeeperClient.feedProvisionInfos(createProvisionInfos()); + HostSpec host1 = new HostSpec("host1.yahoo.com", Collections.emptyList()); + HostSpec host2 = new HostSpec("host2.yahoo.com", Collections.emptyList()); + ImmutableSet<HostSpec> hosts = ImmutableSet.of(host1, host2); + zooKeeperClient.feedProvisionInfo(ProvisionInfo.withHosts(hosts)); Path hostsPath = app.append(ZKApplicationPackage.allocatedHostsNode); assertTrue(zk.exists(hostsPath.getAbsolute())); - assertEquals(0, zk.getBytes(hostsPath.getAbsolute()).length); // Changed from null - assertTrue(zk.exists(hostsPath.append("1.2.3").getAbsolute())); - assertTrue(zk.exists(hostsPath.append("3.2.1").getAbsolute())); - assertTrue(zk.getBytes(hostsPath.append("1.2.3").getAbsolute()).length > 0); - assertTrue(zk.getBytes(hostsPath.append("3.2.1").getAbsolute()).length > 0); - } - - private Map<Version, ProvisionInfo> createProvisionInfos() { - Map<Version, ProvisionInfo> provisionInfoMap = new HashMap<>(); - ProvisionInfo a = ProvisionInfo.withHosts(Collections.singleton(new HostSpec("host.yahoo.com", Collections.emptyList()))); - ProvisionInfo b = ProvisionInfo.withHosts(Collections.singleton(new HostSpec("host2.yahoo.com", Collections.emptyList()))); - provisionInfoMap.put(Version.fromIntValues(1, 2, 3), a); - provisionInfoMap.put(Version.fromIntValues(3, 2, 1), b); - return provisionInfoMap; + + ProvisionInfo deserialized = ProvisionInfo.fromJson(zk.getBytes(hostsPath.getAbsolute()), Optional.empty()); + assertEquals(hosts, deserialized.getHosts()); } } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/ZooKeeperDeployerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/ZooKeeperDeployerTest.java index 9c7f12c2147..b7bd7918e02 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/ZooKeeperDeployerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/deploy/ZooKeeperDeployerTest.java @@ -4,6 +4,7 @@ package com.yahoo.vespa.config.server.deploy; import com.yahoo.config.application.api.ApplicationPackage; import com.yahoo.config.application.api.DeployLogger; import com.yahoo.config.model.application.provider.*; +import com.yahoo.config.provision.ProvisionInfo; import com.yahoo.config.provision.Version; import com.yahoo.io.IOUtils; import com.yahoo.path.Path; @@ -52,7 +53,7 @@ public class ZooKeeperDeployerTest { ZooKeeperClient client = new ZooKeeperClient(configCurator, logger, true, appPath); ZooKeeperDeployer deployer = new ZooKeeperDeployer(client); - deployer.deploy(applicationPackage, Collections.singletonMap(Version.fromIntValues(1, 0, 0), new MockFileRegistry()), Collections.emptyMap()); + deployer.deploy(applicationPackage, Collections.singletonMap(Version.fromIntValues(1, 0, 0), new MockFileRegistry()), ProvisionInfo.withHosts(Collections.emptySet())); assertTrue(configCurator.exists(appPath.getAbsolute())); } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandlerTest.java index 5e10f364aeb..1719b71b071 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/SessionActiveHandlerTest.java @@ -218,7 +218,7 @@ public class SessionActiveHandlerTest extends SessionHandlerTest { ZooKeeperClient zkC = new ZooKeeperClient(configCurator, new BaseDeployLogger(), false, pathProvider.getSessionDirs().append(String.valueOf(sessionId))); VespaModelFactory modelFactory = new VespaModelFactory(new NullConfigModelRegistry()); zkC.feedZKFileRegistries(Collections.singletonMap(modelFactory.getVersion(), new MockFileRegistry())); - zkC.feedProvisionInfos(Collections.singletonMap(modelFactory.getVersion(), ProvisionInfo.withHosts(Collections.emptySet()))); + zkC.feedProvisionInfo(ProvisionInfo.withHosts(Collections.emptySet())); TestComponentRegistry componentRegistry = new TestComponentRegistry.Builder() .curator(curator) .configCurator(configCurator) diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/provision/StaticProvisionerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/provision/StaticProvisionerTest.java index c54514eb097..2b936a42574 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/provision/StaticProvisionerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/provision/StaticProvisionerTest.java @@ -20,7 +20,7 @@ import java.io.IOException; import static org.junit.Assert.assertEquals; /** - * @author lulf + * @author Ulf Lilleengen */ public class StaticProvisionerTest { @@ -30,7 +30,7 @@ public class StaticProvisionerTest { InMemoryProvisioner inMemoryHostProvisioner = new InMemoryProvisioner(false, "host1.yahoo.com", "host2.yahoo.com", "host3.yahoo.com", "host4.yahoo.com"); VespaModel firstModel = createModel(app, inMemoryHostProvisioner); - StaticProvisioner staticProvisioner = new StaticProvisioner(firstModel.getProvisionInfo().get()); + StaticProvisioner staticProvisioner = new StaticProvisioner(firstModel.provisionInfo()); VespaModel secondModel = createModel(app, staticProvisioner); assertModelConfig(firstModel, secondModel); diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/session/LocalSessionTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/session/LocalSessionTest.java index f0086eabd26..f4be4d31943 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/session/LocalSessionTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/session/LocalSessionTest.java @@ -160,7 +160,7 @@ public class LocalSessionTest { zkc.createWriteStatusTransaction(Session.Status.NEW).commit(); ZooKeeperClient zkClient = new ZooKeeperClient(configCurator, new BaseDeployLogger(), false, appPath); if (provisionInfo.isPresent()) { - zkClient.feedProvisionInfos(Collections.singletonMap(Version.fromIntValues(0, 0, 0), provisionInfo.get())); + zkClient.feedProvisionInfo(provisionInfo.get()); } zkClient.feedZKFileRegistries(Collections.singletonMap(Version.fromIntValues(0, 0, 0), new MockFileRegistry())); File sessionDir = new File(tenantFileSystemDirs.path(), String.valueOf(sessionId)); diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandlerTest.java index 65f546e149a..3dccee1572c 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/tenant/TenantRequestHandlerTest.java @@ -8,6 +8,7 @@ import com.yahoo.config.model.application.provider.BaseDeployLogger; import com.yahoo.config.model.application.provider.FilesApplicationPackage; import com.yahoo.config.model.application.provider.MockFileRegistry; import com.yahoo.config.provision.ApplicationName; +import com.yahoo.config.provision.ProvisionInfo; import com.yahoo.config.provision.Version; import com.yahoo.io.IOUtils; import com.yahoo.path.Path; @@ -94,7 +95,7 @@ public class TenantRequestHandlerTest extends TestWithCurator { File app = tempFolder.newFolder(); IOUtils.copyDirectory(appDir, app); ZooKeeperDeployer deployer = zkc.createDeployer(new BaseDeployLogger()); - deployer.deploy(FilesApplicationPackage.fromFile(appDir), Collections.singletonMap(vespaVersion, new MockFileRegistry()), Collections.emptyMap()); + deployer.deploy(FilesApplicationPackage.fromFile(appDir), Collections.singletonMap(vespaVersion, new MockFileRegistry()), ProvisionInfo.withHosts(Collections.emptySet())); } private ApplicationSet reloadConfig(long id, Clock clock) { diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationPackageTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationPackageTest.java index abc77a91c51..9e91b97806d 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationPackageTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/zookeeper/ZKApplicationPackageTest.java @@ -64,8 +64,7 @@ public class ZKApplicationPackageTest extends TestWithCurator { assertTrue(zkApp.getFileRegistryMap().containsKey(goodVersion)); assertFalse(zkApp.getFileRegistryMap().containsKey(Version.fromIntValues(0, 0, 0))); assertThat(zkApp.getFileRegistryMap().get(goodVersion).fileSourceHost(), is("dummyfiles")); - assertTrue(zkApp.getProvisionInfoMap().containsKey(goodVersion)); - ProvisionInfo readInfo = zkApp.getProvisionInfoMap().get(goodVersion); + ProvisionInfo readInfo = zkApp.getProvisionInfo().get(); assertThat(Utf8.toString(readInfo.toJson()), is(Utf8.toString(provisionInfo.toJson()))); assertThat(readInfo.getHosts().iterator().next().flavor(), is(TEST_FLAVOR)); assertTrue(zkApp.getDeployment().isPresent()); diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java index 914658302b6..e2ff17ba782 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java @@ -24,7 +24,6 @@ public class CapacityPolicies { this.flavors = flavors; } - /** provides capacity defaults for various environments */ public int decideSize(Capacity requestedCapacity) { int requestedNodes = requestedCapacity.nodeCount(); if (requestedCapacity.isRequired()) return requestedNodes; @@ -39,10 +38,10 @@ public class CapacityPolicies { } public Flavor decideFlavor(Capacity requestedCapacity, ClusterSpec cluster, Optional<String> defaultFlavorOverride) { - // for now, always use requested docker flavor when requested + // for now, always use the requested flavor if a docker flavor is requested Optional<String> requestedFlavor = requestedCapacity.flavor(); if (requestedFlavor.isPresent() && - flavors.getFlavorOrThrow(requestedFlavor.get()).getType() == Flavor.Type.DOCKER_CONTAINER) + flavors.getFlavorOrThrow(requestedFlavor.get()).getType() == Flavor.Type.DOCKER_CONTAINER) return flavors.getFlavorOrThrow(requestedFlavor.get()); String defaultFlavorName = defaultFlavorOverride.isPresent() ? |