From a9d8a7104c55bfd5b26529f2f3a4ee4c1a840ce3 Mon Sep 17 00:00:00 2001 From: Harald Musum Date: Thu, 18 Jan 2024 15:25:39 +0100 Subject: Support minimum-required-vespa-version attribute If attribute is set and the running Vespa version is lower than the specified version deployment will fail with invalid application package error --- .../vespa/model/builder/xml/dom/VespaDomBuilder.java | 15 +++++++++++++++ config-model/src/main/resources/schema/services.rnc | 1 + .../vespa/model/builder/xml/dom/VespaDomBuilderTest.java | 15 +++++++++++++++ .../schema-test-files/services-hosted-infrastructure.xml | 2 +- 4 files changed, 32 insertions(+), 1 deletion(-) (limited to 'config-model') diff --git a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/VespaDomBuilder.java b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/VespaDomBuilder.java index 1a5041f44ac..973ebc8c602 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/VespaDomBuilder.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/VespaDomBuilder.java @@ -2,6 +2,7 @@ package com.yahoo.vespa.model.builder.xml.dom; import ai.vespa.validation.Validation; +import com.yahoo.component.Version; import com.yahoo.config.model.ApplicationConfigProducerRoot; import com.yahoo.config.model.ConfigModelRepo; import com.yahoo.config.model.builder.xml.XmlHelper; @@ -62,6 +63,8 @@ public class VespaDomBuilder extends VespaModelBuilder { return new DomRootBuilder(name). build(deployState, parent, XmlHelper.getDocument(deployState.getApplicationPackage().getServices(), "services.xml") .getDocumentElement()); + } catch (IllegalArgumentException e) { + throw e; } catch (Exception e) { throw new IllegalArgumentException(e); } @@ -204,6 +207,7 @@ public class VespaDomBuilder extends VespaModelBuilder { @Override protected ApplicationConfigProducerRoot doBuild(DeployState deployState, TreeConfigProducer parent, Element producerSpec) { + verifyMinimumRequiredVespaVersion(deployState.getVespaVersion(), producerSpec); ApplicationConfigProducerRoot root = new ApplicationConfigProducerRoot(parent, name, deployState.getDocumentModel(), @@ -215,6 +219,17 @@ public class VespaDomBuilder extends VespaModelBuilder { new Client(root); return root; } + + private static void verifyMinimumRequiredVespaVersion(Version thisVersion, Element producerSpec) { + var minimumRequiredVespaVersion = producerSpec.getAttribute("minimum-required-vespa-version"); + if (minimumRequiredVespaVersion.isEmpty()) return; + if (Version.fromString(minimumRequiredVespaVersion).compareTo(thisVersion) > 0) + throw new IllegalArgumentException( + ("Cannot deploy application, minimum required Vespa version is specified as %s in services.xml" + + ", this Vespa version is %s.") + .formatted(minimumRequiredVespaVersion, thisVersion.toFullString())); + } + } /** diff --git a/config-model/src/main/resources/schema/services.rnc b/config-model/src/main/resources/schema/services.rnc index 1c30b2d91f9..03d4ee80683 100644 --- a/config-model/src/main/resources/schema/services.rnc +++ b/config-model/src/main/resources/schema/services.rnc @@ -7,6 +7,7 @@ include "containercluster.rnc" start = element services { attribute version { "1.0" }? & + attribute minimum-required-vespa-version { text }? & attribute application-type { "hosted-infrastructure" }? & element legacy { element v7-geo-positions { xsd:boolean } }? & GenericConfig* & diff --git a/config-model/src/test/java/com/yahoo/vespa/model/builder/xml/dom/VespaDomBuilderTest.java b/config-model/src/test/java/com/yahoo/vespa/model/builder/xml/dom/VespaDomBuilderTest.java index 66a64681c60..2d5b1a307cd 100755 --- a/config-model/src/test/java/com/yahoo/vespa/model/builder/xml/dom/VespaDomBuilderTest.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/builder/xml/dom/VespaDomBuilderTest.java @@ -17,6 +17,7 @@ import java.io.StringReader; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; /** * @author gjoranv @@ -99,6 +100,20 @@ public class VespaDomBuilderTest { assertEquals("hosts [" + host.getHostname() + "]", hostSystem.toString()); } + @Test + void testMinimumRequiredVespaVersion() { + var exception = assertThrows(IllegalArgumentException.class, + () -> createModel(hosts, """ + + """)); + assertEquals("Cannot deploy application, minimum required Vespa version is specified as 1.0.1 in services.xml, this Vespa version is 1.0.0.", + exception.getMessage()); + + createModel(hosts, """ + + """); + } + private VespaModel createModel(String hosts, String services) { VespaModelCreatorWithMockPkg creator = new VespaModelCreatorWithMockPkg(hosts, services); return creator.create(); diff --git a/config-model/src/test/schema-test-files/services-hosted-infrastructure.xml b/config-model/src/test/schema-test-files/services-hosted-infrastructure.xml index b1711906086..9144b1ad0f8 100644 --- a/config-model/src/test/schema-test-files/services-hosted-infrastructure.xml +++ b/config-model/src/test/schema-test-files/services-hosted-infrastructure.xml @@ -1,6 +1,6 @@ - + -- cgit v1.2.3