diff options
author | Martin Polden <mpolden@mpolden.no> | 2019-10-21 13:20:44 +0200 |
---|---|---|
committer | Martin Polden <mpolden@mpolden.no> | 2019-10-21 13:20:44 +0200 |
commit | 16de69e746e3be247df8d45bbef576f64aafed79 (patch) | |
tree | e1c7ca3956b788f2ee0ae8569239b208a190a72f /controller-server/src/test/java | |
parent | c4348ba0ee1e05bf2c253bf388fae82435e1c7f0 (diff) |
Add support for downloading application package
Diffstat (limited to 'controller-server/src/test/java')
4 files changed, 63 insertions, 16 deletions
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ApplicationStoreMock.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ApplicationStoreMock.java index 48d573edd05..d915fe06720 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ApplicationStoreMock.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ApplicationStoreMock.java @@ -11,10 +11,10 @@ import com.yahoo.vespa.hosted.controller.api.integration.deployment.ApplicationV import com.yahoo.vespa.hosted.controller.api.integration.deployment.TesterId; import java.util.Map; +import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import static java.util.Objects.requireNonNull; -import static org.junit.Assert.assertFalse; /** * Threadsafe. @@ -40,6 +40,14 @@ public class ApplicationStoreMock implements ApplicationStore { } @Override + public Optional<byte[]> find(TenantName tenant, ApplicationName application, long buildNumber) { + return store.getOrDefault(appId(tenant, application), Map.of()).entrySet().stream() + .filter(kv -> kv.getKey().buildNumber().orElse(Long.MIN_VALUE) == buildNumber) + .map(Map.Entry::getValue) + .findFirst(); + } + + @Override public void put(TenantName tenant, ApplicationName application, ApplicationVersion applicationVersion, byte[] applicationPackage) { store.putIfAbsent(appId(tenant, application), new ConcurrentHashMap<>()); store.get(appId(tenant, application)).put(applicationVersion, applicationPackage); diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ContainerControllerTester.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ContainerControllerTester.java index 80e52f373d7..8a1bbcd09d5 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ContainerControllerTester.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ContainerControllerTester.java @@ -125,7 +125,7 @@ public class ContainerControllerTester { } public void assertResponse(Request request, String expectedResponse, int expectedStatusCode) { - containerTester.assertResponse(request, expectedResponse, expectedStatusCode); + containerTester.assertResponse(() -> request, expectedResponse, expectedStatusCode); } /* diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ContainerTester.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ContainerTester.java index 7f0b07e4c93..300eddd6291 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ContainerTester.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ContainerTester.java @@ -22,10 +22,12 @@ import java.io.File; import java.io.IOException; import java.io.UncheckedIOException; import java.nio.charset.CharacterCodingException; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; import java.time.Instant; import java.util.Optional; +import java.util.function.Consumer; import java.util.function.Supplier; import java.util.regex.Pattern; @@ -119,27 +121,26 @@ public class ContainerTester { } public void assertResponse(Supplier<Request> request, String expectedResponse) { - assertResponse(request.get(), expectedResponse, 200); + assertResponse(request, expectedResponse, 200); } public void assertResponse(Request request, String expectedResponse) { - assertResponse(request, expectedResponse, 200); + assertResponse(() -> request, expectedResponse, 200); } public void assertResponse(Supplier<Request> request, String expectedResponse, int expectedStatusCode) { - assertResponse(request.get(), expectedResponse, expectedStatusCode); + assertResponse(request, + (response) -> assertEquals(expectedResponse, new String(response.getBody(), StandardCharsets.UTF_8)), + expectedStatusCode); } - public void assertResponse(Request request, String expectedResponse, int expectedStatusCode) { + public void assertResponse(Supplier<Request> requestSupplier, Consumer<Response> responseAssertion, int expectedStatusCode) { + var request = requestSupplier.get(); FilterResult filterResult = invokeSecurityFilters(request); request = filterResult.request; Response response = filterResult.response != null ? filterResult.response : container.handleRequest(request); - try { - assertEquals(expectedResponse, response.getBodyAsString()); - } catch (IOException e) { - throw new UncheckedIOException(e); - } assertEquals("Status code", expectedStatusCode, response.getStatus()); + responseAssertion.accept(response); } // Hack to run request filters as part of the request processing chain. 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 b3f32f3861a..09fd804ea0c 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 @@ -94,6 +94,7 @@ import static com.yahoo.application.container.handler.Request.Method.GET; import static com.yahoo.application.container.handler.Request.Method.PATCH; import static com.yahoo.application.container.handler.Request.Method.POST; import static com.yahoo.application.container.handler.Request.Method.PUT; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -632,6 +633,14 @@ public class ApplicationApiTest extends ControllerContainerTest { .data(createApplicationSubmissionData(applicationPackage)), "{\"message\":\"Application package version: 1.0.43-d00d, source revision of repository 'repo', branch 'master' with commit 'd00d', by a@b, built against 6.1 at 1970-01-01T00:00:01Z\"}"); + // GET application package + tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/package", GET).userIdentity(HOSTED_VESPA_OPERATOR), + (response) -> { + assertEquals("attachment; filename=\"tenant1.application1-build43.zip\"", response.getHeaders().getFirst("Content-Disposition")); + assertArrayEquals(applicationPackage.zippedContent(), response.getBody()); + }, + 200); + // Second attempt has a service under a different domain than the tenant of the application, and fails. ApplicationPackage packageWithServiceForWrongDomain = new ApplicationPackageBuilder() .instances("instance1") @@ -659,6 +668,22 @@ public class ApplicationApiTest extends ControllerContainerTest { .data(createApplicationSubmissionData(packageWithService)), "{\"message\":\"Application package version: 1.0.44-d00d, source revision of repository 'repo', branch 'master' with commit 'd00d', by a@b, built against 6.1 at 1970-01-01T00:00:01Z\"}"); + // GET last submitted application package + tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/package", GET).userIdentity(HOSTED_VESPA_OPERATOR), + (response) -> { + assertEquals("attachment; filename=\"tenant1.application1-build44.zip\"", response.getHeaders().getFirst("Content-Disposition")); + assertArrayEquals(packageWithService.zippedContent(), response.getBody()); + }, + 200); + + // GET application package for previous build + tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/package?build=43", GET).userIdentity(HOSTED_VESPA_OPERATOR), + (response) -> { + assertEquals("attachment; filename=\"tenant1.application1-build43.zip\"", response.getHeaders().getFirst("Content-Disposition")); + assertArrayEquals(applicationPackage.zippedContent(), response.getBody()); + }, + 200); + // Fourth attempt has a wrong content hash in a header, and fails. tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/submit", POST) .screwdriverIdentity(SCREWDRIVER_ID) @@ -1139,6 +1164,21 @@ public class ApplicationApiTest extends ControllerContainerTest { ConfigServerMock configServer = serviceRegistry().configServerMock(); configServer.throwOnNextPrepare(new ConfigServerException(new URI("server-url"), "Failed to prepare application", ConfigServerException.ErrorCode.INVALID_APPLICATION_PACKAGE, null)); + + // GET non-existent application package + tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/package", GET).userIdentity(HOSTED_VESPA_OPERATOR), + "{\"error-code\":\"NOT_FOUND\",\"message\":\"No application package has been submitted for 'tenant1.application1'\"}", + 404); + + // GET non-existent application package of specific build + tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/package?build=42", GET).userIdentity(HOSTED_VESPA_OPERATOR), + "{\"error-code\":\"NOT_FOUND\",\"message\":\"No application package found for 'tenant1.application1' with build number 42\"}", + 404); + + // GET non-existent application package of invalid build + tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/package?build=foobar", GET).userIdentity(HOSTED_VESPA_OPERATOR), + "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Invalid build number: For input string: \\\"foobar\\\"\"}", + 400); // POST (deploy) an application with an invalid application package MultiPartStreamer entity = createApplicationDeployData(applicationPackageInstance1, true); @@ -1556,10 +1596,9 @@ public class ApplicationApiTest extends ControllerContainerTest { job.type(JobType.systemTest).submit(); // Notifying about job started not by the controller fails - Request request = request("/application/v4/tenant/tenant1/application/application1/jobreport", POST) + var request = request("/application/v4/tenant/tenant1/application/application1/jobreport", POST) .data(asJson(job.type(JobType.systemTest).report())) - .userIdentity(HOSTED_VESPA_OPERATOR) - .get(); + .userIdentity(HOSTED_VESPA_OPERATOR); tester.assertResponse(request, "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Notified of completion " + "of system-test for tenant1.application1, but that has not been triggered; last was " + controllerTester.controller().applications().requireInstance(app.id().defaultInstance()).deploymentJobs().jobStatus().get(JobType.systemTest).lastTriggered().get().at() + "\"}", 400); @@ -1567,8 +1606,7 @@ public class ApplicationApiTest extends ControllerContainerTest { // Notifying about unknown job fails request = request("/application/v4/tenant/tenant1/application/application1/jobreport", POST) .data(asJson(job.type(JobType.productionUsEast3).report())) - .userIdentity(HOSTED_VESPA_OPERATOR) - .get(); + .userIdentity(HOSTED_VESPA_OPERATOR); tester.assertResponse(request, "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Notified of completion " + "of production-us-east-3 for tenant1.application1, but that has not been triggered; last was never\"}", 400); |