diff options
6 files changed, 48 insertions, 11 deletions
diff --git a/config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentSpec.java b/config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentSpec.java index 22ffdeb7262..c4fec6e668e 100644 --- a/config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentSpec.java +++ b/config-model-api/src/main/java/com/yahoo/config/application/api/DeploymentSpec.java @@ -637,21 +637,29 @@ public class DeploymentSpec { private final String tagName; private final List<String> attributes; private final String message; + private final int majorVersion; - public DeprecatedElement(String tagName, List<String> attributes, String message) { + public DeprecatedElement(int majorVersion, String tagName, List<String> attributes, String message) { this.tagName = Objects.requireNonNull(tagName); this.attributes = Objects.requireNonNull(attributes); this.message = Objects.requireNonNull(message); + this.majorVersion = majorVersion; if (message.isBlank()) throw new IllegalArgumentException("message must be non-empty"); } + /** Returns the major version that deprecated this element */ + public int majorVersion() { + return majorVersion; + } + public String humanReadableString() { + String deprecationDescription = "deprecated since major version " + majorVersion; if (attributes.isEmpty()) { - return "Element '" + tagName + "' is deprecated. " + message; + return "Element '" + tagName + "' is " + deprecationDescription + ". " + message; } - return "Element '" + tagName + "' contains deprecated attribute" + (attributes.size() > 1 ? "s" : "") + ": " + + return "Element '" + tagName + "' contains attribute" + (attributes.size() > 1 ? "s " : " ") + attributes.stream().map(attr -> "'" + attr + "'").collect(Collectors.joining(", ")) + - ". " + message; + " " + deprecationDescription + ". " + message; } @Override diff --git a/config-model-api/src/main/java/com/yahoo/config/application/api/xml/DeploymentSpecXmlReader.java b/config-model-api/src/main/java/com/yahoo/config/application/api/xml/DeploymentSpecXmlReader.java index 2f73bff83b8..09d61835ae3 100644 --- a/config-model-api/src/main/java/com/yahoo/config/application/api/xml/DeploymentSpecXmlReader.java +++ b/config-model-api/src/main/java/com/yahoo/config/application/api/xml/DeploymentSpecXmlReader.java @@ -439,7 +439,7 @@ public class DeploymentSpecXmlReader { private Optional<String> readGlobalServiceId(Element environmentTag) { String globalServiceId = environmentTag.getAttribute(globalServiceIdAttribute); if (globalServiceId.isEmpty()) return Optional.empty(); - deprecate(environmentTag, List.of(globalServiceIdAttribute), "See https://cloud.vespa.ai/en/reference/routing#deprecated-syntax"); + deprecate(environmentTag, List.of(globalServiceIdAttribute), 7, "See https://cloud.vespa.ai/en/reference/routing#deprecated-syntax"); return Optional.of(globalServiceId); } @@ -524,15 +524,15 @@ public class DeploymentSpecXmlReader { private boolean readActive(Element regionTag) { String activeValue = regionTag.getAttribute("active"); if ("".equals(activeValue)) return true; // Default to active - deprecate(regionTag, List.of("active"), "See https://cloud.vespa.ai/en/reference/routing#deprecated-syntax"); + deprecate(regionTag, List.of("active"), 7, "See https://cloud.vespa.ai/en/reference/routing#deprecated-syntax"); if ("true".equals(activeValue)) return true; if ("false".equals(activeValue)) return false; throw new IllegalArgumentException("Value of 'active' attribute in region tag must be 'true' or 'false' " + "to control whether this region should receive traffic from the global endpoint of this application"); } - private void deprecate(Element element, List<String> attributes, String message) { - deprecatedElements.add(new DeprecatedElement(element.getTagName(), attributes, message)); + private void deprecate(Element element, List<String> attributes, int majorVersion, String message) { + deprecatedElements.add(new DeprecatedElement(majorVersion, element.getTagName(), attributes, message)); } private static boolean isEmptySpec(Element root) { diff --git a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java index 81649375c8a..701878f98ab 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java @@ -1089,9 +1089,9 @@ public class ContainerModelBuilderTest extends ContainerModelBuilderTestBase { assertFalse(logger.msgs.isEmpty()); assertEquals(Level.WARNING, logger.msgs.get(0).getFirst()); assertEquals(Level.WARNING, logger.msgs.get(1).getFirst()); - assertEquals("Element 'prod' contains deprecated attribute: 'global-service-id'. See https://cloud.vespa.ai/en/reference/routing#deprecated-syntax", + assertEquals("Element 'prod' contains attribute 'global-service-id' deprecated since major version 7. See https://cloud.vespa.ai/en/reference/routing#deprecated-syntax", logger.msgs.get(0).getSecond()); - assertEquals("Element 'region' contains deprecated attribute: 'active'. See https://cloud.vespa.ai/en/reference/routing#deprecated-syntax", + assertEquals("Element 'region' contains attribute 'active' deprecated since major version 7. See https://cloud.vespa.ai/en/reference/routing#deprecated-syntax", logger.msgs.get(1).getSecond()); } diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/pkg/ApplicationPackageValidator.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/pkg/ApplicationPackageValidator.java index ccad4fe92ad..b097814eadd 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/pkg/ApplicationPackageValidator.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/pkg/ApplicationPackageValidator.java @@ -59,6 +59,16 @@ public class ApplicationPackageValidator { validateEndpointChange(application, applicationPackage, instant); validateCompactedEndpoint(applicationPackage); validateSecurityClientsPem(applicationPackage); + validateDeprecatedElements(applicationPackage); + } + + /** Verify that deployment spec does not use elements deprecated on a major version older than compile version */ + private void validateDeprecatedElements(ApplicationPackage applicationPackage) { + for (var deprecatedElement : applicationPackage.deploymentSpec().deprecatedElements()) { + if (applicationPackage.compileVersion().isEmpty()) continue; + if (deprecatedElement.majorVersion() >= applicationPackage.compileVersion().get().getMajor()) continue; + throw new IllegalArgumentException(deprecatedElement.humanReadableString()); + } } /** Verify that we have the security/clients.pem file for public systems */ diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java index f4f50de59d7..75abf94bf0e 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/ControllerTest.java @@ -1195,4 +1195,20 @@ public class ControllerTest { assertEquals(cloudAccount, tester.controllerTester().configServer().cloudAccount(context.deploymentIdIn(zone)).get().value()); } + @Test + public void testSubmitWithElementDeprecatedOnPreviousMajor() { + DeploymentContext context = tester.newDeploymentContext(); + var applicationPackage = new ApplicationPackageBuilder() + .compileVersion(Version.fromString("8.1")) + .region("us-west-1") + .globalServiceId("qrs") + .build(); + try { + context.submit(applicationPackage).deploy(); + fail("Expected exception"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().contains("Element 'prod' contains attribute 'global-service-id' deprecated since major version 7")); + } + } + } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/ApplicationPackageBuilder.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/ApplicationPackageBuilder.java index 5d1a677bf51..490731ca06a 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/ApplicationPackageBuilder.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/deployment/ApplicationPackageBuilder.java @@ -147,7 +147,10 @@ public class ApplicationPackageBuilder { } public ApplicationPackageBuilder region(String regionName) { - return region(RegionName.from(regionName), true); + prodBody.append(" <region>") + .append(regionName) + .append("</region>\n"); + return this; } public ApplicationPackageBuilder region(RegionName regionName, boolean active) { |