diff --git a/config-model-api/src/main/java/com/yahoo/config/model/api/Model.java b/config-model-api/src/main/java/com/yahoo/config/model/api/Model.java index a7fd48bfea8e..54d22d588325 100644 --- a/config-model-api/src/main/java/com/yahoo/config/model/api/Model.java +++ b/config-model-api/src/main/java/com/yahoo/config/model/api/Model.java @@ -70,6 +70,9 @@ public interface Model { /** Returns the version of this model. */ default Version version() { return Version.emptyVersion; } + /** Returns the wanted node version of this model. */ + default Version wantedNodeVersion() { return Version.emptyVersion; } + /** Returns the provisioned hosts of this. */ default Provisioned provisioned() { return new Provisioned(); } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/VespaModel.java b/config-model/src/main/java/com/yahoo/vespa/model/VespaModel.java index 8390cc59b6fe..ac99bee93edf 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/VespaModel.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/VespaModel.java @@ -108,6 +108,7 @@ public final class VespaModel extends AbstractConfigProducerRoot implements Seri public static final Logger log = Logger.getLogger(VespaModel.class.getName()); private final Version version; + private final Version wantedNodeVersion; private final ConfigModelRepo configModelRepo = new ConfigModelRepo(); private final AllocatedHosts allocatedHosts; @@ -170,6 +171,7 @@ private VespaModel(ConfigModelRegistry configModelRegistry, DeployState deploySt throws IOException, SAXException { super("vespamodel"); version = deployState.getVespaVersion(); + wantedNodeVersion = deployState.getWantedNodeVespaVersion(); fileReferencesRepository = new FileReferencesRepository(deployState.getFileRegistry()); rankingConstants = new RankingConstants(deployState.getFileRegistry(), Optional.empty()); validationOverrides = deployState.validationOverrides(); @@ -407,6 +409,11 @@ public Version version() { return version; } + @Override + public Version wantedNodeVersion() { + return wantedNodeVersion; + } + /** * Resolves config of the given type and config id, by first instantiating the correct {@link com.yahoo.config.ConfigInstance.Builder}, * calling {@link #getConfig(com.yahoo.config.ConfigInstance.Builder, String)}. The default values used will be those of the config diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/application/TenantApplications.java b/configserver/src/main/java/com/yahoo/vespa/config/server/application/TenantApplications.java index 7c669f290d3c..5e9e1e8bf33a 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/application/TenantApplications.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/application/TenantApplications.java @@ -390,10 +390,10 @@ public Set listFileReferences(ApplicationId applicationId) { @Override public boolean compatibleWith(Optional vespaVersion, ApplicationId application) { if (vespaVersion.isEmpty()) return true; - Version latestDeployed = applicationMapper.getForVersion(application, Optional.empty(), clock.instant()) - .getVespaVersion(); - boolean compatibleMajor = !incompatibleMajorVersions.value().contains(latestDeployed.getMajor()); - return compatibleMajor || vespaVersion.get().getMajor() == latestDeployed.getMajor(); + Version wantedVersion = applicationMapper.getForVersion(application, Optional.empty(), clock.instant()) + .getModel().wantedNodeVersion(); + boolean compatibleMajor = ! incompatibleMajorVersions.value().contains(wantedVersion.getMajor()); + return compatibleMajor || vespaVersion.get().getMajor() == wantedVersion.getMajor(); } @Override diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/application/TenantApplicationsTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/application/TenantApplicationsTest.java index 2b361e825e55..c95c95750a1d 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/application/TenantApplicationsTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/application/TenantApplicationsTest.java @@ -3,10 +3,12 @@ import com.yahoo.cloud.config.ConfigserverConfig; import com.yahoo.component.Version; +import com.yahoo.component.Vtag; import com.yahoo.concurrent.InThreadExecutorService; import com.yahoo.concurrent.StripedExecutor; import com.yahoo.config.model.NullConfigModelRegistry; import com.yahoo.config.model.application.provider.FilesApplicationPackage; +import com.yahoo.config.model.deploy.DeployState; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.TenantName; import com.yahoo.text.Utf8; @@ -50,6 +52,7 @@ import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; +import java.util.function.Supplier; import java.util.stream.IntStream; import static com.yahoo.vespa.config.server.application.TenantApplications.RemoveApplicationWaiter; @@ -151,6 +154,19 @@ public void require_that_application_ids_can_be_deleted() { assertEquals(0, repo.activeApplications().size()); } + private static ApplicationSet createSet(ApplicationId id, Version version) throws IOException, SAXException { + VespaModel model = new VespaModel(new NullConfigModelRegistry(), + new DeployState.Builder().wantedNodeVespaVersion(version) + .applicationPackage(FilesApplicationPackage.fromFile(new File("src/test/apps/app"))) + .build()); + return ApplicationSet.from(new Application(model, + new ServerCache(), + 1, + Version.emptyVersion, + MetricUpdater.createTestUpdater(), + id)); + } + @Test public void major_version_compatibility() throws Exception { InMemoryFlagSource flagSource = new InMemoryFlagSource(); @@ -158,30 +174,21 @@ public void major_version_compatibility() throws Exception { ApplicationId app1 = createApplicationId("myapp"); applications.createApplication(app1); applications.createPutTransaction(app1, 1).commit(); - VespaModel model = new VespaModel(FilesApplicationPackage.fromFile(new File("src/test/apps/app"))); - Function createApplicationSet = (version) -> { - return ApplicationSet.from(new Application(model, - new ServerCache(), - 1, - version, - MetricUpdater.createTestUpdater(), - app1)); - }; Version deployedVersion0 = Version.fromString("6.1"); - applications.activateApplication(createApplicationSet.apply(deployedVersion0), 1); + applications.activateApplication(createSet(app1, deployedVersion0), 1); assertTrue("Empty version is compatible", applications.compatibleWith(Optional.empty(), app1)); Version nodeVersion0 = Version.fromString("6.0"); assertTrue("Lower version is compatible", applications.compatibleWith(Optional.of(nodeVersion0), app1)); Version deployedVersion1 = Version.fromString("7.1"); - applications.activateApplication(createApplicationSet.apply(deployedVersion1), 1); + applications.activateApplication(createSet(app1, deployedVersion1), 1); assertTrue("New major is compatible", applications.compatibleWith(Optional.of(nodeVersion0), app1)); flagSource.withListFlag(PermanentFlags.INCOMPATIBLE_MAJOR_VERSIONS.id(), List.of(8), Integer.class); Version deployedVersion2 = Version.fromString("8.1"); - applications.activateApplication(createApplicationSet.apply(deployedVersion2), 1); + applications.activateApplication(createSet(app1, deployedVersion2), 1); assertFalse("New major is incompatible", applications.compatibleWith(Optional.of(nodeVersion0), app1)); Version nodeVersion1 = Version.fromString("8.0");