summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorValerij Fredriksen <valerijf@verizonmedia.com>2020-07-21 12:49:14 +0200
committerValerij Fredriksen <valerijf@verizonmedia.com>2020-07-21 12:49:14 +0200
commitecd871806391296801f5475c991c1a2d0820c7f9 (patch)
tree4e0b9a83bd03e878b6edfbf92926b1e638969a7c
parent4d5ddc879354e898b458150dbd7da69fecaddc0a (diff)
Create application package to remove all deployments
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ApplicationPackage.java28
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/ApplicationPackageValidator.java3
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java33
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("<validation-overrides version=\"1.0\">\n");
+ for (ValidationId validationId: ValidationId.values())
+ validationOverridesContents.append("\t<allow until=\"").append(until).append("\">").append(validationId.value()).append("</allow>\n");
+ validationOverridesContents.append("</validation-overrides>\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;
@@ -975,6 +972,36 @@ public class ApplicationApiTest extends ControllerContainerTest {
}
@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);