From ecd871806391296801f5475c991c1a2d0820c7f9 Mon Sep 17 00:00:00 2001 From: Valerij Fredriksen Date: Tue, 21 Jul 2020 12:49:14 +0200 Subject: Create application package to remove all deployments --- .../controller/application/ApplicationPackage.java | 28 ++++++++++++++++++ .../application/ApplicationPackageValidator.java | 3 +- .../restapi/application/ApplicationApiTest.java | 33 ++++++++++++++++++++-- 3 files changed, 60 insertions(+), 4 deletions(-) diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ApplicationPackage.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ApplicationPackage.java index 083984bd13c..827a7554a36 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ApplicationPackage.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ApplicationPackage.java @@ -5,11 +5,13 @@ import com.google.common.collect.ImmutableMap; import com.google.common.hash.Hashing; import com.yahoo.component.Version; import com.yahoo.config.application.api.DeploymentSpec; +import com.yahoo.config.application.api.ValidationId; import com.yahoo.config.application.api.ValidationOverrides; import com.yahoo.security.X509CertificateUtils; import com.yahoo.slime.Inspector; import com.yahoo.slime.Slime; import com.yahoo.slime.SlimeUtils; +import com.yahoo.vespa.hosted.controller.deployment.ZipBuilder; import com.yahoo.yolean.Exceptions; import java.io.ByteArrayInputStream; @@ -19,7 +21,10 @@ import java.io.InputStreamReader; import java.io.Reader; import java.io.UncheckedIOException; import java.security.cert.X509Certificate; +import java.time.Duration; import java.time.Instant; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -184,4 +189,27 @@ public class ApplicationPackage { } + /** Creates a valid application package that will remove all application's deployments */ + public static ApplicationPackage createEmptyForDeploymentRemoval() { + DeploymentSpec deploymentSpec = DeploymentSpec.empty; + ValidationOverrides validationOverrides = allValidationOverrides(); + try (ZipBuilder zipBuilder = new ZipBuilder(deploymentSpec.xmlForm().length() + validationOverrides.xmlForm().length() + 500)) { + zipBuilder.add("validation-overrides.xml", validationOverrides.xmlForm().getBytes(UTF_8)); + zipBuilder.add("deployment.xml", deploymentSpec.xmlForm().getBytes(UTF_8)); + + zipBuilder.close(); + return new ApplicationPackage(zipBuilder.toByteArray()); + } + } + + private static ValidationOverrides allValidationOverrides() { + String until = DateTimeFormatter.ISO_LOCAL_DATE.format(Instant.now().plus(Duration.ofDays(25)).atZone(ZoneOffset.UTC)); + StringBuilder validationOverridesContents = new StringBuilder(1000); + validationOverridesContents.append("\n"); + for (ValidationId validationId: ValidationId.values()) + validationOverridesContents.append("\t").append(validationId.value()).append("\n"); + validationOverridesContents.append("\n"); + + return ValidationOverrides.fromXml(validationOverridesContents.toString()); + } } diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ApplicationPackageValidator.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ApplicationPackageValidator.java index b245718171f..3e72936575d 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ApplicationPackageValidator.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ApplicationPackageValidator.java @@ -51,7 +51,8 @@ public class ApplicationPackageValidator { /** Verify that we have the security/clients.pem file for public systems */ private void validateSecurityClientsPem(ApplicationPackage applicationPackage) { - if (controller.system().isPublic() && applicationPackage.trustedCertificates().isEmpty()) + if (!controller.system().isPublic() || applicationPackage.deploymentSpec().steps().isEmpty()) return; + if (applicationPackage.trustedCertificates().isEmpty()) throw new IllegalArgumentException("Missing required file 'security/clients.pem'"); } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java index 388ca65dc40..0b26b66ccef 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java @@ -70,11 +70,9 @@ import org.junit.Before; import org.junit.Test; import java.io.File; -import java.math.BigDecimal; import java.net.URI; import java.time.Duration; import java.time.Instant; -import java.time.YearMonth; import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.Base64; @@ -84,7 +82,6 @@ import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; -import java.util.TreeSet; import java.util.function.Supplier; import static com.yahoo.application.container.handler.Request.Method.DELETE; @@ -974,6 +971,36 @@ public class ApplicationApiTest extends ControllerContainerTest { new File("instance1-metering.json")); } + @Test + public void testRemovingAllDeployments() { + createAthenzDomainWithAdmin(ATHENZ_TENANT_DOMAIN, USER_ID); + ApplicationPackage applicationPackage = new ApplicationPackageBuilder() + .instances("instance1") + .region("us-west-1") + .region("us-east-3") + .region("eu-west-1") + .endpoint("eu", "default", "eu-west-1") + .endpoint("default", "default", "us-west-1", "us-east-3") + .build(); + + deploymentTester.controllerTester().createTenant("tenant1", ATHENZ_TENANT_DOMAIN.getName(), 432L); + + // Create tenant and deploy + var app = deploymentTester.newDeploymentContext("tenant1", "application1", "instance1"); + app.submit(applicationPackage).deploy(); + tester.controller().jobController().deploy(app.instanceId(), JobType.devUsEast1, Optional.empty(), applicationPackage); + + assertEquals(Set.of(ZoneId.from("prod.us-west-1"), ZoneId.from("prod.us-east-3"), ZoneId.from("prod.eu-west-1"), ZoneId.from("dev.us-east-1")), + app.instance().deployments().keySet()); + + tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/deployment", DELETE) + .userIdentity(USER_ID) + .oktaAccessToken(OKTA_AT).oktaIdentityToken(OKTA_IT), + "{\"message\":\"Application package version: 1.0.2-unknown\"}"); + + assertEquals(Set.of(ZoneId.from("dev.us-east-1")), app.instance().deployments().keySet()); + } + @Test public void testErrorResponses() throws Exception { createAthenzDomainWithAdmin(ATHENZ_TENANT_DOMAIN, USER_ID); -- cgit v1.2.3