diff options
79 files changed, 541 insertions, 366 deletions
diff --git a/component/src/main/java/com/yahoo/component/Version.java b/component/src/main/java/com/yahoo/component/Version.java index 7b07cbebdde..8ef540c2ae7 100644 --- a/component/src/main/java/com/yahoo/component/Version.java +++ b/component/src/main/java/com/yahoo/component/Version.java @@ -290,6 +290,9 @@ public final class Version implements Comparable<Version> { public int hashCode() { return stringValue.hashCode(); } + /** Returns whether this equals the empty version */ + public boolean isEmpty() { return this.equals(emptyVersion); } + /** * Compares this <code>Version</code> to another. * diff --git a/config-application-package/pom.xml b/config-application-package/pom.xml index 3e1bdd20936..6bb1191ff8f 100644 --- a/config-application-package/pom.xml +++ b/config-application-package/pom.xml @@ -27,6 +27,12 @@ </dependency> <dependency> <groupId>com.yahoo.vespa</groupId> + <artifactId>component</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.yahoo.vespa</groupId> <artifactId>vespajlib</artifactId> <version>${project.version}</version> <scope>provided</scope> diff --git a/config-application-package/src/main/java/com/yahoo/config/model/application/provider/ApplicationPackageXmlFilesValidator.java b/config-application-package/src/main/java/com/yahoo/config/model/application/provider/ApplicationPackageXmlFilesValidator.java index 201c18527bb..3bc956ae377 100644 --- a/config-application-package/src/main/java/com/yahoo/config/model/application/provider/ApplicationPackageXmlFilesValidator.java +++ b/config-application-package/src/main/java/com/yahoo/config/model/application/provider/ApplicationPackageXmlFilesValidator.java @@ -2,8 +2,8 @@ package com.yahoo.config.model.application.provider; import com.yahoo.collections.Tuple2; +import com.yahoo.component.Version; import com.yahoo.config.application.api.ApplicationPackage; -import com.yahoo.config.provision.Version; import com.yahoo.path.Path; import com.yahoo.io.reader.NamedReader; @@ -21,22 +21,24 @@ import java.util.Optional; public class ApplicationPackageXmlFilesValidator { private final AppSubDirs appDirs; - private final Optional<Version> vespaVersion; + + /** The Vespa version this package tshould be validated against */ + private final Version vespaVersion; private static final FilenameFilter xmlFilter = (dir, name) -> name.endsWith(".xml"); - public ApplicationPackageXmlFilesValidator(AppSubDirs appDirs, Optional<Version> vespaVersion) { + public ApplicationPackageXmlFilesValidator(AppSubDirs appDirs, Version vespaVersion) { this.appDirs = appDirs; this.vespaVersion = vespaVersion; } - public static ApplicationPackageXmlFilesValidator createDefaultXMLValidator(File appDir, Optional<Version> vespaVersion) { + public static ApplicationPackageXmlFilesValidator createDefaultXMLValidator(File appDir, Version vespaVersion) { return new ApplicationPackageXmlFilesValidator(new AppSubDirs(appDir), vespaVersion); } - public static ApplicationPackageXmlFilesValidator createTestXmlValidator(File appDir) { - return new ApplicationPackageXmlFilesValidator(new AppSubDirs(appDir), Optional.empty()); + public static ApplicationPackageXmlFilesValidator createTestXmlValidator(File appDir, Version vespaVersion) { + return new ApplicationPackageXmlFilesValidator(new AppSubDirs(appDir), vespaVersion); } @SuppressWarnings("deprecation") @@ -56,11 +58,11 @@ public class ApplicationPackageXmlFilesValidator { } // For testing - public static void checkIncludedDirs(ApplicationPackage app) throws IOException { + public static void checkIncludedDirs(ApplicationPackage app, Version vespaVersion) throws IOException { for (String includedDir : app.getUserIncludeDirs()) { List<NamedReader> includedFiles = app.getFiles(Path.fromString(includedDir), ".xml", true); for (NamedReader file : includedFiles) { - createSchemaValidator("container-include.rnc", Optional.empty()).validate(file); + createSchemaValidator("container-include.rnc", vespaVersion).validate(file); } } } @@ -115,7 +117,7 @@ public class ApplicationPackageXmlFilesValidator { } } - private static SchemaValidator createSchemaValidator(String schemaFile, Optional<Version> vespaVersion) { + private static SchemaValidator createSchemaValidator(String schemaFile, Version vespaVersion) { return new SchemaValidator(schemaFile, new BaseDeployLogger(), vespaVersion); } diff --git a/config-application-package/src/main/java/com/yahoo/config/model/application/provider/FilesApplicationPackage.java b/config-application-package/src/main/java/com/yahoo/config/model/application/provider/FilesApplicationPackage.java index 06e74e08307..63f19e9abf3 100644 --- a/config-application-package/src/main/java/com/yahoo/config/model/application/provider/FilesApplicationPackage.java +++ b/config-application-package/src/main/java/com/yahoo/config/model/application/provider/FilesApplicationPackage.java @@ -1,6 +1,7 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.config.model.application.provider; +import com.yahoo.component.Vtag; import com.yahoo.config.application.ConfigDefinitionDir; import com.yahoo.config.application.Xml; import com.yahoo.config.application.XmlPreProcessor; @@ -630,9 +631,10 @@ public class FilesApplicationPackage implements ApplicationPackage { @Override public void validateXML(Optional<Version> vespaVersion) throws IOException { - ApplicationPackageXmlFilesValidator xmlFilesValidator = ApplicationPackageXmlFilesValidator.createDefaultXMLValidator(appDir, vespaVersion); + com.yahoo.component.Version modelVersion = vespaVersion.map(v -> new com.yahoo.component.Version(vespaVersion.toString())).orElse(Vtag.currentVersion); + ApplicationPackageXmlFilesValidator xmlFilesValidator = ApplicationPackageXmlFilesValidator.createDefaultXMLValidator(appDir, modelVersion); xmlFilesValidator.checkApplication(); - ApplicationPackageXmlFilesValidator.checkIncludedDirs(this); + ApplicationPackageXmlFilesValidator.checkIncludedDirs(this, modelVersion); } @Override diff --git a/config-application-package/src/main/java/com/yahoo/config/model/application/provider/SchemaValidator.java b/config-application-package/src/main/java/com/yahoo/config/model/application/provider/SchemaValidator.java index 698fa8fdce7..fd1156d435a 100644 --- a/config-application-package/src/main/java/com/yahoo/config/model/application/provider/SchemaValidator.java +++ b/config-application-package/src/main/java/com/yahoo/config/model/application/provider/SchemaValidator.java @@ -6,8 +6,8 @@ import com.thaiopensource.util.PropertyMapBuilder; import com.thaiopensource.validate.ValidateProperty; import com.thaiopensource.validate.ValidationDriver; import com.thaiopensource.validate.rng.CompactSchemaReader; +import com.yahoo.component.Version; import com.yahoo.config.application.api.DeployLogger; -import com.yahoo.config.provision.Version; import com.yahoo.io.IOUtils; import com.yahoo.io.reader.NamedReader; import com.yahoo.log.LogLevel; @@ -27,7 +27,6 @@ import java.io.Reader; import java.net.JarURLConnection; import java.net.URL; import java.util.Enumeration; -import java.util.Optional; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.logging.Level; @@ -53,8 +52,9 @@ public class SchemaValidator { * Initializes the validator by using the given file as schema file * @param schema a schema file in RNC format * @param logger a logger + * @param vespaVersion the version of Vespa we should validate against */ - public SchemaValidator(String schema, DeployLogger logger, Optional<Version> vespaVersion) { + public SchemaValidator(String schema, DeployLogger logger, Version vespaVersion) { this.deployLogger = logger; driver = new ValidationDriver(PropertyMap.EMPTY, instanceProperties(), CompactSchemaReader.getInstance()); File schemaDir = new File(schemaDirBase); @@ -70,26 +70,27 @@ public class SchemaValidator { /** * Initializes the validator by using the given file as schema file * @param schema a schema file in RNC format + * @param vespaVersion the version we should validate against * @throws IOException if it is not possible to read schema files */ - public SchemaValidator(String schema) throws IOException { - this(schema, new BaseDeployLogger(), Optional.empty()); + public SchemaValidator(String schema, Version vespaVersion) throws IOException { + this(schema, new BaseDeployLogger(), vespaVersion); } /** * Create a validator for services.xml for tests * @throws IOException if it is not possible to read schema files */ - public static SchemaValidator createTestValidatorServices() throws IOException { - return new SchemaValidator(servicesXmlSchemaName); + public static SchemaValidator createTestValidatorServices(Version vespaVersion) throws IOException { + return new SchemaValidator(servicesXmlSchemaName, vespaVersion); } /** * Create a validator for hosts.xml for tests * @throws IOException if it is not possible to read schema files */ - public static SchemaValidator createTestValidatorHosts() throws IOException { - return new SchemaValidator(hostsXmlSchemaName); + public static SchemaValidator createTestValidatorHosts(Version vespaVersion) throws IOException { + return new SchemaValidator(hostsXmlSchemaName, vespaVersion); } /** @@ -97,8 +98,8 @@ public class SchemaValidator { * * @throws IOException if it is not possible to read schema files */ - public static SchemaValidator createTestValidatorDeployment() throws IOException { - return new SchemaValidator(deploymentXmlSchemaName); + public static SchemaValidator createTestValidatorDeployment(Version vespaVersion) throws IOException { + return new SchemaValidator(deploymentXmlSchemaName, vespaVersion); } private class CustomErrorHandler implements ErrorHandler { @@ -129,7 +130,7 @@ public class SchemaValidator { * @return the directory the schema files are stored in * @throws IOException if it is not possible to read schema files */ - public File saveSchemasFromJar(File tmpBase, Optional<Version> vespaVersion) throws IOException { + private File saveSchemasFromJar(File tmpBase, Version vespaVersion) throws IOException { final Class<? extends SchemaValidator> schemaValidatorClass = this.getClass(); final ClassLoader classLoader = schemaValidatorClass.getClassLoader(); Enumeration<URL> uris = classLoader.getResources("schema"); @@ -158,7 +159,7 @@ public class SchemaValidator { // TODO: Hack to handle cases where bundle=null if (bundle == null) { File schemaPath; - if (vespaVersion.isPresent() && vespaVersion.get().getMajor() == 5) { + if (vespaVersion.getMajor() == 5) { schemaPath = new File(Defaults.getDefaults().vespaHome() + "share/vespa/schema/version/5.x/schema/"); } else { schemaPath = new File(Defaults.getDefaults().vespaHome() + "share/vespa/schema/"); @@ -234,12 +235,12 @@ public class SchemaValidator { errorHandler.fileName = (fileName == null ? " input" : fileName); try { if ( ! driver.validate(inputSource)) { - //Shouldn't happen, error handler should have thrown + // Shouldn't happen, error handler should have thrown throw new RuntimeException("Aborting due to earlier XML errors."); } } catch (SAXException e) { - //This should never happen, as it is handled by the ErrorHandler - //installed for the driver. + // This should never happen, as it is handled by the ErrorHandler + // installed for the driver. throw new IllegalArgumentException( "XML error in " + (fileName == null ? " input" : fileName) + ": " + Exceptions.toMessageString(e)); } diff --git a/config-application-package/src/main/java/com/yahoo/config/model/application/provider/SimpleApplicationValidator.java b/config-application-package/src/main/java/com/yahoo/config/model/application/provider/SimpleApplicationValidator.java index 2d960f00d66..97b989617b3 100644 --- a/config-application-package/src/main/java/com/yahoo/config/model/application/provider/SimpleApplicationValidator.java +++ b/config-application-package/src/main/java/com/yahoo/config/model/application/provider/SimpleApplicationValidator.java @@ -1,6 +1,8 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.config.model.application.provider; +import com.yahoo.component.Version; + import java.io.IOException; import java.io.Reader; @@ -11,7 +13,7 @@ import java.io.Reader; */ public class SimpleApplicationValidator { - public static void checkServices(Reader reader) throws IOException { - SchemaValidator.createTestValidatorServices().validate(reader); + public static void checkServices(Reader reader, Version version) throws IOException { + SchemaValidator.createTestValidatorServices(version).validate(reader); } } diff --git a/config-model-api/pom.xml b/config-model-api/pom.xml index cf016ec4ee0..8fa2d482cab 100644 --- a/config-model-api/pom.xml +++ b/config-model-api/pom.xml @@ -29,6 +29,12 @@ </dependency> <dependency> <groupId>com.yahoo.vespa</groupId> + <artifactId>component</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.yahoo.vespa</groupId> <artifactId>defaults</artifactId> <version>${project.version}</version> <scope>provided</scope> 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 9226e3bbe11..cd8ca30f36d 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 @@ -1,12 +1,12 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.config.model.api; +import com.yahoo.component.Version; import com.yahoo.config.application.api.ApplicationPackage; import com.yahoo.config.application.api.DeployLogger; import com.yahoo.config.application.api.FileRegistry; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.Rotation; -import com.yahoo.config.provision.Version; import com.yahoo.config.provision.Zone; import java.io.File; @@ -30,7 +30,17 @@ public interface ModelContext { FileRegistry getFileRegistry(); Properties properties(); default Optional<File> appDir() { return Optional.empty();} - default Optional<Version> vespaVersion() { 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(); + + /** The Vespa version we want nodes to become */ + Version wantedNodeVespaVersion(); interface Properties { boolean multitenant(); diff --git a/config-model-api/src/main/java/com/yahoo/config/model/api/ModelFactory.java b/config-model-api/src/main/java/com/yahoo/config/model/api/ModelFactory.java index a61001cc9d9..2f80e66af05 100644 --- a/config-model-api/src/main/java/com/yahoo/config/model/api/ModelFactory.java +++ b/config-model-api/src/main/java/com/yahoo/config/model/api/ModelFactory.java @@ -9,10 +9,9 @@ import com.yahoo.config.provision.Version; public interface ModelFactory { /** - * Gets version of this {@link ModelFactory}. The version will be used to dispatch deployments to the correct - * {@link ModelFactory}. + * Returns the Vespa version of the models this builds. * - * @return The version of a {@link Model} instance that this factory can create. + * @return the version of a {@link Model} instance that this factory can create. */ Version getVersion(); @@ -21,7 +20,7 @@ public interface ModelFactory { * validation will be done, calling this method assumes that {@link #createAndValidateModel} has already * been called at some point for this model. * - * @param modelContext An instance of {@link ModelContext}, containing dependencies for creating a {@link Model}. + * @param modelContext an instance of {@link ModelContext}, containing dependencies for creating a {@link Model}. * @return a {@link Model} instance. */ Model createModel(ModelContext modelContext); @@ -30,8 +29,8 @@ public interface ModelFactory { * Creates an instance of a {@link Model}. The resulting instance will be used to serve config. Any validation * of a {@link Model} and the {@link ModelContext} can be done in this method. * - * @param modelContext An instance of {@link ModelContext}, containing dependencies for creating a {@link Model}. - * @param ignoreValidationErrors true if validation errors should not trigger exceptions. + * @param modelContext an instance of {@link ModelContext}, containing dependencies for creating a {@link Model} + * @param ignoreValidationErrors true if validation errors should not trigger exceptions * @return a {@link ModelCreateResult} instance. */ ModelCreateResult createAndValidateModel(ModelContext modelContext, boolean ignoreValidationErrors); diff --git a/config-model/src/main/java/com/yahoo/config/model/deploy/DeployProperties.java b/config-model/src/main/java/com/yahoo/config/model/deploy/DeployProperties.java index c734e5a9c42..ccf300aedbd 100644 --- a/config-model/src/main/java/com/yahoo/config/model/deploy/DeployProperties.java +++ b/config-model/src/main/java/com/yahoo/config/model/deploy/DeployProperties.java @@ -51,6 +51,7 @@ public class DeployProperties { return hostedVespa; } + /** Returns the config model version this is building */ public Version vespaVersion() { return vespaVersion; } diff --git a/config-model/src/main/java/com/yahoo/config/model/deploy/DeployState.java b/config-model/src/main/java/com/yahoo/config/model/deploy/DeployState.java index 968e690fac3..14f42a56bc3 100644 --- a/config-model/src/main/java/com/yahoo/config/model/deploy/DeployState.java +++ b/config-model/src/main/java/com/yahoo/config/model/deploy/DeployState.java @@ -1,6 +1,8 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.config.model.deploy; +import com.yahoo.component.Version; +import com.yahoo.component.Vtag; import com.yahoo.config.application.api.ApplicationPackage; import com.yahoo.config.application.api.DeployLogger; import com.yahoo.config.application.api.FileRegistry; @@ -47,7 +49,7 @@ import java.util.Set; import java.util.logging.Logger; /** - * Contains various state during deploy that should be reachable to all builders of a {@link com.yahoo.config.model.ConfigModel} + * Contains various state during deploy that should be available in all builders of a {@link com.yahoo.config.model.ConfigModel} * * @author lulf * @since 5.8 @@ -68,6 +70,7 @@ public class DeployState implements ConfigDefinitionStore { private final QueryProfiles queryProfiles; private final SemanticRules semanticRules; private final ValidationOverrides validationOverrides; + private final Version wantedNodeVespaVersion; private final HostProvisioner provisioner; @@ -83,18 +86,14 @@ public class DeployState implements ConfigDefinitionStore { FileRegistry fileRegistry, DeployLogger deployLogger, Optional<HostProvisioner> hostProvisioner, DeployProperties properties, Optional<ApplicationPackage> permanentApplicationPackage, Optional<ConfigDefinitionRepo> configDefinitionRepo, java.util.Optional<Model> previousModel, Set<Rotation> rotations, Zone zone, QueryProfiles queryProfiles, - SemanticRules semanticRules, Instant now) { + SemanticRules semanticRules, Instant now, Version wantedNodeVespaVersion) { this.logger = deployLogger; this.fileRegistry = fileRegistry; this.rankProfileRegistry = rankProfileRegistry; this.applicationPackage = applicationPackage; this.properties = properties; this.previousModel = previousModel; - if (hostProvisioner.isPresent()) { - this.provisioner = hostProvisioner.get(); - } else { - this.provisioner = getDefaultModelHostProvisioner(applicationPackage); - } + this.provisioner = hostProvisioner.orElse(getDefaultModelHostProvisioner(applicationPackage)); this.searchDefinitions = searchDocumentModel.getSearchDefinitions(); this.documentModel = searchDocumentModel.getDocumentModel(); this.permanentApplicationPackage = permanentApplicationPackage; @@ -104,7 +103,7 @@ public class DeployState implements ConfigDefinitionStore { this.queryProfiles = queryProfiles; // TODO: Remove this by seeing how pagetemplates are propagated this.semanticRules = semanticRules; // TODO: Remove this by seeing how pagetemplates are propagated this.validationOverrides = new ValidationOverridesXMLReader().read(applicationPackage.getValidationOverrides(), now); - + this.wantedNodeVespaVersion = wantedNodeVespaVersion; } public static HostProvisioner getDefaultModelHostProvisioner(ApplicationPackage applicationPackage) { @@ -212,6 +211,8 @@ public class DeployState implements ConfigDefinitionStore { public QueryProfiles getQueryProfiles() { return queryProfiles; } public SemanticRules getSemanticRules() { return semanticRules; } + + public Version getWantedNodeVespaVersion() { return wantedNodeVespaVersion; } public static class Builder { @@ -226,6 +227,7 @@ public class DeployState implements ConfigDefinitionStore { private Set<Rotation> rotations = new HashSet<>(); private Zone zone = Zone.defaultZone(); private Instant now = Instant.now(); + private Version wantedNodeVespaVersion = Vtag.currentVersion; public Builder applicationPackage(ApplicationPackage applicationPackage) { this.applicationPackage = applicationPackage; @@ -281,6 +283,11 @@ public class DeployState implements ConfigDefinitionStore { this.now = now; return this; } + + public Builder wantedNodeVespaVersion(Version version) { + this.wantedNodeVespaVersion = version; + return this; + } public DeployState build() { RankProfileRegistry rankProfileRegistry = new RankProfileRegistry(); @@ -288,7 +295,7 @@ public class DeployState implements ConfigDefinitionStore { SemanticRules semanticRules = new SemanticRuleBuilder().build(applicationPackage); SearchDocumentModel searchDocumentModel = createSearchDocumentModel(rankProfileRegistry, logger, queryProfiles); return new DeployState(applicationPackage, searchDocumentModel, rankProfileRegistry, fileRegistry, logger, hostProvisioner, - properties, permanentApplicationPackage, configDefinitionRepo, previousModel, rotations, zone, queryProfiles, semanticRules, now); + properties, permanentApplicationPackage, configDefinitionRepo, previousModel, rotations, zone, queryProfiles, semanticRules, now, wantedNodeVespaVersion); } private SearchDocumentModel createSearchDocumentModel(RankProfileRegistry rankProfileRegistry, DeployLogger logger, QueryProfiles queryProfiles) { diff --git a/config-model/src/main/java/com/yahoo/config/model/test/TestDriver.java b/config-model/src/main/java/com/yahoo/config/model/test/TestDriver.java index 4518e44d441..38523b33549 100644 --- a/config-model/src/main/java/com/yahoo/config/model/test/TestDriver.java +++ b/config-model/src/main/java/com/yahoo/config/model/test/TestDriver.java @@ -2,6 +2,7 @@ package com.yahoo.config.model.test; import com.google.common.annotations.Beta; +import com.yahoo.component.Version; import com.yahoo.config.model.MapConfigModelRegistry; import com.yahoo.config.application.api.ApplicationPackage; import com.yahoo.config.model.application.provider.SchemaValidator; @@ -101,11 +102,11 @@ public class TestDriver { if (!validate) { return; } - SchemaValidator validator = SchemaValidator.createTestValidatorHosts(); + SchemaValidator validator = SchemaValidator.createTestValidatorHosts(new Version(6)); if (appPkg.getHosts() != null) { validator.validate(appPkg.getHosts()); } - validator = SchemaValidator.createTestValidatorServices(); + validator = SchemaValidator.createTestValidatorServices(new Version(6)); validator.validate(appPkg.getServices()); } } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/VespaModelFactory.java b/config-model/src/main/java/com/yahoo/vespa/model/VespaModelFactory.java index 35ea2134813..36071c4387e 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/VespaModelFactory.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/VespaModelFactory.java @@ -70,6 +70,7 @@ public class VespaModelFactory implements ModelFactory { this.clock = clock; } + /** Returns the version this model is build for */ @Override public Version getVersion() { return Version.fromIntValues(VespaVersion.major, VespaVersion.minor, VespaVersion.micro); @@ -81,14 +82,24 @@ public class VespaModelFactory implements ModelFactory { } @Override - public ModelCreateResult createAndValidateModel(ModelContext modelContext, boolean ignoreValidationErrors) { + public ModelCreateResult createAndValidateModel(ModelContext modelContext, + boolean ignoreValidationErrors) { + validateXml(modelContext, ignoreValidationErrors); + DeployState deployState = createDeployState(modelContext); + VespaModel model = buildModel(deployState); + List<ConfigChangeAction> changeActions = validateModel(model, deployState, ignoreValidationErrors); + return new ModelCreateResult(model, changeActions); + } + + private void validateXml(ModelContext modelContext, boolean ignoreValidationErrors) { if (modelContext.appDir().isPresent()) { ApplicationPackageXmlFilesValidator validator = ApplicationPackageXmlFilesValidator.createDefaultXMLValidator(modelContext.appDir().get(), - modelContext.vespaVersion()); + modelContext.modelVespaVersion()); try { validator.checkApplication(); - ApplicationPackageXmlFilesValidator.checkIncludedDirs(modelContext.applicationPackage()); + ApplicationPackageXmlFilesValidator.checkIncludedDirs(modelContext.applicationPackage(), + modelContext.modelVespaVersion()); } catch (IllegalArgumentException e) { rethrowUnlessIgnoreErrors(e, ignoreValidationErrors); } catch (Exception e) { @@ -98,10 +109,6 @@ public class VespaModelFactory implements ModelFactory { } else { validateXML(modelContext.applicationPackage(), ignoreValidationErrors); } - DeployState deployState = createDeployState(modelContext); - VespaModel model = buildModel(deployState); - List<ConfigChangeAction> changeActions = validateModel(model, deployState, ignoreValidationErrors); - return new ModelCreateResult(model, changeActions); } private VespaModel buildModel(DeployState deployState) { @@ -123,7 +130,8 @@ public class VespaModelFactory implements ModelFactory { .modelHostProvisioner(createHostProvisioner(modelContext)) .rotations(modelContext.properties().rotations()) .zone(zone) - .now(clock.instant()); + .now(clock.instant()) + .wantedNodeVespaVersion(modelContext.wantedNodeVespaVersion()); modelContext.previousModel().ifPresent(builder::previousModel); return builder.build(); } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminBuilderBase.java b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminBuilderBase.java index 0a433cbc122..260d8f72270 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminBuilderBase.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminBuilderBase.java @@ -63,21 +63,21 @@ public abstract class DomAdminBuilderBase extends VespaDomBuilder.DomConfigProdu } @Override - protected Admin doBuild(AbstractConfigProducer parent, Element adminE) { - Yamas yamas = getYamas(XML.getChild(adminE, "yamas")); + protected Admin doBuild(AbstractConfigProducer parent, Element adminElement) { + Yamas yamas = getYamas(XML.getChild(adminElement, "yamas")); Metrics metrics = new MetricsBuilder(applicationType, predefinedMetricSets) - .buildMetrics(XML.getChild(adminE, "metrics")); + .buildMetrics(XML.getChild(adminElement, "metrics")); Map<String, MetricsConsumer> legacyMetricsConsumers = DomMetricBuilderHelper - .buildMetricsConsumers(XML.getChild(adminE, "metric-consumers")); + .buildMetricsConsumers(XML.getChild(adminElement, "metric-consumers")); Admin admin = new Admin(parent, yamas, metrics, legacyMetricsConsumers, multitenant); - doBuildAdmin(admin, adminE); + doBuildAdmin(admin, adminElement); new ModelConfigProvider(admin); - FileDistributionOptions fileDistributionOptions = new DomFileDistributionOptionsBuilder().build(XML.getChild(adminE, "filedistribution")); + FileDistributionOptions fileDistributionOptions = new DomFileDistributionOptionsBuilder().build(XML.getChild(adminElement, "filedistribution")); admin.setFileDistribution(new FileDistributionConfigProducer.Builder(fileDistributionOptions).build(parent, fileRegistry)); return admin; } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV4Builder.java b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV4Builder.java index 760fe246fc5..08843d306b7 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV4Builder.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV4Builder.java @@ -1,6 +1,7 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.model.builder.xml.dom; +import com.yahoo.component.Version; import com.yahoo.config.model.api.ConfigServerSpec; import com.yahoo.config.provision.ClusterSpec; import com.yahoo.config.application.api.DeployLogger; @@ -28,25 +29,29 @@ import java.util.Optional; public class DomAdminV4Builder extends DomAdminBuilderBase { private final Collection<ContainerModel> containerModels; - private final DeployLogger deployLogger; + private final ConfigModelContext context; - public DomAdminV4Builder(ConfigModelContext modelContext, boolean multitenant, List<ConfigServerSpec> configServerSpecs, Collection<ContainerModel> containerModels) { - super(modelContext.getApplicationType(), modelContext.getDeployState().getFileRegistry(), multitenant, configServerSpecs); + public DomAdminV4Builder(ConfigModelContext context, boolean multitenant, List<ConfigServerSpec> configServerSpecs, Collection<ContainerModel> containerModels) { + super(context.getApplicationType(), context.getDeployState().getFileRegistry(), multitenant, configServerSpecs); this.containerModels = containerModels; - this.deployLogger = modelContext.getDeployLogger(); + this.context = context; } @Override protected void doBuildAdmin(Admin admin, Element w3cAdminElement) { ModelElement adminElement = new ModelElement(w3cAdminElement); admin.addConfigservers(getConfigServersFromSpec(admin)); - + Version version = context.getDeployState().getWantedNodeVespaVersion(); + // Note: These two elements only exists in admin version 4.0 // This build handles admin version 3.0 by ignoring its content (as the content is not useful) - Optional<NodesSpecification> requestedSlobroks = NodesSpecification.optionalDedicatedFromParent(adminElement.getChild("slobroks")); - Optional<NodesSpecification> requestedLogservers = NodesSpecification.optionalDedicatedFromParent(adminElement.getChild("logservers")); - assignSlobroks(requestedSlobroks.orElse(NodesSpecification.nonDedicated(3)), admin); - assignLogserver(requestedLogservers.orElse(NodesSpecification.nonDedicated(1)), admin); + Optional<NodesSpecification> requestedSlobroks = + NodesSpecification.optionalDedicatedFromParent(adminElement.getChild("slobroks"), version); + Optional<NodesSpecification> requestedLogservers = + NodesSpecification.optionalDedicatedFromParent(adminElement.getChild("logservers"), version); + + assignSlobroks(requestedSlobroks.orElse(NodesSpecification.nonDedicated(3, version)), admin); + assignLogserver(requestedLogservers.orElse(NodesSpecification.nonDedicated(1, version)), admin); } private void assignSlobroks(NodesSpecification nodesSpecification, Admin admin) { @@ -71,7 +76,10 @@ public class DomAdminV4Builder extends DomAdminBuilderBase { } private Collection<HostResource> allocateHosts(HostSystem hostSystem, String clusterId, NodesSpecification nodesSpecification) { - return nodesSpecification.provision(hostSystem, ClusterSpec.Type.admin, ClusterSpec.Id.from(clusterId), deployLogger).keySet(); + return nodesSpecification.provision(hostSystem, + ClusterSpec.Type.admin, + ClusterSpec.Id.from(clusterId), + context.getDeployLogger()).keySet(); } /** diff --git a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/NodesSpecification.java b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/NodesSpecification.java index c83f6098a0f..eeb6d286da4 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/NodesSpecification.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/NodesSpecification.java @@ -1,6 +1,7 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.model.builder.xml.dom; +import com.yahoo.component.Version; import com.yahoo.config.provision.Capacity; import com.yahoo.config.provision.ClusterMembership; import com.yahoo.config.provision.ClusterSpec; @@ -25,30 +26,37 @@ public class NodesSpecification { private final int groups; + /** The Vespa version we want the nodes to run */ + private Version version; + /** * Whether the capacity amount specified is required or can it be relaxed * at the discretion of the component fulfilling it */ private final boolean required; - + + /** The flavor the nodes should have, or empty to use the default */ private final Optional<String> flavor; + /** The identifier of the custom docker image layer to use (not supported yet) */ private final Optional<String> dockerImage; - private NodesSpecification(boolean dedicated, int count, int groups, boolean required, + private NodesSpecification(boolean dedicated, int count, int groups, Version version, boolean required, Optional<String> flavor, Optional<String> dockerImage) { this.dedicated = dedicated; this.count = count; this.groups = groups; + this.version = version; this.required = required; this.flavor = flavor; this.dockerImage = dockerImage; } - private NodesSpecification(boolean dedicated, ModelElement nodesElement) { + private NodesSpecification(boolean dedicated, Version version, ModelElement nodesElement) { this(dedicated, nodesElement.requiredIntegerAttribute("count"), nodesElement.getIntegerAttribute("groups", 1), + version, nodesElement.getBooleanAttribute("required", false), Optional.ofNullable(nodesElement.getStringAttribute("flavor")), Optional.ofNullable(nodesElement.getStringAttribute("docker-image"))); @@ -57,8 +65,8 @@ public class NodesSpecification { /** * Returns a requirement for dedicated nodes taken from the given <code>nodes</code> element */ - public static NodesSpecification from(ModelElement nodesElement) { - return new NodesSpecification(true, nodesElement); + public static NodesSpecification from(ModelElement nodesElement, Version version) { + return new NodesSpecification(true, version, nodesElement); } /** @@ -66,11 +74,11 @@ public class NodesSpecification { * contained in the given parent element, or empty if the parent element is null, or the nodes elements * is not present. */ - public static Optional<NodesSpecification> fromParent(ModelElement parentElement) { + public static Optional<NodesSpecification> fromParent(ModelElement parentElement, Version version) { if (parentElement == null) return Optional.empty(); ModelElement nodesElement = parentElement.getChild("nodes"); if (nodesElement == null) return Optional.empty(); - return Optional.of(from(nodesElement)); + return Optional.of(from(nodesElement, version)); } /** @@ -78,16 +86,16 @@ public class NodesSpecification { * contained in the given parent element, or empty if the parent element is null, or the nodes elements * is not present. */ - public static Optional<NodesSpecification> optionalDedicatedFromParent(ModelElement parentElement) { + public static Optional<NodesSpecification> optionalDedicatedFromParent(ModelElement parentElement, Version version) { if (parentElement == null) return Optional.empty(); ModelElement nodesElement = parentElement.getChild("nodes"); if (nodesElement == null) return Optional.empty(); - return Optional.of(new NodesSpecification(nodesElement.getBooleanAttribute("dedicated", false), nodesElement)); + return Optional.of(new NodesSpecification(nodesElement.getBooleanAttribute("dedicated", false), version, nodesElement)); } /** Returns a requirement from <code>count</code> nondedicated nodes in one group */ - public static NodesSpecification nonDedicated(int count) { - return new NodesSpecification(false, count, 1, false, Optional.empty(), Optional.empty()); + public static NodesSpecification nonDedicated(int count, Version version) { + return new NodesSpecification(false, count, 1, version, false, Optional.empty(), Optional.empty()); } /** @@ -103,7 +111,7 @@ public class NodesSpecification { public int groups() { return groups; } public Map<HostResource, ClusterMembership> provision(HostSystem hostSystem, ClusterSpec.Type clusterType, ClusterSpec.Id clusterId, DeployLogger logger) { - ClusterSpec cluster = ClusterSpec.request(clusterType, clusterId, dockerImage); + ClusterSpec cluster = ClusterSpec.request(clusterType, clusterId, version); return hostSystem.allocateHosts(cluster, Capacity.fromNodeCount(count, flavor, required), groups, logger); } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java index c39b3247be1..32811fdcb78 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java @@ -400,9 +400,9 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> { private List<Container> createNodes(ContainerCluster cluster, Element nodesElement, ConfigModelContext context) { if (nodesElement.hasAttribute("count")) // regular, hosted node spec - return createNodesFromNodeCount(cluster, nodesElement); + return createNodesFromNodeCount(cluster, nodesElement, context); else if (nodesElement.hasAttribute("type")) // internal use for hosted system infrastructure nodes - return createNodesFromNodeType(cluster, nodesElement); + return createNodesFromNodeType(cluster, nodesElement, context); else if (nodesElement.hasAttribute("of")) // hosted node spec referencing a content cluster return createNodesFromContentServiceReference(cluster, nodesElement, context); else // the non-hosted option @@ -448,7 +448,7 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> { return singleContentHost.get(); } else { // request 1 node - ClusterSpec clusterSpec = ClusterSpec.request(ClusterSpec.Type.container, ClusterSpec.Id.from(cluster.getName()), Optional.empty()); + ClusterSpec clusterSpec = ClusterSpec.request(ClusterSpec.Type.container, ClusterSpec.Id.from(cluster.getName()), context.getDeployState().getWantedNodeVespaVersion()); return cluster.getHostSystem().allocateHosts(clusterSpec, Capacity.fromNodeCount(1), 1, logger).keySet().iterator().next(); } } else { @@ -456,8 +456,9 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> { } } - private List<Container> createNodesFromNodeCount(ContainerCluster cluster, Element nodesElement) { - NodesSpecification nodesSpecification = NodesSpecification.from(new ModelElement(nodesElement)); + private List<Container> createNodesFromNodeCount(ContainerCluster cluster, Element nodesElement, ConfigModelContext context) { + NodesSpecification nodesSpecification = NodesSpecification.from(new ModelElement(nodesElement), + context.getDeployState().getWantedNodeVespaVersion()); Map<HostResource, ClusterMembership> hosts = nodesSpecification.provision(cluster.getRoot().getHostSystem(), ClusterSpec.Type.container, ClusterSpec.Id.from(cluster.getName()), @@ -465,11 +466,11 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> { return createNodesFromHosts(hosts, cluster); } - private List<Container> createNodesFromNodeType(ContainerCluster cluster, Element nodesElement) { + private List<Container> createNodesFromNodeType(ContainerCluster cluster, Element nodesElement, ConfigModelContext context) { NodeType type = NodeType.valueOf(nodesElement.getAttribute("type")); ClusterSpec clusterSpec = ClusterSpec.request(ClusterSpec.Type.container, ClusterSpec.Id.from(cluster.getName()), - Optional.empty()); + context.getDeployState().getWantedNodeVespaVersion()); Map<HostResource, ClusterMembership> hosts = cluster.getRoot().getHostSystem().allocateHosts(clusterSpec, Capacity.fromRequiredNodeType(type), 1, log); @@ -492,7 +493,8 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> { cluster.setHostClusterId(referenceId); Map<HostResource, ClusterMembership> hosts = - StorageGroup.provisionHosts(NodesSpecification.from(new ModelElement(referencedNodesElement)), + StorageGroup.provisionHosts(NodesSpecification.from(new ModelElement(referencedNodesElement), + context.getDeployState().getWantedNodeVespaVersion()), referenceId, cluster.getRoot().getHostSystem(), context.getDeployLogger()); @@ -514,9 +516,9 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> { NodesSpecification nodesSpec; if (contentNodesElementOrNull == null) - nodesSpec = NodesSpecification.nonDedicated(1); + nodesSpec = NodesSpecification.nonDedicated(1, context.getDeployState().getWantedNodeVespaVersion()); else - nodesSpec = NodesSpecification.from(new ModelElement(contentNodesElementOrNull)); + nodesSpec = NodesSpecification.from(new ModelElement(contentNodesElementOrNull), context.getDeployState().getWantedNodeVespaVersion()); Map<HostResource, ClusterMembership> hosts = StorageGroup.provisionHosts(nodesSpec, diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/Content.java b/config-model/src/main/java/com/yahoo/vespa/model/content/Content.java index 7625374b0a0..681dba789ca 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/content/Content.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/content/Content.java @@ -215,7 +215,7 @@ public class Content extends ConfigModel { @Override public void doBuild(Content content, Element xml, ConfigModelContext modelContext) { Admin admin = content.adminModel != null ? content.adminModel.getAdmin() : null; // This is null in tests only - content.cluster = new ContentCluster.Builder(admin, modelContext.getDeployLogger()).build(content.containers, modelContext.getParentProducer(), xml); + content.cluster = new ContentCluster.Builder(admin).build(content.containers, modelContext, xml); buildIndexingClusters(content, modelContext, (ApplicationConfigProducerRoot)modelContext.getParentProducer()); } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/StorageGroup.java b/config-model/src/main/java/com/yahoo/vespa/model/content/StorageGroup.java index 2b23939d8ed..8e065b7d73d 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/content/StorageGroup.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/content/StorageGroup.java @@ -1,6 +1,7 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.model.content; +import com.yahoo.config.model.ConfigModelContext; import com.yahoo.config.provision.ClusterMembership; import com.yahoo.config.provision.ClusterSpec; import com.yahoo.config.application.api.DeployLogger; @@ -189,12 +190,12 @@ public class StorageGroup { private final ModelElement clusterElement; private final ContentCluster owner; - private final DeployLogger deployLogger; + private final ConfigModelContext context; - public Builder(ModelElement clusterElement, ContentCluster owner, DeployLogger deployLogger) { + public Builder(ModelElement clusterElement, ContentCluster owner, ConfigModelContext context) { this.clusterElement = clusterElement; this.owner = owner; - this.deployLogger = deployLogger; + this.context = context; } public StorageGroup buildRootGroup() { @@ -404,13 +405,13 @@ public class StorageGroup { Optional<NodesSpecification> nodeRequirement; if (nodesElement.isPresent() && nodesElement.get().getStringAttribute("count") != null ) // request these nodes - nodeRequirement = Optional.of(NodesSpecification.from(nodesElement.get())); + nodeRequirement = Optional.of(NodesSpecification.from(nodesElement.get(), context.getDeployState().getWantedNodeVespaVersion())); else if (! nodesElement.isPresent() && subGroups.isEmpty() && owner.getRoot().getDeployState().isHosted()) // request one node - nodeRequirement = Optional.of(NodesSpecification.nonDedicated(1)); + nodeRequirement = Optional.of(NodesSpecification.nonDedicated(1, context.getDeployState().getWantedNodeVespaVersion())); else // Nodes or groups explicitly listed, and/opr not hosted - resolve in GroupBuilder nodeRequirement = Optional.empty(); - return new GroupBuilder(group, subGroups, explicitNodes, nodeRequirement, deployLogger); + return new GroupBuilder(group, subGroups, explicitNodes, nodeRequirement, context.getDeployLogger()); } private Optional<String> childAsString(Optional<ModelElement> element, String childTagName) { diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/ContentCluster.java b/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/ContentCluster.java index bb1d8d37d60..ca8af6ce18d 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/ContentCluster.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/content/cluster/ContentCluster.java @@ -3,6 +3,8 @@ package com.yahoo.vespa.model.content.cluster; import com.google.common.base.Preconditions; import com.google.common.collect.Sets; +import com.yahoo.config.model.ConfigModelContext; +import com.yahoo.config.model.api.ModelContext; import com.yahoo.config.model.producer.AbstractConfigProducerRoot; import com.yahoo.config.provision.ClusterSpec; import com.yahoo.config.application.api.DeployLogger; @@ -88,35 +90,32 @@ public class ContentCluster extends AbstractConfigProducer implements StorDistri /** The admin model of this system or null if none (which only happens in tests) */ private final Admin admin; - private final DeployLogger deployLogger; - public Builder(Admin admin, DeployLogger deployLogger) { + public Builder(Admin admin) { this.admin = admin; - this.deployLogger = deployLogger; } - public ContentCluster build(Collection<ContainerModel> containers, - AbstractConfigProducer ancestor, Element w3cContentElement) { + public ContentCluster build(Collection<ContainerModel> containers, ConfigModelContext context, Element w3cContentElement) { ModelElement contentElement = new ModelElement(w3cContentElement); ModelElement documentsElement = contentElement.getChild("documents"); Map<String, NewDocumentType> documentDefinitions = - new SearchDefinitionBuilder().build(ancestor.getRoot().getDeployState().getDocumentModel().getDocumentManager(), documentsElement); + new SearchDefinitionBuilder().build(context.getParentProducer().getRoot().getDeployState().getDocumentModel().getDocumentManager(), documentsElement); String routingSelection = new DocumentSelectionBuilder().build(documentsElement); Redundancy redundancy = new RedundancyBuilder().build(contentElement); Set<NewDocumentType> globallyDistributedDocuments = new GlobalDistributionBuilder(documentDefinitions).build(documentsElement); - ContentCluster c = new ContentCluster(ancestor, getClusterName(contentElement), documentDefinitions, + ContentCluster c = new ContentCluster(context.getParentProducer(), getClusterName(contentElement), documentDefinitions, globallyDistributedDocuments, routingSelection, redundancy, - ancestor.getRoot().getDeployState().getProperties().zone()); + context.getParentProducer().getRoot().getDeployState().getProperties().zone()); c.clusterControllerConfig = new ClusterControllerConfig.Builder(getClusterName(contentElement), contentElement).build(c, contentElement.getXml()); c.search = new ContentSearchCluster.Builder(documentDefinitions, globallyDistributedDocuments).build(c, contentElement.getXml()); c.persistenceFactory = new EngineFactoryBuilder().build(contentElement, c); c.storageNodes = new StorageCluster.Builder().build(c, w3cContentElement); c.distributorNodes = new DistributorCluster.Builder(c).build(c, w3cContentElement); - c.rootGroup = new StorageGroup.Builder(contentElement, c, deployLogger).buildRootGroup(); + c.rootGroup = new StorageGroup.Builder(contentElement, c, context).buildRootGroup(); validateThatGroupSiblingsAreUnique(c.clusterName, c.rootGroup); redundancy.setExplicitGroups(c.getRootGroup().getNumberOfLeafGroups()); c.search.handleRedundancy(redundancy); @@ -144,10 +143,9 @@ public class ContentCluster extends AbstractConfigProducer implements StorDistri setupTuning(c, tuning); } - AbstractConfigProducerRoot root = ancestor.getRoot(); - if (root == null) return c; + if (context.getParentProducer().getRoot() == null) return c; - addClusterControllers(containers, root, c.rootGroup, contentElement, c.clusterName, c); + addClusterControllers(containers, context, c.rootGroup, contentElement, c.clusterName, c); return c; } @@ -263,7 +261,7 @@ public class ContentCluster extends AbstractConfigProducer implements StorDistri } } - private void addClusterControllers(Collection<ContainerModel> containers, AbstractConfigProducerRoot root, + private void addClusterControllers(Collection<ContainerModel> containers, ConfigModelContext context, StorageGroup rootGroup, ModelElement contentElement, String contentClusterName, ContentCluster contentCluster) { if (admin == null) return; // only in tests @@ -271,7 +269,7 @@ public class ContentCluster extends AbstractConfigProducer implements StorDistri ContainerCluster clusterControllers; - ContentCluster overlappingCluster = findOverlappingCluster(root, contentCluster); + ContentCluster overlappingCluster = findOverlappingCluster(context.getParentProducer().getRoot(), contentCluster); if (overlappingCluster != null && overlappingCluster.getClusterControllers() != null) { // Borrow the cluster controllers of the other cluster in this case. // This condition only obtains on non-hosted systems with a shared config server, @@ -281,9 +279,10 @@ public class ContentCluster extends AbstractConfigProducer implements StorDistri else if (admin.multitenant()) { String clusterName = contentClusterName + "-controllers"; NodesSpecification nodesSpecification = - NodesSpecification.optionalDedicatedFromParent(contentElement.getChild("controllers")).orElse(NodesSpecification.nonDedicated(3)); + NodesSpecification.optionalDedicatedFromParent(contentElement.getChild("controllers"), context.getDeployState().getWantedNodeVespaVersion()) + .orElse(NodesSpecification.nonDedicated(3, context.getDeployState().getWantedNodeVespaVersion())); Collection<HostResource> hosts = nodesSpecification.isDedicated() ? - getControllerHosts(nodesSpecification, admin, clusterName) : + getControllerHosts(nodesSpecification, admin, clusterName, context) : drawControllerHosts(nodesSpecification.count(), rootGroup, containers); clusterControllers = createClusterControllers(new ClusterControllerCluster(contentCluster, "standalone"), hosts, clusterName, true); @@ -319,8 +318,8 @@ public class ContentCluster extends AbstractConfigProducer implements StorDistri return ! Sets.intersection(c1Hosts, c2Hosts).isEmpty(); } - private Collection<HostResource> getControllerHosts(NodesSpecification nodesSpecification, Admin admin, String clusterName) { - return nodesSpecification.provision(admin.getHostSystem(), ClusterSpec.Type.admin, ClusterSpec.Id.from(clusterName), deployLogger).keySet(); + private Collection<HostResource> getControllerHosts(NodesSpecification nodesSpecification, Admin admin, String clusterName, ConfigModelContext context) { + return nodesSpecification.provision(admin.getHostSystem(), ClusterSpec.Type.admin, ClusterSpec.Id.from(clusterName), context.getDeployLogger()).keySet(); } private List<HostResource> drawControllerHosts(int count, StorageGroup rootGroup, Collection<ContainerModel> containers) { diff --git a/config-model/src/test/java/com/yahoo/config/model/ApplicationDeployTest.java b/config-model/src/test/java/com/yahoo/config/model/ApplicationDeployTest.java index b531fc515ed..9c07c7fc73e 100644 --- a/config-model/src/test/java/com/yahoo/config/model/ApplicationDeployTest.java +++ b/config-model/src/test/java/com/yahoo/config/model/ApplicationDeployTest.java @@ -2,6 +2,7 @@ package com.yahoo.config.model; import com.google.common.io.Files; +import com.yahoo.component.Version; import com.yahoo.config.ConfigInstance; import com.yahoo.config.application.api.ApplicationMetaData; import com.yahoo.config.application.api.UnparsedConfigDefinition; @@ -239,9 +240,9 @@ public class ApplicationDeployTest { public FilesApplicationPackage createAppPkg(String appPkg, boolean validateXml) throws IOException { final FilesApplicationPackage filesApplicationPackage = FilesApplicationPackage.fromFile(new File(appPkg)); if (validateXml) { - ApplicationPackageXmlFilesValidator validator = ApplicationPackageXmlFilesValidator.createTestXmlValidator(new File(appPkg)); + ApplicationPackageXmlFilesValidator validator = ApplicationPackageXmlFilesValidator.createTestXmlValidator(new File(appPkg), new Version(6)); validator.checkApplication(); - ApplicationPackageXmlFilesValidator.checkIncludedDirs(filesApplicationPackage); + ApplicationPackageXmlFilesValidator.checkIncludedDirs(filesApplicationPackage, new Version(6)); } return filesApplicationPackage; } diff --git a/config-model/src/test/java/com/yahoo/config/model/MapConfigModelRegistryTest.java b/config-model/src/test/java/com/yahoo/config/model/MapConfigModelRegistryTest.java index ea32feff8a9..8edde5e3d22 100644 --- a/config-model/src/test/java/com/yahoo/config/model/MapConfigModelRegistryTest.java +++ b/config-model/src/test/java/com/yahoo/config/model/MapConfigModelRegistryTest.java @@ -8,6 +8,7 @@ import org.w3c.dom.Element; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.List; import static org.junit.Assert.*; @@ -47,7 +48,7 @@ public class MapConfigModelRegistryTest { } @Override - public List<ConfigModelId> handlesElements() { return Arrays.asList(ConfigModelId.fromName("modelB")); } + public List<ConfigModelId> handlesElements() { return Collections.singletonList(ConfigModelId.fromName("modelB")); } @Override public void doBuild(ModelB model, Element spec, ConfigModelContext modelContext) { } } @@ -57,7 +58,7 @@ public class MapConfigModelRegistryTest { super(ModelB.class); } @Override - public List<ConfigModelId> handlesElements() { return Arrays.asList(ConfigModelId.fromName("modelB")); } + public List<ConfigModelId> handlesElements() { return Collections.singletonList(ConfigModelId.fromName("modelB")); } @Override public void doBuild(ModelB model, Element spec, ConfigModelContext modelContext) { } } @@ -73,7 +74,7 @@ public class MapConfigModelRegistryTest { super(ModelA.class); } @Override - public List<ConfigModelId> handlesElements() { return Arrays.asList(ConfigModelId.fromName("modelA")); } + public List<ConfigModelId> handlesElements() { return Collections.singletonList(ConfigModelId.fromName("modelA")); } @Override public void doBuild(ModelA model, Element spec, ConfigModelContext modelContext) { } diff --git a/config-model/src/test/java/com/yahoo/config/model/MockModelContext.java b/config-model/src/test/java/com/yahoo/config/model/MockModelContext.java index 84e8977a391..20a941eb690 100644 --- a/config-model/src/test/java/com/yahoo/config/model/MockModelContext.java +++ b/config-model/src/test/java/com/yahoo/config/model/MockModelContext.java @@ -1,6 +1,7 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.config.model; +import com.yahoo.component.Version; import com.yahoo.config.model.api.*; import com.yahoo.config.application.api.ApplicationPackage; import com.yahoo.config.model.application.provider.BaseDeployLogger; @@ -23,6 +24,7 @@ import java.util.Set; * @author hmusum */ public class MockModelContext implements ModelContext { + private final ApplicationPackage applicationPackage; public MockModelContext() { @@ -67,6 +69,12 @@ public class MockModelContext implements ModelContext { public FileRegistry getFileRegistry() { return new MockFileRegistry(); } + + @Override + public Version modelVespaVersion() { return new Version(6); } + + @Override + public Version wantedNodeVespaVersion() { return new Version(6); } @Override public Properties properties() { diff --git a/config-model/src/test/java/com/yahoo/config/model/application/provider/SchemaValidatorTest.java b/config-model/src/test/java/com/yahoo/config/model/application/provider/SchemaValidatorTest.java index ca4a2e70ee6..cbf7f4e9cd5 100644 --- a/config-model/src/test/java/com/yahoo/config/model/application/provider/SchemaValidatorTest.java +++ b/config-model/src/test/java/com/yahoo/config/model/application/provider/SchemaValidatorTest.java @@ -1,6 +1,7 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.config.model.application.provider; +import com.yahoo.component.Version; import org.junit.Test; import org.xml.sax.InputSource; import org.xml.sax.SAXException; @@ -64,6 +65,6 @@ public class SchemaValidatorTest { } private SchemaValidator createValidator() throws IOException { - return SchemaValidator.createTestValidatorServices(); + return SchemaValidator.createTestValidatorServices(new Version(6)); } } diff --git a/config-model/src/test/java/com/yahoo/searchdefinition/derived/AttributeListTestCase.java b/config-model/src/test/java/com/yahoo/searchdefinition/derived/AttributeListTestCase.java index 09899f4796f..97cbb7b1f37 100644 --- a/config-model/src/test/java/com/yahoo/searchdefinition/derived/AttributeListTestCase.java +++ b/config-model/src/test/java/com/yahoo/searchdefinition/derived/AttributeListTestCase.java @@ -20,9 +20,9 @@ import static org.junit.Assert.assertTrue; * @author bratseth */ public class AttributeListTestCase extends SearchDefinitionTestCase { + @Test public void testDeriving() throws IOException, ParseException { - // Test attribute importing Search search = SearchBuilder.buildFromFile("src/test/examples/simple.sd"); @@ -66,6 +66,6 @@ public class AttributeListTestCase extends SearchDefinitionTestCase { assertEquals(Attribute.CollectionType.SINGLE, attribute.getCollectionType()); assertTrue(!attributes.hasNext()); - } + } diff --git a/config-model/src/test/java/com/yahoo/searchdefinition/derived/SummaryTestCase.java b/config-model/src/test/java/com/yahoo/searchdefinition/derived/SummaryTestCase.java index 6220ab9f7d5..f2c1286ce34 100644 --- a/config-model/src/test/java/com/yahoo/searchdefinition/derived/SummaryTestCase.java +++ b/config-model/src/test/java/com/yahoo/searchdefinition/derived/SummaryTestCase.java @@ -21,13 +21,14 @@ import static org.junit.Assert.assertNull; * @author bratseth */ public class SummaryTestCase extends SearchDefinitionTestCase { + @Test public void testDeriving() throws IOException, ParseException { Search search = SearchBuilder.buildFromFile("src/test/examples/simple.sd"); SummaryClass summary=new SummaryClass(search,search.getSummary("default"), new BaseDeployLogger()); assertEquals("default",summary.getName()); - Iterator fields=summary.fieldIterator(); + Iterator<SummaryClassField> fields=summary.fieldIterator(); SummaryClassField field; diff --git a/config-model/src/test/java/com/yahoo/vespa/model/HostResourceTest.java b/config-model/src/test/java/com/yahoo/vespa/model/HostResourceTest.java index 16c63bc5251..cc7a38a828d 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/HostResourceTest.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/HostResourceTest.java @@ -1,6 +1,7 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.model; +import com.yahoo.component.Version; import com.yahoo.config.model.test.MockRoot; import com.yahoo.config.provision.ClusterMembership; import com.yahoo.config.provision.ClusterSpec; @@ -143,7 +144,7 @@ public class HostResourceTest { } private static ClusterSpec clusterSpec(ClusterSpec.Type type, String id) { - return ClusterSpec.from(type, ClusterSpec.Id.from(id), ClusterSpec.Group.from(0), Optional.empty()); + return ClusterSpec.from(type, ClusterSpec.Id.from(id), ClusterSpec.Group.from(0), Version.fromString("6.42")); } private HostResource mockHostResource() { diff --git a/config-model/src/test/java/com/yahoo/vespa/model/VespaModelFactoryTest.java b/config-model/src/test/java/com/yahoo/vespa/model/VespaModelFactoryTest.java index 8671f44ad6a..c0040875ec3 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/VespaModelFactoryTest.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/VespaModelFactoryTest.java @@ -1,13 +1,29 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.model; +import com.yahoo.component.Version; import com.yahoo.config.application.api.ApplicationPackage; import com.yahoo.config.model.MockModelContext; import com.yahoo.config.model.NullConfigModelRegistry; -import com.yahoo.config.model.api.*; +import com.yahoo.config.model.api.ConfigServerSpec; +import com.yahoo.config.model.api.HostInfo; import com.yahoo.config.model.api.HostProvisioner; +import com.yahoo.config.model.api.Model; +import com.yahoo.config.model.api.ModelContext; +import com.yahoo.config.model.api.ModelCreateResult; +import com.yahoo.config.model.api.ServiceInfo; import com.yahoo.config.model.test.MockApplicationPackage; -import com.yahoo.config.provision.*; +import com.yahoo.config.provision.ApplicationId; +import com.yahoo.config.provision.ApplicationName; +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.InstanceName; +import com.yahoo.config.provision.ProvisionLogger; +import com.yahoo.config.provision.Rotation; +import com.yahoo.config.provision.TenantName; +import com.yahoo.config.provision.Zone; import org.junit.Before; import org.junit.Test; @@ -100,7 +116,7 @@ public class VespaModelFactoryTest { ClusterMembership.from(ClusterSpec.from(ClusterSpec.Type.admin, new ClusterSpec.Id(routingClusterName), ClusterSpec.Group.from(0), - Optional.empty()), + Version.fromString("6.42")), 0)); } @@ -111,7 +127,7 @@ public class VespaModelFactoryTest { ClusterMembership.from(ClusterSpec.from(ClusterSpec.Type.container, new ClusterSpec.Id(routingClusterName), ClusterSpec.Group.from(0), - Optional.empty()), + Version.fromString("6.42")), 0))); } }; diff --git a/config-model/src/test/java/com/yahoo/vespa/model/admin/ClusterControllerTestCase.java b/config-model/src/test/java/com/yahoo/vespa/model/admin/ClusterControllerTestCase.java index 200e51ef924..d8116d01294 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/admin/ClusterControllerTestCase.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/admin/ClusterControllerTestCase.java @@ -5,6 +5,7 @@ import com.google.common.base.Function; import com.google.common.collect.Collections2; import com.yahoo.cloud.config.ZookeeperServerConfig; import com.yahoo.cloud.config.ZookeepersConfig; +import com.yahoo.component.Version; import com.yahoo.config.model.application.provider.SimpleApplicationValidator; import com.yahoo.config.model.test.TestDriver; import com.yahoo.config.model.test.TestRoot; @@ -434,7 +435,7 @@ public class ClusterControllerTestCase extends DomBuilderTest { .withServices(servicesXml) .withSearchDefinitions(sds) .build()); - SimpleApplicationValidator.checkServices(new StringReader(servicesXml)); + SimpleApplicationValidator.checkServices(new StringReader(servicesXml), new Version(6)); return model; } } diff --git a/config-model/src/test/java/com/yahoo/vespa/model/content/utils/ContentClusterUtils.java b/config-model/src/test/java/com/yahoo/vespa/model/content/utils/ContentClusterUtils.java index 8a3d241a79b..595013c506e 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/content/utils/ContentClusterUtils.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/content/utils/ContentClusterUtils.java @@ -3,6 +3,7 @@ package com.yahoo.vespa.model.content.utils; import com.yahoo.config.application.api.ApplicationPackage; import com.yahoo.config.application.api.DeployLogger; +import com.yahoo.config.model.ConfigModelContext; import com.yahoo.config.model.api.HostProvisioner; import com.yahoo.config.model.application.provider.BaseDeployLogger; import com.yahoo.config.model.deploy.DeployState; @@ -23,6 +24,7 @@ import java.util.Optional; /** * For testing purposes only. + * * @author geirst */ public class ContentClusterUtils { @@ -51,8 +53,9 @@ public class ContentClusterUtils { public static ContentCluster createCluster(String clusterXml, MockRoot root) throws Exception { Document doc = XML.getDocument(clusterXml); Admin admin = new Admin(root, new Yamas("vespa", 60), new Metrics(), Collections.emptyMap(), false); - DeployLogger deployLogger = new BaseDeployLogger(); - return new ContentCluster.Builder(admin, deployLogger).build(Collections.emptyList(), root, doc.getDocumentElement()); + ConfigModelContext context = ConfigModelContext.create(null, DeployState.createTestState(), null, root, null); + + return new ContentCluster.Builder(admin).build(Collections.emptyList(), context, doc.getDocumentElement()); } public static ContentCluster createCluster(String clusterXml, List<String> searchDefinitions) throws Exception { diff --git a/config-model/src/test/java/com/yahoo/vespa/model/test/utils/VespaModelCreatorWithFilePkg.java b/config-model/src/test/java/com/yahoo/vespa/model/test/utils/VespaModelCreatorWithFilePkg.java index 14216733d2a..77825b3f370 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/test/utils/VespaModelCreatorWithFilePkg.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/test/utils/VespaModelCreatorWithFilePkg.java @@ -1,6 +1,7 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.model.test.utils; +import com.yahoo.component.Version; import com.yahoo.config.model.ConfigModelRegistry; import com.yahoo.config.model.NullConfigModelRegistry; import com.yahoo.config.model.application.provider.*; @@ -44,8 +45,8 @@ public class VespaModelCreatorWithFilePkg { } public void validate() throws IOException { - ApplicationPackageXmlFilesValidator.createTestXmlValidator(applicationPkg.getAppDir()).checkApplication(); - ApplicationPackageXmlFilesValidator.checkIncludedDirs(applicationPkg); + ApplicationPackageXmlFilesValidator.createTestXmlValidator(applicationPkg.getAppDir(), new Version(6)).checkApplication(); + ApplicationPackageXmlFilesValidator.checkIncludedDirs(applicationPkg, new Version(6)); } public VespaModel create(boolean validateApplicationWithSchema) { diff --git a/config-model/src/test/java/com/yahoo/vespa/model/test/utils/VespaModelCreatorWithMockPkg.java b/config-model/src/test/java/com/yahoo/vespa/model/test/utils/VespaModelCreatorWithMockPkg.java index 2f83d3bc394..6d5471f649e 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/test/utils/VespaModelCreatorWithMockPkg.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/test/utils/VespaModelCreatorWithMockPkg.java @@ -1,6 +1,7 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.model.test.utils; +import com.yahoo.component.Version; import com.yahoo.config.application.api.ApplicationPackage; import com.yahoo.config.model.ConfigModelRegistry; import com.yahoo.config.model.NullConfigModelRegistry; @@ -53,15 +54,16 @@ public class VespaModelCreatorWithMockPkg { try { this.deployState = deployState; VespaModel model = new VespaModel(configModelRegistry, deployState); + Version vespaVersion = new Version(6); if (validate) { try { if (appPkg.getHosts() != null) { - SchemaValidator.createTestValidatorHosts().validate(appPkg.getHosts()); + SchemaValidator.createTestValidatorHosts(vespaVersion).validate(appPkg.getHosts()); } if (appPkg.getDeployment().isPresent()) { - SchemaValidator.createTestValidatorDeployment().validate(appPkg.getDeployment().get()); + SchemaValidator.createTestValidatorDeployment(vespaVersion).validate(appPkg.getDeployment().get()); } - SchemaValidator.createTestValidatorServices().validate(appPkg.getServices()); + SchemaValidator.createTestValidatorServices(vespaVersion).validate(appPkg.getServices()); } catch (Exception e) { System.err.println(e.getClass()); throw e instanceof RuntimeException ? (RuntimeException) e : new RuntimeException(e); diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/ClusterMembership.java b/config-provisioning/src/main/java/com/yahoo/config/provision/ClusterMembership.java index ff7ff0b4971..b78c4bb9f56 100644 --- a/config-provisioning/src/main/java/com/yahoo/config/provision/ClusterMembership.java +++ b/config-provisioning/src/main/java/com/yahoo/config/provision/ClusterMembership.java @@ -2,6 +2,7 @@ package com.yahoo.config.provision; import com.yahoo.component.Version; +import com.yahoo.component.Vtag; import java.util.Optional; @@ -20,7 +21,7 @@ public class ClusterMembership { protected ClusterMembership() {} - private ClusterMembership(String stringValue, Optional<Version> vespaVersion) { + private ClusterMembership(String stringValue, Version vespaVersion) { String restValue; if (stringValue.endsWith("/retired")) { retired = true; @@ -51,14 +52,14 @@ public class ClusterMembership { this.stringValue = toStringValue(); } - private void initWithoutGroup(String[] components, Optional<Version> vespaVersion) { - this.cluster = ClusterSpec.requestVersion(ClusterSpec.Type.valueOf(components[0]), - ClusterSpec.Id.from(components[1]), - vespaVersion); + private void initWithoutGroup(String[] components, Version vespaVersion) { + this.cluster = ClusterSpec.request(ClusterSpec.Type.valueOf(components[0]), + ClusterSpec.Id.from(components[1]), + vespaVersion); this.index = Integer.parseInt(components[2]); } - private void initWithGroup(String[] components, Optional<Version> vespaVersion) { + private void initWithGroup(String[] components, Version vespaVersion) { this.cluster = ClusterSpec.from(ClusterSpec.Type.valueOf(components[0]), ClusterSpec.Id.from(components[1]), ClusterSpec.Group.from(Integer.valueOf(components[2])), vespaVersion); this.index = Integer.parseInt(components[3]); @@ -115,10 +116,16 @@ public class ClusterMembership { @Deprecated // TODO: April 2017 - Remove this when no version older than 6.92 is in production public static ClusterMembership from(String stringValue, Optional<String> dockerImage) { - return fromVersion(stringValue, dockerImage.map(DockerImage::new).map(DockerImage::tagAsVersion)); + return from(stringValue, dockerImage.map(DockerImage::new).map(DockerImage::tagAsVersion).orElse(Vtag.currentVersion)); } + @Deprecated + // TODO: April 2017 - Remove this when no version older than 6.97 is in production public static ClusterMembership fromVersion(String stringValue, Optional<Version> vespaVersion) { + return new ClusterMembership(stringValue, vespaVersion.orElse(Vtag.currentVersion)); + } + + public static ClusterMembership from(String stringValue, Version vespaVersion) { return new ClusterMembership(stringValue, vespaVersion); } diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/ClusterSpec.java b/config-provisioning/src/main/java/com/yahoo/config/provision/ClusterSpec.java index 25c83d288eb..6a79f2f06ed 100644 --- a/config-provisioning/src/main/java/com/yahoo/config/provision/ClusterSpec.java +++ b/config-provisioning/src/main/java/com/yahoo/config/provision/ClusterSpec.java @@ -2,6 +2,8 @@ package com.yahoo.config.provision; import com.yahoo.component.Version; +import com.yahoo.component.Vtag; + import java.util.Objects; import java.util.Optional; @@ -19,9 +21,9 @@ public final class ClusterSpec { /** The group id of these hosts, or empty if this is represents a request for hosts */ private final Optional<Group> groupId; - private final Optional<Version> vespaVersion; + private final Version vespaVersion; - private ClusterSpec(Type type, Id id, Optional<Group> groupId, Optional<Version> vespaVersion) { + private ClusterSpec(Type type, Id id, Optional<Group> groupId, Version vespaVersion) { this.type = type; this.id = id; this.groupId = groupId; @@ -34,10 +36,10 @@ public final class ClusterSpec { /** Returns the cluster id */ public Id id() { return id; } - public Optional<Version> vespaVersion() { return vespaVersion; } + public Version vespaVersion() { return vespaVersion; } - public Optional<String> dockerImage() { - return vespaVersion.map(DockerImage.defaultImage::withTag).map(DockerImage::toString); + public String dockerImage() { + return DockerImage.defaultImage.withTag(vespaVersion).toString(); } /** Returns the group within the cluster this specifies, or empty to specify the whole cluster */ @@ -47,18 +49,28 @@ public final class ClusterSpec { /** Create a specification <b>requesting</b> a cluster with these attributes */ @Deprecated - // TODO: April 2017 - Remove this we no longer have old config-models using it + // TODO: April 2017 - Remove this when no version older than 6.94 is used anywhere public static ClusterSpec request(Type type, Id id, Optional<String> dockerImage) { return requestVersion(type, id, dockerImage.map(DockerImage::new).map(DockerImage::tagAsVersion)); } /** Create a specification <b>requesting</b> a cluster with these attributes */ + // TODO: April 2017 - Remove this when no version older than 6.97 is used anywhere public static ClusterSpec requestVersion(Type type, Id id, Optional<Version> vespaVersion) { + return new ClusterSpec(type, id, Optional.empty(), vespaVersion.orElse(Vtag.currentVersion)); + } + + public static ClusterSpec request(Type type, Id id, Version vespaVersion) { return new ClusterSpec(type, id, Optional.empty(), vespaVersion); } /** Create a specification <b>specifying</b> an existing cluster group having these attributes */ + // TODO: April 2017 - Remove this when no version older than 6.97 is used anywhere public static ClusterSpec from(Type type, Id id, Group groupId, Optional<Version> vespaVersion) { + return new ClusterSpec(type, id, Optional.of(groupId), vespaVersion.orElse(Vtag.currentVersion)); + } + + public static ClusterSpec from(Type type, Id id, Group groupId, Version vespaVersion) { return new ClusterSpec(type, id, Optional.of(groupId), vespaVersion); } @@ -66,7 +78,7 @@ public final class ClusterSpec { public String toString() { return String.join(" ", type.toString(), id.toString(), groupId.map(Group::toString).orElse(""), - vespaVersion.orElse(Version.emptyVersion).toString()); + vespaVersion.toString()); } @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 c5ccb7d2f58..d817dd4834c 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 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.config.provision; +import com.yahoo.component.Vtag; import com.yahoo.slime.ArrayTraverser; import com.yahoo.slime.Cursor; import com.yahoo.slime.Inspector; @@ -8,11 +9,13 @@ import com.yahoo.slime.Slime; import com.yahoo.vespa.config.SlimeUtils; import java.io.IOException; -import java.util.*; -import java.util.logging.Logger; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.Optional; +import java.util.Set; /** - * Information about provisioned hosts, and (de)serialization (from)to JSON. + * Information about hosts provisioned for an application, and (de)serialization of this information to/from JSON. * * @author lulf * @since 5.12 @@ -24,6 +27,7 @@ public class ProvisionInfo { private static final String hostSpecHostName = "hostName"; private static final String hostSpecMembership = "membership"; private static final String hostSpecFlavor = "flavor"; + private static final String hostSpecVespaVersion = "vespaVersion"; private static final String dockerImage = "dockerImage"; private final Set<HostSpec> hosts = new LinkedHashSet<>(); @@ -48,8 +52,7 @@ public class ProvisionInfo { cursor.setString(hostSpecHostName, host.hostname()); if (host.membership().isPresent()) { cursor.setString(hostSpecMembership, host.membership().get().stringValue()); - if (host.membership().get().cluster().dockerImage().isPresent()) - cursor.setString(dockerImage, host.membership().get().cluster().dockerImage().get()); + cursor.setString(hostSpecVespaVersion, host.membership().get().cluster().vespaVersion().toString()); } if (host.flavor().isPresent()) cursor.setString(hostSpecFlavor, host.flavor().get().name()); @@ -61,17 +64,17 @@ public class ProvisionInfo { private static ProvisionInfo fromSlime(Inspector inspector, Optional<NodeFlavors> nodeFlavors) { Inspector array = inspector.field(mappingKey); - final Set<HostSpec> hosts = new LinkedHashSet<>(); + Set<HostSpec> hosts = new LinkedHashSet<>(); array.traverse(new ArrayTraverser() { @Override public void entry(int i, Inspector inspector) { - hosts.add(createHostSpec(inspector.field(hostSpecKey), nodeFlavors)); + hosts.add(deserializeHostSpec(inspector.field(hostSpecKey), nodeFlavors)); } }); return new ProvisionInfo(hosts); } - private static HostSpec createHostSpec(Inspector object, Optional<NodeFlavors> nodeFlavors) { + private static HostSpec deserializeHostSpec(Inspector object, Optional<NodeFlavors> nodeFlavors) { Optional<ClusterMembership> membership = object.field(hostSpecMembership).valid() ? Optional.of(readMembership(object)) : Optional.empty(); Optional<Flavor> flavor = @@ -81,8 +84,11 @@ public class ProvisionInfo { } private static ClusterMembership readMembership(Inspector object) { + // TODO: When no version older than 6.97 is present anywhere, remove the possibility of the version field missing (and hence also remove reading of dockerImage) return ClusterMembership.from(object.field(hostSpecMembership).asString(), - object.field(dockerImage).valid() ? Optional.of(object.field(dockerImage).asString()) : Optional.empty()); + object.field(hostSpecVespaVersion).valid() ? + com.yahoo.component.Version.fromString(object.field(hostSpecVespaVersion).asString()) : + ( object.field(dockerImage).valid() ? new DockerImage(object.field(dockerImage).asString()).tagAsVersion() : Vtag.currentVersion)); } private static Optional<Flavor> readFlavor(Inspector object, Optional<NodeFlavors> nodeFlavors) { diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/Version.java b/config-provisioning/src/main/java/com/yahoo/config/provision/Version.java index 6dcb5fe207e..6792e31afd9 100644 --- a/config-provisioning/src/main/java/com/yahoo/config/provision/Version.java +++ b/config-provisioning/src/main/java/com/yahoo/config/provision/Version.java @@ -15,6 +15,7 @@ package com.yahoo.config.provision; * Loosely based on component/Version.java * {@link Version} objects are immutable. */ +// TODO: Replace usage of this by com.yahoo.component.Version public final class Version implements Comparable<Version> { private final int major; diff --git a/config-provisioning/src/test/java/com/yahoo/config/provision/ClusterMembershipTest.java b/config-provisioning/src/test/java/com/yahoo/config/provision/ClusterMembershipTest.java index 56da6dbcaa7..90a727a221f 100644 --- a/config-provisioning/src/test/java/com/yahoo/config/provision/ClusterMembershipTest.java +++ b/config-provisioning/src/test/java/com/yahoo/config/provision/ClusterMembershipTest.java @@ -1,6 +1,8 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.config.provision; +import com.yahoo.component.*; +import com.yahoo.component.Version; import org.junit.Test; import java.util.Optional; @@ -16,59 +18,59 @@ public class ClusterMembershipTest { @Test public void testContainerServiceInstance() { - ClusterSpec cluster = ClusterSpec.requestVersion(ClusterSpec.Type.container, ClusterSpec.Id.from("id1"), Optional.empty()); + ClusterSpec cluster = ClusterSpec.request(ClusterSpec.Type.container, ClusterSpec.Id.from("id1"), Version.fromString("6.42")); assertContainerService(ClusterMembership.from(cluster, 3)); } @Test public void testContainerServiceInstanceFromString() { - assertContainerService(ClusterMembership.fromVersion("container/id1/3", Optional.empty())); + assertContainerService(ClusterMembership.from("container/id1/3", Vtag.currentVersion)); } @Test public void testServiceInstance() { - ClusterSpec cluster = ClusterSpec.requestVersion(ClusterSpec.Type.content, ClusterSpec.Id.from("id1"), Optional.empty()); + ClusterSpec cluster = ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("id1"), Version.fromString("6.42")); assertContentService(ClusterMembership.from(cluster, 37)); } @Test public void testServiceInstanceFromString() { - assertContentService(ClusterMembership.fromVersion("content/id1/37", Optional.empty())); + assertContentService(ClusterMembership.from("content/id1/37", Vtag.currentVersion)); } @Test public void testServiceInstanceWithGroup() { ClusterSpec cluster = ClusterSpec.from(ClusterSpec.Type.content, ClusterSpec.Id.from("id1"), - ClusterSpec.Group.from(4), Optional.empty()); + ClusterSpec.Group.from(4), Version.fromString("6.42")); assertContentServiceWithGroup(ClusterMembership.from(cluster, 37)); } @Test public void testServiceInstanceWithGroupFromString() { - assertContentServiceWithGroup(ClusterMembership.from("content/id1/4/37", Optional.empty())); + assertContentServiceWithGroup(ClusterMembership.from("content/id1/4/37", Vtag.currentVersion)); } @Test public void testServiceInstanceWithRetire() { - ClusterSpec cluster = ClusterSpec.requestVersion(ClusterSpec.Type.content, ClusterSpec.Id.from("id1"), Optional.empty()); + ClusterSpec cluster = ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("id1"), Version.fromString("6.42")); assertContentServiceWithRetire(ClusterMembership.retiredFrom(cluster, 37)); } @Test public void testServiceInstanceWithRetireFromString() { - assertContentServiceWithRetire(ClusterMembership.from("content/id1/37/retired", Optional.empty())); + assertContentServiceWithRetire(ClusterMembership.from("content/id1/37/retired", Vtag.currentVersion)); } @Test public void testServiceInstanceWithGroupAndRetire() { ClusterSpec cluster = ClusterSpec.from(ClusterSpec.Type.content, ClusterSpec.Id.from("id1"), - ClusterSpec.Group.from(4), Optional.empty()); + ClusterSpec.Group.from(4), Version.fromString("6.42")); assertContentServiceWithGroupAndRetire(ClusterMembership.retiredFrom(cluster, 37)); } @Test public void testServiceInstanceWithGroupAndRetireFromString() { - assertContentServiceWithGroupAndRetire(ClusterMembership.from("content/id1/4/37/retired", Optional.empty())); + assertContentServiceWithGroupAndRetire(ClusterMembership.from("content/id1/4/37/retired", Vtag.currentVersion)); } private void assertContainerService(ClusterMembership instance) { diff --git a/config-provisioning/src/test/java/com/yahoo/config/provision/HostFilterTest.java b/config-provisioning/src/test/java/com/yahoo/config/provision/HostFilterTest.java index b16e2d76ca8..23fe00d0ec5 100644 --- a/config-provisioning/src/test/java/com/yahoo/config/provision/HostFilterTest.java +++ b/config-provisioning/src/test/java/com/yahoo/config/provision/HostFilterTest.java @@ -1,6 +1,7 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.config.provision; +import com.yahoo.component.Vtag; import org.junit.Test; import java.util.Arrays; @@ -70,7 +71,7 @@ public class HostFilterTest { } private Optional<ClusterMembership> membership(String membershipString) { - return Optional.of(ClusterMembership.from(membershipString, Optional.empty())); + return Optional.of(ClusterMembership.from(membershipString, Vtag.currentVersion)); } } 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 a6ccdb8536f..d54b76c1b65 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 @@ -20,7 +20,7 @@ public class ProvisionInfoTest { private final HostSpec h1 = new HostSpec("host1", Optional.empty()); private final HostSpec h2 = new HostSpec("host2", Optional.empty()); - private final HostSpec h3 = new HostSpec("host3", Optional.of(ClusterMembership.from("container/test/0", Optional.empty()))); + private final HostSpec h3 = new HostSpec("host3", Optional.of(ClusterMembership.from("container/test/0", com.yahoo.component.Version.fromString("6.73.1")))); private final HostSpec h4 = new HostSpec("host4", Optional.of(ClusterMembership.from("container/test/1", Optional.of("docker-registry.ops.yahoo.com:4443/vespa/ci:6.42.1")))); @Test @@ -57,7 +57,8 @@ public class ProvisionInfoTest { assertTrue(serializedInfo.getHosts().contains(h4)); assertTrue(!getHost(h1.hostname(), serializedInfo.getHosts()).membership().isPresent()); assertEquals("container/test/0", getHost(h3.hostname(), serializedInfo.getHosts()).membership().get().stringValue()); - assertEquals("docker-registry.ops.yahoo.com:4443/vespa/ci:6.42.1", getHost(h4.hostname(), serializedInfo.getHosts()).membership().get().cluster().dockerImage().get()); + assertEquals(h3.membership().get().cluster().vespaVersion(), getHost(h3.hostname(), serializedInfo.getHosts()).membership().get().cluster().vespaVersion()); + assertEquals("docker-registry.ops.yahoo.com:4443/vespa/ci:6.42.1", getHost(h4.hostname(), serializedInfo.getHosts()).membership().get().cluster().dockerImage()); } private HostSpec getHost(String hostname, Set<HostSpec> hosts) { diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/ServerCache.java b/configserver/src/main/java/com/yahoo/vespa/config/server/ServerCache.java index 59cb7b63114..6d2567f711a 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/ServerCache.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/ServerCache.java @@ -68,4 +68,5 @@ public class ServerCache { public int checkSumElems() { return md5Sums.size(); } + } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java index 7f26795a003..5fac9f61b4b 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/ModelContextImpl.java @@ -1,13 +1,13 @@ // Copyright 2016 Yahoo Inc. 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.*; import com.yahoo.config.application.api.ApplicationPackage; import com.yahoo.config.application.api.DeployLogger; import com.yahoo.config.application.api.FileRegistry; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.Rotation; -import com.yahoo.config.provision.Version; import com.yahoo.config.provision.Zone; import java.io.File; @@ -31,7 +31,18 @@ public class ModelContextImpl implements ModelContext { private final Optional<HostProvisioner> hostProvisioner; private final ModelContext.Properties properties; private final Optional<File> appDir; - Optional<Version> vespaVersion; + + /** The version of Vespa we are building a model for */ + private final Version modelVespaVersion; + + /** + * The Version of Vespa this model should specify that nodes should use. Note that this + * is separate from the version of this model, as upgrades are not immediate. + * We may build a config model of Vespa version "a" which specifies that nodes should + * use Vespa version "b". The "a" model will then be used by nodes who have not yet + * upgraded to version "b". + */ + private final Version wantedNodeVespaVersion; public ModelContextImpl(ApplicationPackage applicationPackage, Optional<Model> previousModel, @@ -42,7 +53,8 @@ public class ModelContextImpl implements ModelContext { Optional<HostProvisioner> hostProvisioner, ModelContext.Properties properties, Optional<File> appDir, - Optional<Version> vespaVersion) { + Version modelVespaVersion, + Version wantedNodeVespaVersion) { this.applicationPackage = applicationPackage; this.previousModel = previousModel; this.permanentApplicationPackage = permanentApplicationPackage; @@ -52,7 +64,8 @@ public class ModelContextImpl implements ModelContext { this.hostProvisioner = hostProvisioner; this.properties = properties; this.appDir = appDir; - this.vespaVersion = vespaVersion; + this.modelVespaVersion = modelVespaVersion; + this.wantedNodeVespaVersion = wantedNodeVespaVersion; } @Override @@ -101,7 +114,10 @@ public class ModelContextImpl implements ModelContext { } @Override - public Optional<Version> vespaVersion() { return vespaVersion; } + public Version modelVespaVersion() { return modelVespaVersion; } + + @Override + public Version wantedNodeVespaVersion() { return wantedNodeVespaVersion; } /** * @author lulf 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 3b15da0fbea..70c855f064c 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 @@ -72,10 +72,10 @@ public class ActivatedModelsBuilder extends ModelsBuilder<Application> { @Override protected Application buildModelVersion(ModelFactory modelFactory, ApplicationPackage applicationPackage, - ApplicationId applicationId) { - Version version = modelFactory.getVersion(); + ApplicationId applicationId, com.yahoo.component.Version wantedNodeVespaVersion) { log.log(LogLevel.DEBUG, String.format("Loading model version %s for session %s application %s", - version, appGeneration, applicationId)); + modelFactory.getVersion(), appGeneration, applicationId)); + ServerCache cache = zkClient.loadServerCache(); ModelContext modelContext = new ModelContextImpl( applicationPackage, Optional.<Model>empty(), @@ -86,10 +86,10 @@ public class ActivatedModelsBuilder extends ModelsBuilder<Application> { createHostProvisioner(getForVersionOrLatest(applicationPackage.getProvisionInfoMap(), modelFactory.getVersion())), createModelContextProperties(applicationId), Optional.empty(), - Optional.empty()); - ServerCache cache = zkClient.loadServerCache(); + new com.yahoo.component.Version(modelFactory.getVersion().toString()), + wantedNodeVespaVersion); MetricUpdater applicationMetricUpdater = metrics.getOrCreateMetricUpdater(Metrics.createDimensions(applicationId)); - return new Application(modelFactory.createModel(modelContext), cache, appGeneration, version, + return new Application(modelFactory.createModel(modelContext), cache, appGeneration, modelFactory.getVersion(), applicationMetricUpdater, applicationId); } 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 1b32d6bde22..f2b78e9e0dd 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 @@ -40,7 +40,8 @@ public abstract class ModelsBuilder<MODELRESULT extends ModelResult> { this.modelFactoryRegistry = modelFactoryRegistry; } - public List<MODELRESULT> buildModels(ApplicationId applicationId, ApplicationPackage applicationPackage) { + public List<MODELRESULT> buildModels(ApplicationId applicationId, + com.yahoo.component.Version wantedNodeVespaVersion, ApplicationPackage applicationPackage) { Set<Version> versions = modelFactoryRegistry.allVersions(); // If the application specifies a major, load models only for that @@ -60,7 +61,7 @@ public abstract class ModelsBuilder<MODELRESULT extends ModelResult> { for (int i = 0; i < majorVersions.size(); i++) { try { allApplicationModels.addAll(buildModelVersion(filterByMajorVersion(majorVersions.get(i), versions), - applicationId, applicationPackage)); + applicationId, wantedNodeVespaVersion, applicationPackage)); // skip old config models after we have found a major version which works if (allApplicationModels.size() > 0 && allApplicationModels.get(0).getModel().skipOldConfigModels()) @@ -82,10 +83,11 @@ public abstract class ModelsBuilder<MODELRESULT extends ModelResult> { } private List<MODELRESULT> buildModelVersion(Set<Version> versions, ApplicationId applicationId, + com.yahoo.component.Version wantedNodeVespaVersion, ApplicationPackage applicationPackage) { Version latest = findLatest(versions); // load latest application version - MODELRESULT latestApplicationVersion = buildModelVersion(modelFactoryRegistry.getFactory(latest), applicationPackage, applicationId); + MODELRESULT latestApplicationVersion = buildModelVersion(modelFactoryRegistry.getFactory(latest), applicationPackage, applicationId, wantedNodeVespaVersion); if (latestApplicationVersion.getModel().skipOldConfigModels()) { return Collections.singletonList(latestApplicationVersion); } @@ -94,7 +96,7 @@ public abstract class ModelsBuilder<MODELRESULT extends ModelResult> { allApplicationVersions.add(latestApplicationVersion); for (Version version : versions) { if (version.equals(latest)) continue; // already loaded - allApplicationVersions.add(buildModelVersion(modelFactoryRegistry.getFactory(version), applicationPackage, applicationId)); + allApplicationVersions.add(buildModelVersion(modelFactoryRegistry.getFactory(version), applicationPackage, applicationId, wantedNodeVespaVersion)); } return allApplicationVersions; } @@ -114,7 +116,8 @@ public abstract class ModelsBuilder<MODELRESULT extends ModelResult> { } protected abstract MODELRESULT buildModelVersion(ModelFactory modelFactory, ApplicationPackage applicationPackage, - ApplicationId applicationId); + ApplicationId applicationId, + com.yahoo.component.Version wantedNodeVespaVersion); protected ModelContext.Properties createModelContextProperties(ApplicationId applicationId, ConfigserverConfig configserverConfig, diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/PreparedModelsBuilder.java b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/PreparedModelsBuilder.java index cb2ffe1c2f9..c158f5ab03d 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/PreparedModelsBuilder.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/modelfactory/PreparedModelsBuilder.java @@ -1,6 +1,7 @@ // Copyright 2016 Yahoo Inc. 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.component.Vtag; import com.yahoo.config.application.api.ApplicationPackage; import com.yahoo.config.application.api.DeployLogger; import com.yahoo.config.model.api.ConfigChangeAction; @@ -75,17 +76,19 @@ public class PreparedModelsBuilder extends ModelsBuilder<PreparedModelsBuilder.P } @Override - protected PreparedModelResult buildModelVersion(ModelFactory modelFactory, ApplicationPackage applicationPackage, - ApplicationId applicationId) { - Version version = modelFactory.getVersion(); - log.log(LogLevel.DEBUG, "Start building model for Vespa version " + version); + protected PreparedModelResult buildModelVersion(ModelFactory modelFactory, + ApplicationPackage applicationPackage, + ApplicationId applicationId, + com.yahoo.component.Version wantedNodeVespaVersion) { + Version modelVersion = modelFactory.getVersion(); + log.log(LogLevel.DEBUG, "Start building model for Vespa version " + modelVersion); FileDistributionProvider fileDistributionProvider = fileDistributionFactory.createProvider( context.getServerDBSessionDir(), applicationId); Optional<HostProvisioner> hostProvisioner = createHostProvisionerAdapter(properties); Optional<Model> previousModel = currentActiveApplicationSet - .map(set -> set.getForVersionOrLatest(Optional.of(version)).getModel()); + .map(set -> set.getForVersionOrLatest(Optional.of(modelVersion)).getModel()); ModelContext modelContext = new ModelContextImpl( applicationPackage, previousModel, @@ -96,13 +99,14 @@ public class PreparedModelsBuilder extends ModelsBuilder<PreparedModelsBuilder.P hostProvisioner, properties, getAppDir(applicationPackage), - Optional.of(version)); + new com.yahoo.component.Version(modelVersion.toString()), + wantedNodeVespaVersion); - log.log(LogLevel.DEBUG, "Running createAndValidateModel for Vespa version " + version); + log.log(LogLevel.DEBUG, "Running createAndValidateModel for Vespa version " + modelVersion); ModelCreateResult result = modelFactory.createAndValidateModel(modelContext, params.ignoreValidationErrors()); validateModelHosts(context.getHostValidator(), applicationId, result.getModel()); - log.log(LogLevel.DEBUG, "Done building model for Vespa version " + version); - return new PreparedModelsBuilder.PreparedModelResult(version, result.getModel(), fileDistributionProvider, result.getConfigChangeActions()); + log.log(LogLevel.DEBUG, "Done building model for Vespa version " + modelVersion); + return new PreparedModelsBuilder.PreparedModelResult(modelVersion, result.getModel(), fileDistributionProvider, result.getConfigChangeActions()); } private Optional<File> getAppDir(ApplicationPackage applicationPackage) { 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 a68ce0441ab..fcd10a35f39 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 @@ -1,6 +1,7 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.config.server.session; +import com.yahoo.component.Version; import com.yahoo.config.application.api.ApplicationFile; import com.yahoo.config.application.api.ApplicationPackage; import com.yahoo.config.application.api.ApplicationMetaData; @@ -83,7 +84,7 @@ public class LocalSession extends Session implements Comparable<LocalSession> { private Transaction setActive() { Transaction transaction = createSetStatusTransaction(Status.ACTIVATE); - transaction.add(applicationRepo.createPutApplicationTransaction(zooKeeperClient.readApplicationId(getTenant()), getSessionId()).operations()); + transaction.add(applicationRepo.createPutApplicationTransaction(zooKeeperClient.readApplicationId(), getSessionId()).operations()); return transaction; } @@ -153,6 +154,10 @@ public class LocalSession extends Session implements Comparable<LocalSession> { zooKeeperClient.writeApplicationId(applicationId); } + public void setVespaVersion(Version version) { + zooKeeperClient.writeVespaVersion(version); + } + public enum Mode { READ, WRITE } @@ -161,9 +166,9 @@ public class LocalSession extends Session implements Comparable<LocalSession> { return applicationPackage.getMetaData(); } - public ApplicationId getApplicationId() { - return zooKeeperClient.readApplicationId(getTenant()); - } + public ApplicationId getApplicationId() { return zooKeeperClient.readApplicationId(); } + + public Version getVespaVersion() { return zooKeeperClient.readVespaVersion(); } public ProvisionInfo getProvisionInfo() { return zooKeeperClient.getProvisionInfo(); diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/PrepareParams.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/PrepareParams.java index 03a7a3915d3..3890001518a 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/PrepareParams.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/PrepareParams.java @@ -1,10 +1,10 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.config.server.session; +import com.yahoo.component.Version; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.Rotation; import com.yahoo.config.provision.TenantName; -import com.yahoo.config.provision.Version; import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.vespa.config.server.TimeoutBudget; import com.yahoo.vespa.config.server.http.SessionHandler; @@ -29,7 +29,6 @@ public final class PrepareParams { static final String DRY_RUN_PARAM_NAME = "dryRun"; static final String VESPA_VERSION_PARAM_NAME = "vespaVersion"; static final String ROTATIONS_PARAM_NAME = "rotations"; - static final String DOCKER_VESPA_IMAGE_VERSION_PARAM_NAME = "dockerVespaImageVersion"; private final ApplicationId applicationId; private final TimeoutBudget timeoutBudget; @@ -37,18 +36,15 @@ public final class PrepareParams { private final boolean dryRun; private final Optional<Version> vespaVersion; private final Set<Rotation> rotations; - private final Optional<Version> dockerVespaImageVersion; private PrepareParams(ApplicationId applicationId, TimeoutBudget timeoutBudget, boolean ignoreValidationErrors, - boolean dryRun, Optional<Version> vespaVersion, Set<Rotation> rotations, - Optional<Version> dockerVespaImageVersion) { + boolean dryRun, Optional<Version> vespaVersion, Set<Rotation> rotations) { this.timeoutBudget = timeoutBudget; this.applicationId = applicationId; this.ignoreValidationErrors = ignoreValidationErrors; this.dryRun = dryRun; this.vespaVersion = vespaVersion; this.rotations = rotations; - this.dockerVespaImageVersion = dockerVespaImageVersion; } public static class Builder { @@ -58,7 +54,6 @@ public final class PrepareParams { private TimeoutBudget timeoutBudget = new TimeoutBudget(Clock.systemUTC(), Duration.ofSeconds(30)); private Optional<Version> vespaVersion = Optional.empty(); private Set<Rotation> rotations; - private Optional<Version> dockerVespaImageVersion = Optional.empty(); public Builder() { } @@ -102,18 +97,9 @@ public final class PrepareParams { return this; } - public Builder dockerVespaImageVersion(String dockerVespaImageVersion) { - Optional<Version> version = Optional.empty(); - if (dockerVespaImageVersion != null && !dockerVespaImageVersion.isEmpty()) { - version = Optional.of(Version.fromString(dockerVespaImageVersion)); - } - this.dockerVespaImageVersion = version; - return this; - } - public PrepareParams build() { - return new PrepareParams(applicationId, timeoutBudget, ignoreValidationErrors, dryRun, - vespaVersion, rotations, dockerVespaImageVersion); + return new PrepareParams(applicationId, timeoutBudget, ignoreValidationErrors, dryRun, + vespaVersion, rotations); } } @@ -125,7 +111,6 @@ public final class PrepareParams { .applicationId(createApplicationId(request, tenant)) .vespaVersion(request.getProperty(VESPA_VERSION_PARAM_NAME)) .rotations(request.getProperty(ROTATIONS_PARAM_NAME)) - .dockerVespaImageVersion(request.getProperty(DOCKER_VESPA_IMAGE_VERSION_PARAM_NAME)) .build(); } @@ -153,6 +138,7 @@ public final class PrepareParams { return applicationId; } + /** Returns the Vespa version the nodes running the prepared system should have, or empty to use the system version */ public Optional<Version> vespaVersion() { return vespaVersion; } public Set<Rotation> rotations() { return rotations; } @@ -169,15 +155,4 @@ public final class PrepareParams { return timeoutBudget; } - public Optional<Version> getVespaVersion() { - return vespaVersion; - } - - public Set<Rotation> getRotations() { - return rotations; - } - - public Optional<Version> getDockerVespaImageVersion() { - return dockerVespaImageVersion; - } } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java index ca4fa21f804..72dc4cbb963 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/RemoteSession.java @@ -49,7 +49,8 @@ public class RemoteSession extends Session { } private ApplicationSet loadApplication() { - return ApplicationSet.fromList(applicationLoader.buildModels(zooKeeperClient.readApplicationId(getTenant()), + return ApplicationSet.fromList(applicationLoader.buildModels(zooKeeperClient.readApplicationId(), + zooKeeperClient.readVespaVersion(), zooKeeperClient.loadApplicationPackage())); } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionFactoryImpl.java b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionFactoryImpl.java index e7380708d47..729472051fd 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionFactoryImpl.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/session/SessionFactoryImpl.java @@ -119,13 +119,13 @@ public class SessionFactoryImpl implements SessionFactory, LocalSessionLoader { TimeoutBudget timeoutBudget) { File existingApp = getSessionAppDir(existingSession.getSessionId()); ApplicationMetaData metaData = FilesApplicationPackage.readMetaData(existingApp); - final ApplicationId existingSessionId = existingSession.getApplicationId(); + ApplicationId existingApplicationId = existingSession.getApplicationId(); - - final long liveApp = getLiveApp(existingSessionId); - logger.log(LogLevel.DEBUG, "Create from existing application id " + existingSessionId + ", live app for it is " + liveApp); + long liveApp = getLiveApp(existingApplicationId); + logger.log(LogLevel.DEBUG, "Create from existing application id " + existingApplicationId + ", live app for it is " + liveApp); LocalSession session = create(existingApp, metaData.getApplicationName(), liveApp, timeoutBudget); - session.setApplicationId(existingSessionId); + session.setApplicationId(existingApplicationId); + session.setVespaVersion(existingSession.getVespaVersion()); return session; } 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 d9f486a5604..cd10b031a93 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 @@ -3,6 +3,7 @@ package com.yahoo.vespa.config.server.session; import com.google.common.collect.ImmutableList; import com.yahoo.cloud.config.ConfigserverConfig; +import com.yahoo.component.Vtag; import com.yahoo.config.application.api.ApplicationPackage; import com.yahoo.config.application.api.DeployLogger; import com.yahoo.config.application.api.FileRegistry; @@ -91,7 +92,7 @@ public class SessionPreparer { try { prep.buildModels(); prep.makeResult(); - if (!params.isDryRun()) { + if ( ! params.isDryRun()) { prep.writeStateZK(); prep.writeRotZK(); prep.distribute(); @@ -112,6 +113,10 @@ public class SessionPreparer { final Optional<ApplicationSet> currentActiveApplicationSet; final Path tenantPath; final ApplicationId applicationId; + + /** The version of Vespa the application to be prepared specifies for its nodes */ + final com.yahoo.component.Version vespaVersion; + final Rotations rotations; final Set<Rotation> rotationsSet; final ModelContext.Properties properties; @@ -131,6 +136,7 @@ public class SessionPreparer { this.tenantPath = tenantPath; this.applicationId = params.getApplicationId(); + this.vespaVersion = params.vespaVersion().orElse(Vtag.currentVersion); this.rotations = new Rotations(curator, tenantPath); this.rotationsSet = getRotations(params.rotations()); this.properties = new ModelContextImpl.Properties(params.getApplicationId(), @@ -168,7 +174,7 @@ public class SessionPreparer { } void buildModels() { - this.modelResultList = preparedModelsBuilder.buildModels(applicationId, applicationPackage); + this.modelResultList = preparedModelsBuilder.buildModels(applicationId, vespaVersion, applicationPackage); checkTimeout("build models"); } @@ -179,8 +185,13 @@ public class SessionPreparer { void writeStateZK() { log.log(LogLevel.DEBUG, "Writing application package state to zookeeper"); - writeStateToZooKeeper(context.getSessionZooKeeperClient(), applicationPackage, params, logger, - prepareResult.getFileRegistries(), prepareResult.getProvisionInfos()); + writeStateToZooKeeper(context.getSessionZooKeeperClient(), + applicationPackage, + applicationId, + vespaVersion, + logger, + prepareResult.getFileRegistries(), + prepareResult.getProvisionInfos()); checkTimeout("write state to zookeeper"); } @@ -217,14 +228,16 @@ public class SessionPreparer { private void writeStateToZooKeeper(SessionZooKeeperClient zooKeeperClient, ApplicationPackage applicationPackage, - PrepareParams prepareParams, + ApplicationId applicationId, + com.yahoo.component.Version vespaVersion, DeployLogger deployLogger, Map<Version, FileRegistry> fileRegistryMap, Map<Version, ProvisionInfo> provisionInfoMap) { ZooKeeperDeployer zkDeployer = zooKeeperClient.createDeployer(deployLogger); try { zkDeployer.deploy(applicationPackage, fileRegistryMap, provisionInfoMap); - zooKeeperClient.writeApplicationId(prepareParams.getApplicationId()); + zooKeeperClient.writeApplicationId(applicationId); + zooKeeperClient.writeVespaVersion(vespaVersion); } catch (RuntimeException | IOException e) { zkDeployer.cleanup(); throw new RuntimeException("Error preparing session", e); 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 c29a00057a2..dd74270c817 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 @@ -1,6 +1,8 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.config.server.session; +import com.yahoo.component.Version; +import com.yahoo.component.Vtag; import com.yahoo.config.application.api.ApplicationPackage; import com.yahoo.config.application.api.DeployLogger; import com.yahoo.config.provision.NodeFlavors; @@ -36,6 +38,7 @@ public class SessionZooKeeperClient { private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(SessionZooKeeperClient.class.getName()); static final String APPLICATION_ID_PATH = "applicationId"; + static final String VERSION_PATH = "version"; static final String CREATE_TIME_PATH = "createTime"; private final Curator curator; private final ConfigCurator configCurator; @@ -146,38 +149,36 @@ public class SessionZooKeeperClient { return cacheLoader.loadCache(); } + private String applicationIdPath() { + return rootPath.append(APPLICATION_ID_PATH).getAbsolute(); + } + public void writeApplicationId(ApplicationId id) { - String path = getApplicationIdPath(); - try { - configCurator.putData(path, id.serializedForm()); - } catch (RuntimeException e) { - throw new RuntimeException("Unable to write application id '" + id + "' to '" + path + "'", e); - } + configCurator.putData(applicationIdPath(), id.serializedForm()); } - private String getApplicationIdPath() { - return rootPath.append(APPLICATION_ID_PATH).getAbsolute(); + public ApplicationId readApplicationId() { + if ( ! configCurator.exists(applicationIdPath())) return ApplicationId.defaultId(); + return ApplicationId.fromSerializedForm(configCurator.getData(applicationIdPath())); } - public ApplicationId readApplicationId(TenantName tenant) { - String path = getApplicationIdPath(); - try { - // Fallback for cases where id never existed. - if ( ! configCurator.exists(path)) { - // TODO: DEBUG LOG - log.log(LogLevel.INFO, "Unable to locate application id at '" + path + "', returning default"); - return ApplicationId.defaultId(); - } - return ApplicationId.fromSerializedForm(configCurator.getData(path)); - } catch (RuntimeException e) { - throw new RuntimeException("Unable to read application id from '" + path + "'", e); - } + private String versionPath() { + return rootPath.append(VERSION_PATH).getAbsolute(); + } + + public void writeVespaVersion(Version version) { + configCurator.putData(versionPath(), version.toString()); + } + + public Version readVespaVersion() { + if ( ! configCurator.exists(versionPath())) return Vtag.currentVersion; + return new Version(configCurator.getData(versionPath())); } // in seconds public long readCreateTime() { String path = getCreateTimePath(); - if (!configCurator.exists(path)) return 0l; + if ( ! configCurator.exists(path)) return 0L; return Long.parseLong(configCurator.getData(path)); } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/ModelContextImplTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/ModelContextImplTest.java index 0352f2c9f3e..74f030919ec 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/ModelContextImplTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/ModelContextImplTest.java @@ -1,6 +1,7 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.config.server; +import com.yahoo.component.Version; import com.yahoo.config.model.api.ModelContext; import com.yahoo.config.model.application.provider.BaseDeployLogger; import com.yahoo.config.model.application.provider.MockFileRegistry; @@ -48,7 +49,8 @@ public class ModelContextImplTest { Zone.defaultZone(), rotations), Optional.empty(), - Optional.empty()); + new Version(6), + new Version(6)); assertTrue(context.applicationPackage() instanceof MockApplicationPackage); assertFalse(context.hostProvisioner().isPresent()); assertFalse(context.permanentApplicationPackage().isPresent()); 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 07fb3cd51c7..8e20f190c5b 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 @@ -115,14 +115,14 @@ public class DeployTester { /** * Do the initial "deploy" with the existing API-less code as the deploy API doesn't support first deploys yet. */ - public ApplicationId deployApp(String appName, Optional<String> dockerVespaImageVersion) { + public ApplicationId deployApp(String appName, Optional<String> vespaVersion) { final Tenant tenant = tenant(); LocalSession session = tenant.getSessionFactory().createSession(testApp, appName, new TimeoutBudget(Clock.systemUTC(), Duration.ofSeconds(60))); ApplicationId id = ApplicationId.from(tenant.getName(), ApplicationName.from(appName), InstanceName.defaultName()); PrepareParams.Builder paramsBuilder = new PrepareParams.Builder() .applicationId(id); - if (dockerVespaImageVersion.isPresent()) - paramsBuilder.dockerVespaImageVersion(dockerVespaImageVersion.get()); + if (vespaVersion.isPresent()) + paramsBuilder.vespaVersion(vespaVersion.get()); session.prepare(new SilentDeployLogger(), paramsBuilder.build(), 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 a6ad3aff6a2..22db3a6e1c2 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 @@ -97,7 +97,7 @@ public class HostedDeployTest { private void assertProvisionInfo(String vespaVersion, DeployTester tester, ApplicationId applicationId) { tester.getProvisionInfoFromDeployedApp(applicationId).getHosts().stream() .forEach(h -> assertEquals(dockerRegistry + dockerVespaBaseImage + ":" + vespaVersion, - h.membership().get().cluster().dockerImage().get())); + h.membership().get().cluster().dockerImage())); } private static ConfigserverConfig createConfigserverConfig() { diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/session/PrepareParamsTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/session/PrepareParamsTest.java index d91fff41f2e..08cb5c92c1b 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/session/PrepareParamsTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/session/PrepareParamsTest.java @@ -1,10 +1,10 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.config.server.session; +import com.yahoo.component.Version; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.Rotation; import com.yahoo.config.provision.TenantName; -import com.yahoo.config.provision.Version; import com.yahoo.container.jdisc.HttpRequest; import org.junit.Test; @@ -28,15 +28,14 @@ public class PrepareParamsTest { @Test public void testCorrectParsing() { - PrepareParams prepareParams = createParams("http://foo:19071/application/v2/", - TenantName.defaultName()); + PrepareParams prepareParams = createParams("http://foo:19071/application/v2/", TenantName.defaultName()); assertThat(prepareParams.getApplicationId(), is(ApplicationId.defaultId())); assertFalse(prepareParams.isDryRun()); assertFalse(prepareParams.ignoreValidationErrors()); - assertThat(prepareParams.getVespaVersion(), is(Optional.<String>empty())); + assertThat(prepareParams.vespaVersion(), is(Optional.<String>empty())); assertTrue(prepareParams.getTimeoutBudget().hasTimeLeft()); - assertThat(prepareParams.getRotations().size(), is(0)); + assertThat(prepareParams.rotations().size(), is(0)); } @@ -46,35 +45,33 @@ public class PrepareParamsTest { PrepareParams.DRY_RUN_PARAM_NAME + "=true&" + PrepareParams.IGNORE_VALIDATION_PARAM_NAME + "=false&" + PrepareParams.APPLICATION_NAME_PARAM_NAME + "=baz&" + - PrepareParams.VESPA_VERSION_PARAM_NAME + "=" + vespaVersion + "&" + - PrepareParams.DOCKER_VESPA_IMAGE_VERSION_PARAM_NAME+ "=" + vespaVersion; - + PrepareParams.VESPA_VERSION_PARAM_NAME + "=" + vespaVersion; + @Test public void testCorrectParsingWithRotation() { PrepareParams prepareParams = createParams(request + "&" + - PrepareParams.ROTATIONS_PARAM_NAME + "=" + rotation, - TenantName.from("foo")); + PrepareParams.ROTATIONS_PARAM_NAME + "=" + rotation, + TenantName.from("foo")); assertThat(prepareParams.getApplicationId().serializedForm(), is("foo:baz:default")); assertTrue(prepareParams.isDryRun()); assertFalse(prepareParams.ignoreValidationErrors()); - final Version expectedVersion = Version.fromString(vespaVersion); - assertThat(prepareParams.getVespaVersion().get(), is(expectedVersion)); + Version expectedVersion = Version.fromString(vespaVersion); + assertThat(prepareParams.vespaVersion().get(), is(expectedVersion)); assertTrue(prepareParams.getTimeoutBudget().hasTimeLeft()); - final Set<Rotation> rotations = prepareParams.getRotations(); + Set<Rotation> rotations = prepareParams.rotations(); assertThat(rotations.size(), is(1)); assertThat(rotations, contains(equalTo(new Rotation(rotation)))); - assertThat(prepareParams.getDockerVespaImageVersion().get(), is(expectedVersion)); } @Test public void testCorrectParsingWithSeveralRotations() { - final String rotationTwo = "rotation-043.vespa.a02.yahoodns.net"; - final String twoRotations = rotation + "," + rotationTwo; + String rotationTwo = "rotation-043.vespa.a02.yahoodns.net"; + String twoRotations = rotation + "," + rotationTwo; PrepareParams prepareParams = createParams(request + "&" + - PrepareParams.ROTATIONS_PARAM_NAME + "=" + twoRotations, - TenantName.from("foo")); - final Set<Rotation> rotations = prepareParams.getRotations(); + PrepareParams.ROTATIONS_PARAM_NAME + "=" + twoRotations, + TenantName.from("foo")); + Set<Rotation> rotations = prepareParams.rotations(); assertThat(rotations, containsInAnyOrder(new Rotation(rotation), new Rotation(rotationTwo))); } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionPreparerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionPreparerTest.java index ac25cba3b47..1e61e6e9e08 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionPreparerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionPreparerTest.java @@ -186,7 +186,7 @@ public class SessionPreparerTest extends TestWithCurator { preparer.prepare(getContext(getApplicationPackage(testApp)), getLogger(), params, Optional.empty(), tenantPath); SessionZooKeeperClient zkc = new SessionZooKeeperClient(curator, appPath); assertTrue(configCurator.exists(appPath.append(SessionZooKeeperClient.APPLICATION_ID_PATH).getAbsolute())); - assertThat(zkc.readApplicationId(tenant), is(origId)); + assertThat(zkc.readApplicationId(), is(origId)); } @Test diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionZooKeeperClientTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionZooKeeperClientTest.java index 4508d8c234f..d4f3665ac6f 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionZooKeeperClientTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/session/SessionZooKeeperClientTest.java @@ -76,7 +76,7 @@ public class SessionZooKeeperClientTest extends TestWithCurator { @Test public void require_that_default_name_is_returned_if_node_does_not_exist() { - assertThat(createSessionZKClient("3").readApplicationId(TenantName.defaultName()).application().value(), is("default")); + assertThat(createSessionZKClient("3").readApplicationId().application().value(), is("default")); } @Test @@ -101,7 +101,7 @@ public class SessionZooKeeperClientTest extends TestWithCurator { SessionZooKeeperClient zkc = createSessionZKClient(sessionId); String path = "/" + sessionId + "/" + SessionZooKeeperClient.APPLICATION_ID_PATH; configCurator.putData(path, idString); - ApplicationId zkId = zkc.readApplicationId(TenantName.defaultName()); + ApplicationId zkId = zkc.readApplicationId(); assertThat(zkId.serializedForm(), is(expectedIdString)); } diff --git a/logserver/src/main/java/com/yahoo/logserver/handlers/lasterrorsholder/LastErrorsHolder.java b/logserver/src/main/java/com/yahoo/logserver/handlers/lasterrorsholder/LastErrorsHolder.java index 132c0074cb7..54d6e005a90 100644 --- a/logserver/src/main/java/com/yahoo/logserver/handlers/lasterrorsholder/LastErrorsHolder.java +++ b/logserver/src/main/java/com/yahoo/logserver/handlers/lasterrorsholder/LastErrorsHolder.java @@ -25,6 +25,7 @@ import java.util.logging.Logger; * @author hmusum */ public class LastErrorsHolder extends AbstractLogHandler implements ConnectionFactory { + private static final Logger log = Logger.getLogger(LastErrorsHolder.class.getName()); private static final int maxNumErrors = 100; private final Object lock = new Object(); diff --git a/logserver/src/test/java/com/yahoo/logserver/handlers/lasterrorsholder/LastErrorsHolderTestCase.java b/logserver/src/test/java/com/yahoo/logserver/handlers/lasterrorsholder/LastErrorsHolderTestCase.java index 967441ce250..a0e97c28f76 100644 --- a/logserver/src/test/java/com/yahoo/logserver/handlers/lasterrorsholder/LastErrorsHolderTestCase.java +++ b/logserver/src/test/java/com/yahoo/logserver/handlers/lasterrorsholder/LastErrorsHolderTestCase.java @@ -23,6 +23,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; public class LastErrorsHolderTestCase { + private static final int serverPort = 18324; private static final int lastErrorsHolderPort = 18326; Server server; diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java index 7f13ff1a13c..b6b6b24fa89 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java @@ -3,6 +3,7 @@ package com.yahoo.vespa.hosted.provision.persistence; import com.google.common.collect.ImmutableSet; import com.yahoo.component.Version; +import com.yahoo.component.Vtag; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.ApplicationName; import com.yahoo.config.provision.ClusterMembership; @@ -125,8 +126,7 @@ public class NodeSerializer { object.setLong(restartGenerationKey, allocation.restartGeneration().wanted()); object.setLong(currentRestartGenerationKey, allocation.restartGeneration().current()); object.setBool(removableKey, allocation.isRemovable()); - allocation.membership().cluster().vespaVersion() - .ifPresent(version -> object.setString(wantedVespaVersionKey, version.toString())); + object.setString(wantedVespaVersionKey, allocation.membership().cluster().vespaVersion().toString()); } private void toSlime(History history, Cursor array) { @@ -224,7 +224,7 @@ public class NodeSerializer { } else { vespaVersion = softwareVersionFromSlime(object.field(wantedVespaVersionKey)); } - return ClusterMembership.fromVersion(object.field(serviceIdKey).asString(), vespaVersion); + return ClusterMembership.from(object.field(serviceIdKey).asString(), vespaVersion.orElse(Vtag.currentVersion)); } private Optional<Version> softwareVersionFromSlime(Inspector object) { diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodesResponse.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodesResponse.java index 2766a219931..0ac82f1dbd8 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodesResponse.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodesResponse.java @@ -156,8 +156,8 @@ class NodesResponse extends HttpResponse { toSlime(node.allocation().get().membership(), object.setObject("membership")); object.setLong("restartGeneration", node.allocation().get().restartGeneration().wanted()); object.setLong("currentRestartGeneration", node.allocation().get().restartGeneration().current()); - node.allocation().get().membership().cluster().dockerImage().ifPresent(image -> object.setString("wantedDockerImage", image)); - node.allocation().get().membership().cluster().vespaVersion().ifPresent(version -> object.setString("wantedVespaVersion", version.toFullString())); + object.setString("wantedDockerImage", node.allocation().get().membership().cluster().dockerImage()); + object.setString("wantedVespaVersion", node.allocation().get().membership().cluster().vespaVersion().toFullString()); } object.setLong("rebootGeneration", node.status().reboot().wanted()); object.setLong("currentRebootGeneration", node.status().reboot().current()); diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java index 2b5d8cb1708..a8490076d5b 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java @@ -101,15 +101,15 @@ public class MockNodeRepository extends NodeRepository { setDirty("host55.yahoo.com"); ApplicationId app1 = ApplicationId.from(TenantName.from("tenant1"), ApplicationName.from("application1"), InstanceName.from("instance1")); - ClusterSpec cluster1 = ClusterSpec.requestVersion(ClusterSpec.Type.container, ClusterSpec.Id.from("id1"), Optional.of(Version.fromString("6.42"))); + ClusterSpec cluster1 = ClusterSpec.request(ClusterSpec.Type.container, ClusterSpec.Id.from("id1"), Version.fromString("6.42")); provisioner.prepare(app1, cluster1, Capacity.fromNodeCount(2), 1, null); ApplicationId app2 = ApplicationId.from(TenantName.from("tenant2"), ApplicationName.from("application2"), InstanceName.from("instance2")); - ClusterSpec cluster2 = ClusterSpec.requestVersion(ClusterSpec.Type.content, ClusterSpec.Id.from("id2"), Optional.empty()); + ClusterSpec cluster2 = ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("id2"), Version.fromString("6.42")); activate(provisioner.prepare(app2, cluster2, Capacity.fromNodeCount(2), 1, null), app2, provisioner); ApplicationId app3 = ApplicationId.from(TenantName.from("tenant3"), ApplicationName.from("application3"), InstanceName.from("instance3")); - ClusterSpec cluster3 = ClusterSpec.requestVersion(ClusterSpec.Type.content, ClusterSpec.Id.from("id3"), Optional.empty()); + ClusterSpec cluster3 = ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("id3"), Version.fromString("6.42")); activate(provisioner.prepare(app3, cluster3, Capacity.fromNodeCount(2), 1, null), app3, provisioner); } diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/FailedExpirerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/FailedExpirerTest.java index b69c7815de6..0b818ddca87 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/FailedExpirerTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/FailedExpirerTest.java @@ -1,6 +1,7 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.provision.maintenance; +import com.yahoo.component.Version; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.ApplicationName; import com.yahoo.config.provision.Capacity; @@ -120,7 +121,7 @@ public class FailedExpirerTest { List<Node> provisioned = nodeRepository.getNodes(NodeType.tenant, Node.State.provisioned); nodeRepository.setReady(nodeRepository.setDirty(provisioned)); ApplicationId applicationId = ApplicationId.from(TenantName.from("foo"), ApplicationName.from("bar"), InstanceName.from("fuz")); - ClusterSpec cluster = ClusterSpec.requestVersion(ClusterSpec.Type.content, ClusterSpec.Id.from("test"), Optional.empty()); + ClusterSpec cluster = ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("test"), Version.fromString("6.42")); provisioner.prepare(applicationId, cluster, Capacity.fromNodeCount(3, flavorName), 1, null); NestedTransaction transaction = new NestedTransaction().add(new CuratorTransaction(curator)); provisioner.activate(transaction, applicationId, ProvisioningTester.toHostSpecs(nodes)); diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/InactiveAndFailedExpirerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/InactiveAndFailedExpirerTest.java index d0b7d78b217..b820a11bf74 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/InactiveAndFailedExpirerTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/InactiveAndFailedExpirerTest.java @@ -1,6 +1,7 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.provision.maintenance; +import com.yahoo.component.Version; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.ApplicationName; import com.yahoo.config.provision.Capacity; @@ -41,7 +42,7 @@ public class InactiveAndFailedExpirerTest { List<Node> nodes = tester.makeReadyNodes(2, "default"); // Allocate then deallocate 2 nodes - ClusterSpec cluster = ClusterSpec.requestVersion(ClusterSpec.Type.content, ClusterSpec.Id.from("test"), Optional.empty()); + ClusterSpec cluster = ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("test"), Version.fromString("6.42")); tester.prepare(applicationId, cluster, Capacity.fromNodeCount(2), 1); tester.activate(applicationId, ProvisioningTester.toHostSpecs(nodes)); assertEquals(2, tester.getNodes(applicationId, Node.State.active).size()); @@ -78,7 +79,9 @@ public class InactiveAndFailedExpirerTest { List<Node> nodes = tester.makeReadyNodes(1, "default"); // Allocate and deallocate a single node - ClusterSpec cluster = ClusterSpec.requestVersion(ClusterSpec.Type.content, ClusterSpec.Id.from("test"), Optional.empty()); + ClusterSpec cluster = ClusterSpec.request(ClusterSpec.Type.content, + ClusterSpec.Id.from("test"), + Version.fromString("6.42")); tester.prepare(applicationId, cluster, Capacity.fromNodeCount(1), 1); tester.activate(applicationId, ProvisioningTester.toHostSpecs(nodes)); assertEquals(1, tester.getNodes(applicationId, Node.State.active).size()); @@ -104,8 +107,8 @@ public class InactiveAndFailedExpirerTest { @Test public void node_that_wants_to_retire_is_moved_to_parked() { ProvisioningTester tester = new ProvisioningTester(new Zone(Environment.prod, RegionName.from("us-east"))); - ClusterSpec cluster = ClusterSpec.requestVersion(ClusterSpec.Type.content, ClusterSpec.Id.from("test"), - Optional.empty()); + ClusterSpec cluster = ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("test"), + Version.fromString("6.42")); tester.makeReadyNodes(5, "default"); // Allocate two nodes diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeFailTester.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeFailTester.java index 86aef3617f0..fb703cfdd2f 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeFailTester.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/NodeFailTester.java @@ -103,8 +103,8 @@ public class NodeFailTester { tester.createHostNodes(3); // Create applications - ClusterSpec clusterApp1 = ClusterSpec.requestVersion(ClusterSpec.Type.container, ClusterSpec.Id.from("test"), Optional.empty()); - ClusterSpec clusterApp2 = ClusterSpec.requestVersion(ClusterSpec.Type.content, ClusterSpec.Id.from("test"), Optional.empty()); + ClusterSpec clusterApp1 = ClusterSpec.request(ClusterSpec.Type.container, ClusterSpec.Id.from("test"), Version.fromString("6.42")); + ClusterSpec clusterApp2 = ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("test"), Version.fromString("6.42")); int wantedNodesApp1 = 5; int wantedNodesApp2 = 7; tester.activate(app1, clusterApp1, wantedNodesApp1); @@ -132,9 +132,9 @@ public class NodeFailTester { } // Create applications - ClusterSpec clusterNodeAdminApp = ClusterSpec.requestVersion(ClusterSpec.Type.container, ClusterSpec.Id.from("node-admin"), Optional.empty()); - ClusterSpec clusterApp1 = ClusterSpec.requestVersion(ClusterSpec.Type.container, ClusterSpec.Id.from("test"), Optional.of(Version.fromString("6.75.0"))); - ClusterSpec clusterApp2 = ClusterSpec.requestVersion(ClusterSpec.Type.content, ClusterSpec.Id.from("test"), Optional.of(Version.fromString("6.75.0"))); + ClusterSpec clusterNodeAdminApp = ClusterSpec.request(ClusterSpec.Type.container, ClusterSpec.Id.from("node-admin"), Version.fromString("6.42")); + ClusterSpec clusterApp1 = ClusterSpec.request(ClusterSpec.Type.container, ClusterSpec.Id.from("test"), Version.fromString("6.75.0")); + ClusterSpec clusterApp2 = ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("test"), Version.fromString("6.75.0")); Capacity allHosts = Capacity.fromRequiredNodeType(NodeType.host); Capacity capacity1 = Capacity.fromNodeCount(3, Optional.of("docker")); Capacity capacity2 = Capacity.fromNodeCount(5, Optional.of("docker")); @@ -163,7 +163,9 @@ public class NodeFailTester { // Create application Capacity allProxies = Capacity.fromRequiredNodeType(NodeType.proxy); - ClusterSpec clusterApp1 = ClusterSpec.requestVersion(ClusterSpec.Type.container, ClusterSpec.Id.from("test"), Optional.empty()); + ClusterSpec clusterApp1 = ClusterSpec.request(ClusterSpec.Type.container, + ClusterSpec.Id.from("test"), + Version.fromString("6.42")); tester.activate(app1, clusterApp1, allProxies); assertEquals(16, tester.nodeRepository.getNodes(NodeType.proxy, Node.State.active).size()); diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/OperatorChangeApplicationMaintainerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/OperatorChangeApplicationMaintainerTest.java index 63b22ba4726..8f9df5ac736 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/OperatorChangeApplicationMaintainerTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/OperatorChangeApplicationMaintainerTest.java @@ -1,6 +1,7 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.provision.maintenance; +import com.yahoo.component.Version; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.ApplicationName; import com.yahoo.config.provision.Capacity; @@ -108,8 +109,8 @@ public class OperatorChangeApplicationMaintainerTest { final ApplicationId app1 = ApplicationId.from(TenantName.from("foo1"), ApplicationName.from("bar"), InstanceName.from("fuz")); final ApplicationId app2 = ApplicationId.from(TenantName.from("foo2"), ApplicationName.from("bar"), InstanceName.from("fuz")); - final ClusterSpec clusterApp1 = ClusterSpec.requestVersion(ClusterSpec.Type.container, ClusterSpec.Id.from("test"), Optional.empty()); - final ClusterSpec clusterApp2 = ClusterSpec.requestVersion(ClusterSpec.Type.content, ClusterSpec.Id.from("test"), Optional.empty()); + final ClusterSpec clusterApp1 = ClusterSpec.request(ClusterSpec.Type.container, ClusterSpec.Id.from("test"), Version.fromString("6.42")); + final ClusterSpec clusterApp2 = ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("test"), Version.fromString("6.42")); final int wantedNodesApp1 = 5; final int wantedNodesApp2 = 7; MockDeployer deployer; // created on activation diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/PeriodicApplicationMaintainerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/PeriodicApplicationMaintainerTest.java index 9094e3fc599..800a750ff8a 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/PeriodicApplicationMaintainerTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/PeriodicApplicationMaintainerTest.java @@ -1,6 +1,7 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.provision.maintenance; +import com.yahoo.component.Version; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.ApplicationName; import com.yahoo.config.provision.Capacity; @@ -151,8 +152,8 @@ public class PeriodicApplicationMaintainerTest { final ApplicationId app1 = ApplicationId.from(TenantName.from("foo1"), ApplicationName.from("bar"), InstanceName.from("fuz")); final ApplicationId app2 = ApplicationId.from(TenantName.from("foo2"), ApplicationName.from("bar"), InstanceName.from("fuz")); - final ClusterSpec clusterApp1 = ClusterSpec.requestVersion(ClusterSpec.Type.container, ClusterSpec.Id.from("test"), Optional.empty()); - final ClusterSpec clusterApp2 = ClusterSpec.requestVersion(ClusterSpec.Type.content, ClusterSpec.Id.from("test"), Optional.empty()); + final ClusterSpec clusterApp1 = ClusterSpec.request(ClusterSpec.Type.container, ClusterSpec.Id.from("test"), Version.fromString("6.42")); + final ClusterSpec clusterApp2 = ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("test"), Version.fromString("6.42")); final int wantedNodesApp1 = 5; final int wantedNodesApp2 = 7; diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/ReservationExpirerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/ReservationExpirerTest.java index 8d41adec2cd..317e4da8da7 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/ReservationExpirerTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/ReservationExpirerTest.java @@ -1,6 +1,7 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.provision.maintenance; +import com.yahoo.component.Version; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.Capacity; import com.yahoo.config.provision.ClusterSpec; @@ -52,7 +53,7 @@ public class ReservationExpirerTest { assertEquals(2, nodeRepository.getNodes(NodeType.tenant, Node.State.dirty).size()); nodeRepository.setReady(nodes); ApplicationId applicationId = new ApplicationId.Builder().tenant("foo").applicationName("bar").instanceName("fuz").build(); - ClusterSpec cluster = ClusterSpec.requestVersion(ClusterSpec.Type.content, ClusterSpec.Id.from("test"), Optional.empty()); + ClusterSpec cluster = ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("test"), Version.fromString("6.42")); provisioner.prepare(applicationId, cluster, Capacity.fromNodeCount(2), 1, null); assertEquals(2, nodeRepository.getNodes(NodeType.tenant, Node.State.reserved).size()); diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/RetiredExpirerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/RetiredExpirerTest.java index 3e6281d59a7..986566be783 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/RetiredExpirerTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/RetiredExpirerTest.java @@ -1,6 +1,7 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.provision.maintenance; +import com.yahoo.component.Version; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.ApplicationName; import com.yahoo.config.provision.Capacity; @@ -57,7 +58,7 @@ public class RetiredExpirerTest { // Allocate content cluster of sizes 7 -> 2 -> 3: // Should end up with 3 nodes in the cluster (one previously retired), and 3 retired - ClusterSpec cluster = ClusterSpec.requestVersion(ClusterSpec.Type.content, ClusterSpec.Id.from("test"), Optional.empty()); + ClusterSpec cluster = ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("test"), Version.fromString("6.42")); int wantedNodes; activate(applicationId, cluster, wantedNodes=7, 1, provisioner); activate(applicationId, cluster, wantedNodes=2, 1, provisioner); @@ -94,7 +95,7 @@ public class RetiredExpirerTest { ApplicationId applicationId = ApplicationId.from(TenantName.from("foo"), ApplicationName.from("bar"), InstanceName.from("fuz")); - ClusterSpec cluster = ClusterSpec.requestVersion(ClusterSpec.Type.content, ClusterSpec.Id.from("test"), Optional.empty()); + ClusterSpec cluster = ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("test"), Version.fromString("6.42")); activate(applicationId, cluster, 8, 8, provisioner); activate(applicationId, cluster, 1, 1, provisioner); assertEquals(8, nodeRepository.getNodes(applicationId, Node.State.active).size()); diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/SerializationTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/SerializationTest.java index 97610e17b45..e8479ef9ec7 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/SerializationTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/SerializationTest.java @@ -3,6 +3,7 @@ package com.yahoo.vespa.hosted.provision.persistence; import com.google.common.collect.ImmutableSet; import com.yahoo.component.Version; +import com.yahoo.component.Vtag; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.ApplicationName; import com.yahoo.config.provision.ClusterMembership; @@ -65,7 +66,7 @@ public class SerializationTest { node = node.allocate(ApplicationId.from(TenantName.from("myTenant"), ApplicationName.from("myApplication"), InstanceName.from("myInstance")), - ClusterMembership.fromVersion("content/myId/0/0", Optional.empty()), + ClusterMembership.from("content/myId/0/0", Vtag.currentVersion), clock.instant()); assertEquals(1, node.history().events().size()); node = node.withRestart(new Generation(1, 2)); @@ -101,7 +102,7 @@ public class SerializationTest { Node node = createNode().allocate(ApplicationId.from(TenantName.from("myTenant"), ApplicationName.from("myApplication"), InstanceName.from("myInstance")), - ClusterMembership.fromVersion("content/myId/0/0", Optional.empty()), + ClusterMembership.from("content/myId/0/0", Vtag.currentVersion), clock.instant()); Node copy = nodeSerializer.fromJson(Node.State.provisioned, nodeSerializer.toJson(node)); assertEquals(NodeType.host, copy.type()); @@ -155,7 +156,7 @@ public class SerializationTest { node = node.allocate(ApplicationId.from(TenantName.from("myTenant"), ApplicationName.from("myApplication"), InstanceName.from("myInstance")), - ClusterMembership.fromVersion("content/myId/0", Optional.empty()), + ClusterMembership.from("content/myId/0", Vtag.currentVersion), clock.instant()); assertEquals(1, node.history().events().size()); clock.advance(Duration.ofMinutes(2)); @@ -203,7 +204,7 @@ public class SerializationTest { node = node.allocate(ApplicationId.from(TenantName.from("myTenant"), ApplicationName.from("myApplication"), InstanceName.from("myInstance")), - ClusterMembership.fromVersion("content/myId/0/0", Optional.empty()), + ClusterMembership.from("content/myId/0/0", Vtag.currentVersion), clock.instant()); node = node.with(node.status().setFailCount(0)); @@ -216,10 +217,8 @@ public class SerializationTest { public void serialize_docker_image() { Node node = createNode(); - Optional<Version> version = Optional.of("docker-registry.ops.yahoo.com:4443/vespa/ci:6.42.0") - .map(DockerImage::new) - .map(DockerImage::tagAsVersion); - ClusterMembership clusterMembership = ClusterMembership.fromVersion("content/myId/0", version); + Version version = new DockerImage("docker-registry.ops.yahoo.com:4443/vespa/ci:6.42.0").tagAsVersion(); + ClusterMembership clusterMembership = ClusterMembership.from("content/myId/0", version); Node nodeWithAllocation = node.with( new Allocation(ApplicationId.from(TenantName.from("myTenant"), @@ -230,7 +229,7 @@ public class SerializationTest { false)); Node deserializedNode = nodeSerializer.fromJson(State.provisioned, nodeSerializer.toJson(nodeWithAllocation)); - assertEquals("docker-registry.ops.yahoo.com:4443/vespa/ci:6.42.0", deserializedNode.allocation().get().membership().cluster().dockerImage().get()); + assertEquals("docker-registry.ops.yahoo.com:4443/vespa/ci:6.42.0", deserializedNode.allocation().get().membership().cluster().dockerImage()); } @Test @@ -279,8 +278,8 @@ public class SerializationTest { " }\n" + "}"; Node node = nodeSerializer.fromJson(State.active, Utf8.toBytes(nodeWithDockerImage)); - assertEquals("6.42.1", node.allocation().get().membership().cluster().vespaVersion().get().toString()); - assertEquals("docker-registry.ops.yahoo.com:4443/vespa/ci:6.42.1", node.allocation().get().membership().cluster().dockerImage().get()); + assertEquals("6.42.1", node.allocation().get().membership().cluster().vespaVersion().toString()); + assertEquals("docker-registry.ops.yahoo.com:4443/vespa/ci:6.42.1", node.allocation().get().membership().cluster().dockerImage()); String nodeWithWantedVespaVersion = "{\n" + @@ -295,8 +294,8 @@ public class SerializationTest { " }\n" + "}"; node = nodeSerializer.fromJson(State.active, Utf8.toBytes(nodeWithWantedVespaVersion)); - assertEquals("6.42.2", node.allocation().get().membership().cluster().vespaVersion().get().toString()); - assertEquals("docker-registry.ops.yahoo.com:4443/vespa/ci:6.42.2", node.allocation().get().membership().cluster().dockerImage().get()); + assertEquals("6.42.2", node.allocation().get().membership().cluster().vespaVersion().toString()); + assertEquals("docker-registry.ops.yahoo.com:4443/vespa/ci:6.42.2", node.allocation().get().membership().cluster().dockerImage()); } @Test diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/AclProvisioningTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/AclProvisioningTest.java index 4d83a5b5874..6ba2c40186d 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/AclProvisioningTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/AclProvisioningTest.java @@ -1,6 +1,7 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.provision.provisioning; +import com.yahoo.component.Version; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.Capacity; import com.yahoo.config.provision.ClusterSpec; @@ -223,8 +224,8 @@ public class AclProvisioningTest { } private List<Node> allocateNodes(Capacity capacity, ApplicationId applicationId) { - ClusterSpec cluster = ClusterSpec.requestVersion(ClusterSpec.Type.content, ClusterSpec.Id.from("test"), - Optional.empty()); + ClusterSpec cluster = ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("test"), + Version.fromString("6.42")); List<HostSpec> prepared = tester.prepare(applicationId, cluster, capacity, 1); tester.activate(applicationId, new HashSet<>(prepared)); return tester.getNodes(applicationId, Node.State.active).asList(); diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DockerProvisioningTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DockerProvisioningTest.java index 3f3284115bc..89119441a93 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DockerProvisioningTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DockerProvisioningTest.java @@ -24,6 +24,7 @@ import static org.junit.Assert.assertEquals; * @author bratseth */ public class DockerProvisioningTest { + private static final String dockerFlavor = "docker1"; @Test @@ -35,21 +36,21 @@ public class DockerProvisioningTest { tester.makeReadyDockerNodes(1, dockerFlavor, "dockerHost" + i); } - Optional<Version> wantedVespaVersion = Optional.of(Version.fromString("6.39")); - final int nodeCount = 7; + Version wantedVespaVersion = Version.fromString("6.39"); + int nodeCount = 7; List<HostSpec> hosts = tester.prepare(application1, - ClusterSpec.requestVersion(ClusterSpec.Type.content, ClusterSpec.Id.from("myContent"), wantedVespaVersion), + ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("myContent"), wantedVespaVersion), nodeCount, 1, dockerFlavor); tester.activate(application1, new HashSet<>(hosts)); - final NodeList nodes = tester.getNodes(application1, Node.State.active); + NodeList nodes = tester.getNodes(application1, Node.State.active); assertEquals(nodeCount, nodes.size()); assertEquals(dockerFlavor, nodes.asList().get(0).flavor().canonicalName()); // Upgrade Vespa version on nodes - Optional<Version> upgradedWantedVespaVersion = Optional.of(Version.fromString("6.40")); + Version upgradedWantedVespaVersion = Version.fromString("6.40"); List<HostSpec> upgradedHosts = tester.prepare(application1, - ClusterSpec.requestVersion(ClusterSpec.Type.content, ClusterSpec.Id.from("myContent"), upgradedWantedVespaVersion), + ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("myContent"), upgradedWantedVespaVersion), nodeCount, 1, dockerFlavor); tester.activate(application1, new HashSet<>(upgradedHosts)); final NodeList upgradedNodes = tester.getNodes(application1, Node.State.active); @@ -65,10 +66,10 @@ public class DockerProvisioningTest { ApplicationId application1 = tester.makeApplicationId(); tester.makeReadyDockerNodes(1, dockerFlavor, "dockerHost"); - List<HostSpec> hosts = tester.prepare(application1, ClusterSpec.requestVersion(ClusterSpec.Type.content, ClusterSpec.Id.from("myContent"), Optional.empty()), 1, 1, dockerFlavor); + List<HostSpec> hosts = tester.prepare(application1, ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("myContent"), Version.fromString("6.42")), 1, 1, dockerFlavor); tester.activate(application1, new HashSet<>(hosts)); - final NodeList nodes = tester.getNodes(application1, Node.State.active); + NodeList nodes = tester.getNodes(application1, Node.State.active); assertEquals(1, nodes.size()); assertEquals(dockerFlavor, nodes.asList().get(0).flavor().canonicalName()); } diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/MultigroupProvisioningTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/MultigroupProvisioningTest.java index 372819b3f98..3109afb7190 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/MultigroupProvisioningTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/MultigroupProvisioningTest.java @@ -1,6 +1,7 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.provision.provisioning; +import com.yahoo.component.Version; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.Capacity; import com.yahoo.config.provision.ClusterSpec; @@ -196,7 +197,7 @@ public class MultigroupProvisioningTest { assertEquals("No additional groups are retained containing retired nodes", wantedGroups, allGroups.size()); } - private ClusterSpec cluster() { return ClusterSpec.requestVersion(ClusterSpec.Type.content, ClusterSpec.Id.from("test"), Optional.empty()); } + private ClusterSpec cluster() { return ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("test"), Version.fromString("6.42")); } private Set<HostSpec> prepare(ApplicationId application, Capacity capacity, int groupCount, ProvisioningTester tester) { return new HashSet<>(tester.prepare(application, cluster(), capacity, groupCount)); diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/NodeTypeProvisioningTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/NodeTypeProvisioningTest.java index a3ff24d0e73..209c5195812 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/NodeTypeProvisioningTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/NodeTypeProvisioningTest.java @@ -1,5 +1,6 @@ package com.yahoo.vespa.hosted.provision.provisioning; +import com.yahoo.component.Version; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.Capacity; import com.yahoo.config.provision.ClusterSpec; @@ -83,9 +84,9 @@ public class NodeTypeProvisioningTest { private List<HostSpec> deployProxies(ApplicationId application, ProvisioningTester tester) { return tester.prepare(application, - ClusterSpec.requestVersion(ClusterSpec.Type.container, - ClusterSpec.Id.from("test"), - Optional.empty()), + ClusterSpec.request(ClusterSpec.Type.container, + ClusterSpec.Id.from("test"), + Version.fromString("6.42")), Capacity.fromRequiredNodeType(NodeType.proxy), 1); diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTest.java index d89541daebb..3ecfae3312a 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTest.java @@ -2,6 +2,7 @@ package com.yahoo.vespa.hosted.provision.provisioning; import com.yahoo.cloud.config.ConfigserverConfig; +import com.yahoo.component.Version; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.ApplicationName; import com.yahoo.config.provision.Capacity; @@ -659,8 +660,8 @@ public class ProvisioningTest { tester.makeReadyNodes(6, "large-variant-variant"); //cost = 11 ApplicationId applicationId = tester.makeApplicationId(); - ClusterSpec contentClusterSpec = ClusterSpec.requestVersion(ClusterSpec.Type.content, ClusterSpec.Id.from("myContent"), Optional.empty()); - ClusterSpec containerClusterSpec = ClusterSpec.requestVersion(ClusterSpec.Type.container, ClusterSpec.Id.from("myContainer"), Optional.empty()); + ClusterSpec contentClusterSpec = ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("myContent"), Version.fromString("6.42")); + ClusterSpec containerClusterSpec = ClusterSpec.request(ClusterSpec.Type.container, ClusterSpec.Id.from("myContainer"), Version.fromString("6.42")); List<HostSpec> containerNodes = tester.prepare(applicationId, containerClusterSpec, 5, 1, "large"); List<HostSpec> contentNodes = tester.prepare(applicationId, contentClusterSpec, 10, 1, "large"); @@ -681,10 +682,10 @@ public class ProvisioningTest { private SystemState prepare(ApplicationId application, int container0Size, int container1Size, int content0Size, int content1Size, String flavor, ProvisioningTester tester) { // "deploy prepare" with a two container clusters and a storage cluster having of two groups - ClusterSpec containerCluster0 = ClusterSpec.requestVersion(ClusterSpec.Type.container, ClusterSpec.Id.from("container0"), Optional.empty()); - ClusterSpec containerCluster1 = ClusterSpec.requestVersion(ClusterSpec.Type.container, ClusterSpec.Id.from("container1"), Optional.empty()); - ClusterSpec contentCluster0 = ClusterSpec.requestVersion(ClusterSpec.Type.content, ClusterSpec.Id.from("content0"), Optional.empty()); - ClusterSpec contentCluster1 = ClusterSpec.requestVersion(ClusterSpec.Type.content, ClusterSpec.Id.from("content1"), Optional.empty()); + ClusterSpec containerCluster0 = ClusterSpec.request(ClusterSpec.Type.container, ClusterSpec.Id.from("container0"), Version.fromString("6.42")); + ClusterSpec containerCluster1 = ClusterSpec.request(ClusterSpec.Type.container, ClusterSpec.Id.from("container1"), Version.fromString("6.42")); + ClusterSpec contentCluster0 = ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("content0"), Version.fromString("6.42")); + ClusterSpec contentCluster1 = ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("content1"), Version.fromString("6.42")); Set<HostSpec> container0 = prepare(application, containerCluster0, container0Size, 1, flavor, tester); Set<HostSpec> container1 = prepare(application, containerCluster1, container1Size, 1, flavor, tester); diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/VirtualNodeProvisioningTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/VirtualNodeProvisioningTest.java index ac7fdc3d44f..1cb27df3972 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/VirtualNodeProvisioningTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/VirtualNodeProvisioningTest.java @@ -1,6 +1,7 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.provision.provisioning; +import com.yahoo.component.Version; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.ClusterSpec; import com.yahoo.config.provision.Environment; @@ -31,8 +32,8 @@ import static org.junit.Assert.assertNotNull; public class VirtualNodeProvisioningTest { private static final String flavor = "v-4-8-100"; - private static final ClusterSpec contentClusterSpec = ClusterSpec.requestVersion(ClusterSpec.Type.content, ClusterSpec.Id.from("myContent"), Optional.empty()); - private static final ClusterSpec containerClusterSpec = ClusterSpec.requestVersion(ClusterSpec.Type.container, ClusterSpec.Id.from("myContainer"), Optional.empty()); + private static final ClusterSpec contentClusterSpec = ClusterSpec.request(ClusterSpec.Type.content, ClusterSpec.Id.from("myContent"), Version.fromString("6.42")); + private static final ClusterSpec containerClusterSpec = ClusterSpec.request(ClusterSpec.Type.container, ClusterSpec.Id.from("myContainer"), Version.fromString("6.42")); private ProvisioningTester tester; private ApplicationId applicationId; @@ -110,9 +111,9 @@ public class VirtualNodeProvisioningTest { tester.makeReadyVirtualNodes(1, flavor, "parentHost5"); tester.makeReadyVirtualNodes(1, flavor, "parentHost6"); - final int containerNodeCount = 2; - final int contentNodeCount = 2; - final int groups = 1; + int containerNodeCount = 2; + int contentNodeCount = 2; + int groups = 1; List<HostSpec> containerHosts = prepare(containerClusterSpec, containerNodeCount, groups); List<HostSpec> contentHosts = prepare(contentClusterSpec, contentNodeCount, groups); activate(containerHosts, contentHosts); @@ -141,9 +142,9 @@ public class VirtualNodeProvisioningTest { tester.makeReadyVirtualNodes(1, flavor, "parentHost3"); tester.makeReadyVirtualNodes(1, flavor, "parentHost4"); - final int containerNodeCount = 2; - final int contentNodeCount = 2; - final int groups = 1; + int containerNodeCount = 2; + int contentNodeCount = 2; + int groups = 1; List<HostSpec> containerHosts = prepare(containerClusterSpec, containerNodeCount, groups); List<HostSpec> contentHosts = prepare(contentClusterSpec, contentNodeCount, groups); activate(containerHosts, contentHosts); @@ -170,11 +171,11 @@ public class VirtualNodeProvisioningTest { tester.makeReadyVirtualNodes(2, flavor, "parentHost1"); tester.makeReadyVirtualNodes(1, flavor, "parentHost2"); - final int contentNodeCount = 3; + int contentNodeCount = 3; List<HostSpec> hosts = prepare(contentClusterSpec, contentNodeCount, 1); activate(hosts); - final List<Node> nodes = getNodes(applicationId); + List<Node> nodes = getNodes(applicationId); assertDistinctParentHosts(nodes, ClusterSpec.Type.content, contentNodeCount); } diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node1.json b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node1.json index b2a0cced9f5..7a9a70b0f9d 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node1.json +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node1.json @@ -26,6 +26,8 @@ }, "restartGeneration": 0, "currentRestartGeneration": 0, + "wantedDockerImage":"docker-registry.ops.yahoo.com:4443/vespa/ci:6.42.0", + "wantedVespaVersion":"6.42.0", "rebootGeneration": 1, "currentRebootGeneration": 0, "failCount": 0, diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node2.json b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node2.json index 83452ddedfc..e7d565bdd09 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node2.json +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node2.json @@ -26,6 +26,8 @@ }, "restartGeneration": 0, "currentRestartGeneration": 0, + "wantedDockerImage":"docker-registry.ops.yahoo.com:4443/vespa/ci:6.42.0", + "wantedVespaVersion":"6.42.0", "rebootGeneration": 1, "currentRebootGeneration": 0, "failCount": 0, diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node3.json b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node3.json index 5cba6a90bbe..483e90b2641 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node3.json +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node3.json @@ -24,6 +24,8 @@ }, "restartGeneration": 0, "currentRestartGeneration": 0, + "wantedDockerImage":"docker-registry.ops.yahoo.com:4443/vespa/ci:6.42.0", + "wantedVespaVersion":"6.42.0", "rebootGeneration": 1, "currentRebootGeneration": 0, "failCount": 0, diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node6.json b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node6.json index 112219a8778..0a3961d7217 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node6.json +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/node6.json @@ -26,6 +26,8 @@ }, "restartGeneration": 0, "currentRestartGeneration": 0, + "wantedDockerImage":"docker-registry.ops.yahoo.com:4443/vespa/ci:6.42.0", + "wantedVespaVersion":"6.42.0", "rebootGeneration": 1, "currentRebootGeneration": 0, "failCount": 0, |