diff options
Diffstat (limited to 'controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java')
-rw-r--r-- | controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java | 1130 |
1 files changed, 565 insertions, 565 deletions
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 2435bb2efb8..e3292700432 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,8 +70,8 @@ import com.yahoo.vespa.hosted.controller.tenant.AthenzTenant; import com.yahoo.vespa.hosted.controller.tenant.LastLoginInfo; import com.yahoo.vespa.hosted.controller.versions.VespaVersion; import com.yahoo.yolean.Exceptions; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import javax.security.auth.x500.X500Principal; import java.io.File; @@ -100,9 +100,9 @@ import static com.yahoo.application.container.handler.Request.Method.PUT; import static java.net.URLEncoder.encode; import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.stream.Collectors.joining; -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; /** * @author bratseth @@ -153,7 +153,7 @@ public class ApplicationApiTest extends ControllerContainerTest { private ContainerTester tester; private DeploymentTester deploymentTester; - @Before + @BeforeEach public void before() { tester = new ContainerTester(container, responseFiles); deploymentTester = new DeploymentTester(new ControllerTester(tester)); @@ -161,24 +161,24 @@ public class ApplicationApiTest extends ControllerContainerTest { } @Test - public void testApplicationApi() { + void testApplicationApi() { createAthenzDomainWithAdmin(ATHENZ_TENANT_DOMAIN, USER_ID); // (Necessary but not provided in this API) // GET API root tester.assertResponse(request("/application/v4/", GET).userIdentity(USER_ID), - new File("root.json")); + new File("root.json")); // POST (add) a tenant without property ID tester.assertResponse(request("/application/v4/tenant/tenant1", POST) - .userIdentity(USER_ID) - .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}") - .oAuthCredentials(OKTA_CREDENTIALS), - new File("tenant-without-applications.json")); + .userIdentity(USER_ID) + .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}") + .oAuthCredentials(OKTA_CREDENTIALS), + new File("tenant-without-applications.json")); // PUT (modify) a tenant tester.assertResponse(request("/application/v4/tenant/tenant1", PUT) - .userIdentity(USER_ID) - .oAuthCredentials(OKTA_CREDENTIALS) - .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}"), - new File("tenant-without-applications.json")); + .userIdentity(USER_ID) + .oAuthCredentials(OKTA_CREDENTIALS) + .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}"), + new File("tenant-without-applications.json")); // Add another Athens domain, so we can try to create more tenants createAthenzDomainWithAdmin(ATHENZ_TENANT_DOMAIN_2, USER_ID); // New domain to test tenant w/property ID @@ -187,59 +187,59 @@ public class ApplicationApiTest extends ControllerContainerTest { // POST (add) a tenant with property ID tester.assertResponse(request("/application/v4/tenant/tenant2", POST) - .userIdentity(USER_ID) - .oAuthCredentials(OKTA_CREDENTIALS) - .data("{\"athensDomain\":\"domain2\", \"property\":\"property2\", \"propertyId\":\"1234\"}"), - new File("tenant-without-applications-with-id.json")); + .userIdentity(USER_ID) + .oAuthCredentials(OKTA_CREDENTIALS) + .data("{\"athensDomain\":\"domain2\", \"property\":\"property2\", \"propertyId\":\"1234\"}"), + new File("tenant-without-applications-with-id.json")); // PUT (modify) a tenant with property ID tester.assertResponse(request("/application/v4/tenant/tenant2", PUT) - .userIdentity(USER_ID) - .oAuthCredentials(OKTA_CREDENTIALS) - .data("{\"athensDomain\":\"domain2\", \"property\":\"property2\", \"propertyId\":\"1234\"}"), - new File("tenant-without-applications-with-id.json")); + .userIdentity(USER_ID) + .oAuthCredentials(OKTA_CREDENTIALS) + .data("{\"athensDomain\":\"domain2\", \"property\":\"property2\", \"propertyId\":\"1234\"}"), + new File("tenant-without-applications-with-id.json")); // GET a tenant with property ID and contact information updateContactInformation(); tester.controller().tenants().updateLastLogin(TenantName.from("tenant2"), List.of(LastLoginInfo.UserLevel.user, LastLoginInfo.UserLevel.administrator), Instant.ofEpochMilli(1234)); tester.assertResponse(request("/application/v4/tenant/tenant2", GET).userIdentity(USER_ID), - new File("tenant2.json")); + new File("tenant2.json")); // POST (create) an application tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1", POST) - .userIdentity(USER_ID) - .oAuthCredentials(OKTA_CREDENTIALS), - new File("instance-reference.json")); + .userIdentity(USER_ID) + .oAuthCredentials(OKTA_CREDENTIALS), + new File("instance-reference.json")); // GET a tenant tester.assertResponse(request("/application/v4/tenant/tenant1", GET).userIdentity(USER_ID), - new File("tenant-with-application.json")); + new File("tenant-with-application.json")); tester.assertResponse(request("/application/v4/tenant/tenant1", GET) - .userIdentity(USER_ID) - .properties(Map.of("activeInstances", "true")), - new File("tenant-without-applications.json")); + .userIdentity(USER_ID) + .properties(Map.of("activeInstances", "true")), + new File("tenant-without-applications.json")); // GET tenant applications tester.assertResponse(request("/application/v4/tenant/tenant1/application/", GET).userIdentity(USER_ID), - new File("application-list.json")); + new File("application-list.json")); // GET tenant application instances for application that does not exist tester.assertResponse(request("/application/v4/tenant/tenant1/application/fake-app/instance/", GET).userIdentity(USER_ID), "{\"error-code\":\"NOT_FOUND\",\"message\":\"Application 'fake-app' does not exist\"}", 404); // GET tenant applications (instances of "application1" only) tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/", GET).userIdentity(USER_ID), - new File("application-list.json")); + new File("application-list.json")); // GET at a tenant, with "&recursive=true&production=true", recurses over no instances yet, as they are not in deployment spec. tester.assertResponse(request("/application/v4/tenant/tenant1/", GET) - .userIdentity(USER_ID) - .properties(Map.of("recursive", "true", - "production", "true")), - new File("tenant-with-empty-application.json")); + .userIdentity(USER_ID) + .properties(Map.of("recursive", "true", + "production", "true")), + new File("tenant-with-empty-application.json")); // GET at an application, with "&recursive=true&production=true", recurses over no instances yet, as they are not in deployment spec. tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1", GET) - .userIdentity(USER_ID) - .properties(Map.of("recursive", "true", - "production", "true")), - new File("application-without-instances.json")); + .userIdentity(USER_ID) + .properties(Map.of("recursive", "true", + "production", "true")), + new File("application-without-instances.json")); addUserToHostedOperatorRole(HostedAthenzIdentities.from(HOSTED_VESPA_OPERATOR)); @@ -249,87 +249,87 @@ public class ApplicationApiTest extends ControllerContainerTest { // POST (deploy) an application to start a manual deployment in prod is not allowed MultiPartStreamer entity = createApplicationDeployData(applicationPackageInstance1); tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/deploy/production-us-east-3/", POST) - .data(entity) - .userIdentity(USER_ID), - "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Direct deployments are only allowed to manually deployed environments.\"}", 400); + .data(entity) + .userIdentity(USER_ID), + "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Direct deployments are only allowed to manually deployed environments.\"}", 400); // POST (deploy) an application to start a manual deployment in prod is allowed for operators tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/deploy/production-us-east-3/", POST) - .data(entity) - .userIdentity(HOSTED_VESPA_OPERATOR), - "{\"message\":\"Deployment started in run 1 of production-us-east-3 for tenant1.application1.instance1. This may take about 15 minutes the first time.\",\"run\":1}"); + .data(entity) + .userIdentity(HOSTED_VESPA_OPERATOR), + "{\"message\":\"Deployment started in run 1 of production-us-east-3 for tenant1.application1.instance1. This may take about 15 minutes the first time.\",\"run\":1}"); app1.runJob(DeploymentContext.productionUsEast3); tester.controller().applications().deactivate(app1.instanceId(), ZoneId.from("prod", "us-east-3")); // POST (deploy) an application to start a manual deployment to dev tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/deploy/dev-us-east-1/", POST) - .data(entity) - .userIdentity(USER_ID), - "{\"message\":\"Deployment started in run 1 of dev-us-east-1 for tenant1.application1.instance1. This may take about 15 minutes the first time.\",\"run\":1}"); + .data(entity) + .userIdentity(USER_ID), + "{\"message\":\"Deployment started in run 1 of dev-us-east-1 for tenant1.application1.instance1. This may take about 15 minutes the first time.\",\"run\":1}"); app1.runJob(DeploymentContext.devUsEast1); // POST (deploy) a job to restart a manual deployment to dev tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/job/dev-us-east-1", POST) - .userIdentity(USER_ID), - "{\"message\":\"Triggered dev-us-east-1 for tenant1.application1.instance1\"}"); + .userIdentity(USER_ID), + "{\"message\":\"Triggered dev-us-east-1 for tenant1.application1.instance1\"}"); app1.runJob(DeploymentContext.devUsEast1); // GET dev application package tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/job/dev-us-east-1/package", GET) - .userIdentity(USER_ID), - (response) -> { - assertEquals("attachment; filename=\"tenant1.application1.instance1.dev.us-east-1.zip\"", response.getHeaders().getFirst("Content-Disposition")); - assertArrayEquals(applicationPackageInstance1.zippedContent(), response.getBody()); - }, - 200); + .userIdentity(USER_ID), + (response) -> { + assertEquals("attachment; filename=\"tenant1.application1.instance1.dev.us-east-1.zip\"", response.getHeaders().getFirst("Content-Disposition")); + assertArrayEquals(applicationPackageInstance1.zippedContent(), response.getBody()); + }, + 200); // POST an application package is not generally allowed under user instance tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/otheruser/deploy/dev-us-east-1", POST) - .userIdentity(OTHER_USER_ID) - .data(createApplicationDeployData(applicationPackageInstance1)), - accessDenied, - 403); + .userIdentity(OTHER_USER_ID) + .data(createApplicationDeployData(applicationPackageInstance1)), + accessDenied, + 403); // DELETE a dev deployment is not generally allowed under user instance tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/otheruser/environment/dev/region/us-east-1", DELETE) - .userIdentity(OTHER_USER_ID), - accessDenied, - 403); + .userIdentity(OTHER_USER_ID), + accessDenied, + 403); // When the user is a tenant admin, user instances are allowed. // POST an application package is not allowed under user instance for tenant admins tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/myuser/deploy/dev-us-east-1", POST) - .userIdentity(USER_ID) - .data(createApplicationDeployData(applicationPackageInstance1)), - new File("deployment-job-accepted-2.json")); + .userIdentity(USER_ID) + .data(createApplicationDeployData(applicationPackageInstance1)), + new File("deployment-job-accepted-2.json")); tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/myuser/job/dev-us-east-1/diff/1", GET).userIdentity(HOSTED_VESPA_OPERATOR), - (response) -> assertTrue(response.getBodyAsString(), - response.getBodyAsString().contains("--- schemas/test.sd\n" + + (response) -> assertTrue(response.getBodyAsString().contains("--- schemas/test.sd\n" + "@@ -1,0 +1,1 @@\n" + - "+ search test { }\n")), + "+ search test { }\n"), + response.getBodyAsString()), 200); // DELETE a dev deployment is allowed under user instance for tenant admins tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/myuser/environment/dev/region/us-east-1", DELETE) - .userIdentity(USER_ID), - "{\"message\":\"Deactivated tenant1.application1.myuser in dev.us-east-1\"}"); + .userIdentity(USER_ID), + "{\"message\":\"Deactivated tenant1.application1.myuser in dev.us-east-1\"}"); // DELETE a user instance tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/myuser", DELETE) - .userIdentity(USER_ID) - .oAuthCredentials(OKTA_CREDENTIALS), - "{\"message\":\"Deleted instance tenant1.application1.myuser\"}"); + .userIdentity(USER_ID) + .oAuthCredentials(OKTA_CREDENTIALS), + "{\"message\":\"Deleted instance tenant1.application1.myuser\"}"); addScrewdriverUserToDeployRole(SCREWDRIVER_ID, - ATHENZ_TENANT_DOMAIN, - id.application()); + ATHENZ_TENANT_DOMAIN, + id.application()); // POST an application package and a test jar, submitting a new application for production deployment. tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/submit", POST) - .screwdriverIdentity(SCREWDRIVER_ID) - .data(createApplicationSubmissionData(applicationPackageInstance1, 123)), - "{\"message\":\"application build 1, source revision of repository 'repository1', branch 'master' with commit 'commit1', by a@b, built against 6.1 at 1970-01-01T00:00:01Z\"}"); + .screwdriverIdentity(SCREWDRIVER_ID) + .data(createApplicationSubmissionData(applicationPackageInstance1, 123)), + "{\"message\":\"application build 1, source revision of repository 'repository1', branch 'master' with commit 'commit1', by a@b, built against 6.1 at 1970-01-01T00:00:01Z\"}"); app1.runJob(DeploymentContext.systemTest).runJob(DeploymentContext.stagingTest).runJob(DeploymentContext.productionUsCentral1); @@ -344,102 +344,102 @@ public class ApplicationApiTest extends ControllerContainerTest { // POST (create) another application tester.assertResponse(request("/application/v4/tenant/tenant2/application/application2/instance/default", POST) - .userIdentity(USER_ID) - .oAuthCredentials(OKTA_CREDENTIALS), - new File("instance-reference-2.json")); + .userIdentity(USER_ID) + .oAuthCredentials(OKTA_CREDENTIALS), + new File("instance-reference-2.json")); ApplicationId id2 = ApplicationId.from("tenant2", "application2", "instance1"); var app2 = deploymentTester.newDeploymentContext(id2); addScrewdriverUserToDeployRole(SCREWDRIVER_ID, - ATHENZ_TENANT_DOMAIN_2, - id2.application()); + ATHENZ_TENANT_DOMAIN_2, + id2.application()); // POST an application package and a test jar, submitting a new application for production deployment. tester.assertResponse(request("/application/v4/tenant/tenant2/application/application2/submit", POST) - .screwdriverIdentity(SCREWDRIVER_ID) - .data(createApplicationSubmissionData(applicationPackage, 1000)), - "{\"message\":\"application build 1, source revision of repository 'repository1', branch 'master' with commit 'commit1', by a@b, built against 6.1 at 1970-01-01T00:00:01Z\"}"); + .screwdriverIdentity(SCREWDRIVER_ID) + .data(createApplicationSubmissionData(applicationPackage, 1000)), + "{\"message\":\"application build 1, source revision of repository 'repository1', branch 'master' with commit 'commit1', by a@b, built against 6.1 at 1970-01-01T00:00:01Z\"}"); deploymentTester.triggerJobs(); // POST a triggering to force a production job to start without successful tests tester.assertResponse(request("/application/v4/tenant/tenant2/application/application2/instance/instance1/job/production-us-west-1", POST) - .data("{ \"skipTests\": true, \"skipRevision\": true, \"skipUpgrade\": true }") - .userIdentity(USER_ID), - "{\"message\":\"Triggered production-us-west-1 for tenant2.application2.instance1, without revision and platform upgrade\"}"); + .data("{ \"skipTests\": true, \"skipRevision\": true, \"skipUpgrade\": true }") + .userIdentity(USER_ID), + "{\"message\":\"Triggered production-us-west-1 for tenant2.application2.instance1, without revision and platform upgrade\"}"); app2.runJob(DeploymentContext.productionUsWest1); // POST a re-triggering to force a production job to start with previous parameters tester.assertResponse(request("/application/v4/tenant/tenant2/application/application2/instance/instance1/job/production-us-west-1", POST) - .data("{\"reTrigger\":true}") - .userIdentity(USER_ID), - "{\"message\":\"Triggered production-us-west-1 for tenant2.application2.instance1\"}"); + .data("{\"reTrigger\":true}") + .userIdentity(USER_ID), + "{\"message\":\"Triggered production-us-west-1 for tenant2.application2.instance1\"}"); // DELETE manually deployed prod deployment again tester.assertResponse(request("/application/v4/tenant/tenant2/application/application2/instance/instance1/environment/prod/region/us-west-1", DELETE) - .userIdentity(HOSTED_VESPA_OPERATOR), - "{\"message\":\"Deactivated tenant2.application2.instance1 in prod.us-west-1\"}"); + .userIdentity(HOSTED_VESPA_OPERATOR), + "{\"message\":\"Deactivated tenant2.application2.instance1 in prod.us-west-1\"}"); // GET application having both change and outstanding change tester.assertResponse(request("/application/v4/tenant/tenant2/application/application2", GET) - .screwdriverIdentity(SCREWDRIVER_ID), - new File("application2.json")); + .screwdriverIdentity(SCREWDRIVER_ID), + new File("application2.json")); // PATCH in a major version override tester.assertResponse(request("/application/v4/tenant/tenant2/application/application2", PATCH) - .userIdentity(USER_ID) - .data("{\"majorVersion\":7}"), - "{\"message\":\"Set major version to 7\"}"); + .userIdentity(USER_ID) + .data("{\"majorVersion\":7}"), + "{\"message\":\"Set major version to 7\"}"); // POST a pem deploy key tester.assertResponse(request("/application/v4/tenant/tenant2/application/application2/key", POST) - .userIdentity(USER_ID) - .data("{\"key\":\"" + pemPublicKey + "\"}"), - "{\"keys\":[\"-----BEGIN PUBLIC KEY-----\\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuKVFA8dXk43kVfYKzkUqhEY2rDT9\\nz/4jKSTHwbYR8wdsOSrJGVEUPbS2nguIJ64OJH7gFnxM6sxUVj+Nm2HlXw==\\n-----END PUBLIC KEY-----\\n\"]}"); + .userIdentity(USER_ID) + .data("{\"key\":\"" + pemPublicKey + "\"}"), + "{\"keys\":[\"-----BEGIN PUBLIC KEY-----\\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuKVFA8dXk43kVfYKzkUqhEY2rDT9\\nz/4jKSTHwbYR8wdsOSrJGVEUPbS2nguIJ64OJH7gFnxM6sxUVj+Nm2HlXw==\\n-----END PUBLIC KEY-----\\n\"]}"); // PATCH in a pem deploy key at deprecated path tester.assertResponse(request("/application/v4/tenant/tenant2/application/application2/instance/default", PATCH) - .userIdentity(USER_ID) - .data("{\"pemDeployKey\":\"" + pemPublicKey + "\"}"), - "{\"message\":\"Added deploy key " + quotedPemPublicKey + "\"}"); + .userIdentity(USER_ID) + .data("{\"pemDeployKey\":\"" + pemPublicKey + "\"}"), + "{\"message\":\"Added deploy key " + quotedPemPublicKey + "\"}"); // GET an application with a major version override tester.assertResponse(request("/application/v4/tenant/tenant2/application/application2", GET) - .userIdentity(USER_ID), - new File("application2-with-patches.json")); + .userIdentity(USER_ID), + new File("application2-with-patches.json")); // PATCH in removal of the application major version override removal tester.assertResponse(request("/application/v4/tenant/tenant2/application/application2", PATCH) - .userIdentity(USER_ID) - .data("{\"majorVersion\":null}"), - "{\"message\":\"Set major version to empty\"}"); + .userIdentity(USER_ID) + .data("{\"majorVersion\":null}"), + "{\"message\":\"Set major version to empty\"}"); // GET compile version for an application tester.assertResponse(request("/application/v4/tenant/tenant2/application/application2/compile-version", GET) - .userIdentity(USER_ID), - "{\"compileVersion\":\"6.1.0\"}"); + .userIdentity(USER_ID), + "{\"compileVersion\":\"6.1.0\"}"); // DELETE the pem deploy key tester.assertResponse(request("/application/v4/tenant/tenant2/application/application2/key", DELETE) - .userIdentity(USER_ID) - .data("{\"key\":\"" + pemPublicKey + "\"}"), - "{\"keys\":[]}"); + .userIdentity(USER_ID) + .data("{\"key\":\"" + pemPublicKey + "\"}"), + "{\"keys\":[]}"); tester.assertResponse(request("/application/v4/tenant/tenant2/application/application2", GET) - .userIdentity(USER_ID), - new File("application2.json")); + .userIdentity(USER_ID), + new File("application2.json")); // DELETE instance 1 of 2 tester.assertResponse(request("/application/v4/tenant/tenant2/application/application2/instance/default", DELETE) - .userIdentity(USER_ID) - .oAuthCredentials(OKTA_CREDENTIALS), - "{\"message\":\"Deleted instance tenant2.application2.default\"}"); + .userIdentity(USER_ID) + .oAuthCredentials(OKTA_CREDENTIALS), + "{\"message\":\"Deleted instance tenant2.application2.default\"}"); // DELETE application with only one instance left tester.assertResponse(request("/application/v4/tenant/tenant2/application/application2", DELETE) - .userIdentity(USER_ID) - .oAuthCredentials(OKTA_CREDENTIALS), - "{\"message\":\"Deleted application tenant2.application2\"}"); + .userIdentity(USER_ID) + .oAuthCredentials(OKTA_CREDENTIALS), + "{\"message\":\"Deleted application tenant2.application2\"}"); // Set version 6.1 to broken to change compile version for. deploymentTester.upgrader().overrideConfidence(Version.fromString("6.1"), VespaVersion.Confidence.broken); @@ -448,44 +448,44 @@ public class ApplicationApiTest extends ControllerContainerTest { // GET tenant application deployments tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1", GET) - .userIdentity(USER_ID), - new File("instance.json")); + .userIdentity(USER_ID), + new File("instance.json")); // GET an application deployment tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/us-central-1/instance/instance1", GET) - .userIdentity(USER_ID), - new File("deployment.json")); + .userIdentity(USER_ID), + new File("deployment.json")); addIssues(deploymentTester, TenantAndApplicationId.from("tenant1", "application1")); // GET at root, with "&recursive=deployment", returns info about all tenants, their applications and their deployments tester.assertResponse(request("/application/v4/", GET) - .userIdentity(USER_ID) - .recursive("deployment"), - new File("recursive-root.json")); + .userIdentity(USER_ID) + .recursive("deployment"), + new File("recursive-root.json")); // GET at root, with "&recursive=tenant", returns info about all tenants, with limited info about their applications. tester.assertResponse(request("/application/v4/", GET) - .userIdentity(USER_ID) - .recursive("tenant"), - new File("recursive-until-tenant-root.json")); + .userIdentity(USER_ID) + .recursive("tenant"), + new File("recursive-until-tenant-root.json")); // GET at a tenant, with "&recursive=true", returns full info about their applications and their deployments tester.assertResponse(request("/application/v4/tenant/tenant1/", GET) - .userIdentity(USER_ID) - .recursive("true"), - new File("tenant1-recursive.json")); + .userIdentity(USER_ID) + .recursive("true"), + new File("tenant1-recursive.json")); // GET at an application, with "&recursive=true", returns full info about its deployments tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1", GET) - .userIdentity(USER_ID) - .recursive("true"), - new File("instance1-recursive.json")); + .userIdentity(USER_ID) + .recursive("true"), + new File("instance1-recursive.json")); // GET nodes tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/us-central-1/instance/instance1/nodes", GET) - .userIdentity(USER_ID), - new File("application-nodes.json")); + .userIdentity(USER_ID), + new File("application-nodes.json")); // GET clusters tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/us-central-1/instance/instance1/clusters", GET) - .userIdentity(USER_ID), - new File("application-clusters.json")); + .userIdentity(USER_ID), + new File("application-clusters.json")); // GET logs tester.assertResponse(request("/application/v4/tenant/tenant2/application/application1/environment/dev/region/us-east-1/instance/default/logs?from=1233&to=3214", GET) @@ -494,12 +494,12 @@ public class ApplicationApiTest extends ControllerContainerTest { // GET controller logs tester.assertResponse(request("/application/v4/tenant/tenant2/application/application1/environment/prod/region/controller/instance/default/logs?from=1233&to=3214", GET) - .userIdentity(USER_ID), - "INFO - All good"); + .userIdentity(USER_ID), + "INFO - All good"); // Get content/../foo tester.assertResponse(request("/application/v4/tenant/tenant2/application/application1/instance/default/environment/dev/region/us-east-1/content/%2E%2E%2Ffoo", GET).userIdentity(USER_ID), - accessDenied, 403); + accessDenied, 403); // Get content - root tester.assertResponse(request("/application/v4/tenant/tenant2/application/application1/instance/default/environment/dev/region/us-east-1/content/", GET).userIdentity(USER_ID), "{\"path\":\"/\"}"); @@ -513,121 +513,121 @@ public class ApplicationApiTest extends ControllerContainerTest { // GET metrics tester.assertJsonResponse(request("/application/v4/tenant/tenant2/application/application1/environment/dev/region/us-east-1/instance/default/metrics", GET) .userIdentity(USER_ID), - new File("proton-metrics.json")); + new File("proton-metrics.json")); // POST a roll-out of the latest application tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/deploying/application", POST) - .userIdentity(USER_ID), - "{\"message\":\"Triggered revision change to build 1 for tenant1.application1.instance1\"}"); + .userIdentity(USER_ID), + "{\"message\":\"Triggered revision change to build 1 for tenant1.application1.instance1\"}"); // POST a roll-out of a given revision tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/deploying/application", POST) - .data("{ \"build\": 1 }") - .userIdentity(USER_ID), - "{\"message\":\"Triggered revision change to build 1 for tenant1.application1.instance1\"}"); + .data("{ \"build\": 1 }") + .userIdentity(USER_ID), + "{\"message\":\"Triggered revision change to build 1 for tenant1.application1.instance1\"}"); // DELETE (cancel) ongoing change tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/deploying", DELETE) - .userIdentity(HOSTED_VESPA_OPERATOR), - "{\"message\":\"Changed deployment from 'revision change to build 1' to 'no change' for tenant1.application1.instance1\"}"); + .userIdentity(HOSTED_VESPA_OPERATOR), + "{\"message\":\"Changed deployment from 'revision change to build 1' to 'no change' for tenant1.application1.instance1\"}"); // DELETE (cancel) again is a no-op tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/deploying", DELETE) - .userIdentity(USER_ID) - .data("{\"cancel\":\"all\"}"), - "{\"message\":\"No deployment in progress for tenant1.application1.instance1 at this time\"}"); + .userIdentity(USER_ID) + .data("{\"cancel\":\"all\"}"), + "{\"message\":\"No deployment in progress for tenant1.application1.instance1 at this time\"}"); // POST pinning to a given version to an application tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/deploying/pin", POST) - .userIdentity(USER_ID) - .data("6.1.0"), - "{\"message\":\"Triggered pin to 6.1 for tenant1.application1.instance1\"}"); - assertTrue("Action is logged to audit log", - tester.controller().auditLogger().readLog().entries().stream() - .anyMatch(entry -> entry.resource().equals("/application/v4/tenant/tenant1/application/application1/instance/instance1/deploying/pin?"))); + .userIdentity(USER_ID) + .data("6.1.0"), + "{\"message\":\"Triggered pin to 6.1 for tenant1.application1.instance1\"}"); + assertTrue(tester.controller().auditLogger().readLog().entries().stream() + .anyMatch(entry -> entry.resource().equals("/application/v4/tenant/tenant1/application/application1/instance/instance1/deploying/pin?")), + "Action is logged to audit log"); tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/deploying", GET) - .userIdentity(USER_ID), "{\"platform\":\"6.1\",\"pinned\":true}"); + .userIdentity(USER_ID), "{\"platform\":\"6.1\",\"pinned\":true}"); tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/deploying/pin", GET) - .userIdentity(USER_ID), "{\"platform\":\"6.1\",\"pinned\":true}"); + .userIdentity(USER_ID), "{\"platform\":\"6.1\",\"pinned\":true}"); // DELETE only the pin to a given version tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/deploying/pin", DELETE) - .userIdentity(USER_ID), - "{\"message\":\"Changed deployment from 'pin to 6.1' to 'upgrade to 6.1' for tenant1.application1.instance1\"}"); + .userIdentity(USER_ID), + "{\"message\":\"Changed deployment from 'pin to 6.1' to 'upgrade to 6.1' for tenant1.application1.instance1\"}"); tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/deploying", GET) - .userIdentity(USER_ID), "{\"platform\":\"6.1\",\"pinned\":false}"); + .userIdentity(USER_ID), "{\"platform\":\"6.1\",\"pinned\":false}"); // POST pinning again tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/deploying/pin", POST) - .userIdentity(USER_ID) - .data("6.1"), - "{\"message\":\"Triggered pin to 6.1 for tenant1.application1.instance1\"}"); + .userIdentity(USER_ID) + .data("6.1"), + "{\"message\":\"Triggered pin to 6.1 for tenant1.application1.instance1\"}"); tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/deploying", GET) - .userIdentity(USER_ID), "{\"platform\":\"6.1\",\"pinned\":true}"); + .userIdentity(USER_ID), "{\"platform\":\"6.1\",\"pinned\":true}"); // DELETE only the version, but leave the pin tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/deploying/platform", DELETE) - .userIdentity(USER_ID), - "{\"message\":\"Changed deployment from 'pin to 6.1' to 'pin to current platform' for tenant1.application1.instance1\"}"); + .userIdentity(USER_ID), + "{\"message\":\"Changed deployment from 'pin to 6.1' to 'pin to current platform' for tenant1.application1.instance1\"}"); tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/deploying", GET) - .userIdentity(USER_ID), "{\"pinned\":true}"); + .userIdentity(USER_ID), "{\"pinned\":true}"); // DELETE also the pin to a given version tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/deploying/pin", DELETE) - .userIdentity(USER_ID), - "{\"message\":\"Changed deployment from 'pin to current platform' to 'no change' for tenant1.application1.instance1\"}"); + .userIdentity(USER_ID), + "{\"message\":\"Changed deployment from 'pin to current platform' to 'no change' for tenant1.application1.instance1\"}"); tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/deploying", GET) - .userIdentity(USER_ID), "{}"); + .userIdentity(USER_ID), "{}"); // POST a pause to a production job tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/job/production-us-west-1/pause", POST) - .userIdentity(USER_ID), - "{\"message\":\"production-us-west-1 for tenant1.application1.instance1 paused for " + DeploymentTrigger.maxPause + "\"}"); + .userIdentity(USER_ID), + "{\"message\":\"production-us-west-1 for tenant1.application1.instance1 paused for " + DeploymentTrigger.maxPause + "\"}"); // DELETE a pause of a production job tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/job/production-us-west-1/pause", DELETE) - .userIdentity(USER_ID), - "{\"message\":\"production-us-west-1 for tenant1.application1.instance1 resumed\"}"); + .userIdentity(USER_ID), + "{\"message\":\"production-us-west-1 for tenant1.application1.instance1 resumed\"}"); // POST a triggering to the same production job tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/job/production-us-west-1", POST) - .userIdentity(USER_ID), - "{\"message\":\"Triggered production-us-west-1 for tenant1.application1.instance1\"}"); + .userIdentity(USER_ID), + "{\"message\":\"Triggered production-us-west-1 for tenant1.application1.instance1\"}"); // POST a 'reindex application' command tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/environment/prod/region/us-central-1/reindex", POST) - .properties(Map.of("indexedOnly", "true", - "speed", "10")) - .userIdentity(USER_ID), - "{\"message\":\"Requested reindexing of tenant1.application1.instance1 in prod.us-central-1, for indexed types, with speed 10.0\"}"); + .properties(Map.of("indexedOnly", "true", + "speed", "10")) + .userIdentity(USER_ID), + "{\"message\":\"Requested reindexing of tenant1.application1.instance1 in prod.us-central-1, for indexed types, with speed 10.0\"}"); // POST a 'reindex application' command with cluster filter tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/environment/prod/region/us-central-1/reindex", POST) - .properties(Map.of("clusterId", "boo,moo")) - .userIdentity(USER_ID), - "{\"message\":\"Requested reindexing of tenant1.application1.instance1 in prod.us-central-1, on clusters boo, moo\"}"); + .properties(Map.of("clusterId", "boo,moo")) + .userIdentity(USER_ID), + "{\"message\":\"Requested reindexing of tenant1.application1.instance1 in prod.us-central-1, on clusters boo, moo\"}"); // POST a 'reindex application' command with cluster and document type filters tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/environment/prod/region/us-central-1/reindex", POST) - .properties(Map.of("clusterId", "boo,moo", - "documentType", "foo,boo")) - .userIdentity(USER_ID), - "{\"message\":\"Requested reindexing of tenant1.application1.instance1 in prod.us-central-1, on clusters boo, moo, for types foo, boo\"}"); + .properties(Map.of("clusterId", "boo,moo", + "documentType", "foo,boo")) + .userIdentity(USER_ID), + "{\"message\":\"Requested reindexing of tenant1.application1.instance1 in prod.us-central-1, on clusters boo, moo, for types foo, boo\"}"); // POST to enable reindexing tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/environment/prod/region/us-central-1/reindexing", POST) - .userIdentity(USER_ID), - "{\"message\":\"Enabled reindexing of tenant1.application1.instance1 in prod.us-central-1\"}"); + .userIdentity(USER_ID), + "{\"message\":\"Enabled reindexing of tenant1.application1.instance1 in prod.us-central-1\"}"); // DELETE to disable reindexing tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/environment/prod/region/us-central-1/reindexing", DELETE) - .userIdentity(USER_ID), - "{\"message\":\"Disabled reindexing of tenant1.application1.instance1 in prod.us-central-1\"}"); + .userIdentity(USER_ID), + "{\"message\":\"Disabled reindexing of tenant1.application1.instance1 in prod.us-central-1\"}"); // GET to get reindexing status tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/environment/prod/region/us-central-1/reindexing", GET) - .userIdentity(USER_ID), - "{\"enabled\":true,\"clusters\":[{\"name\":\"cluster\",\"pending\":[{\"type\":\"type\",\"requiredGeneration\":100}],\"ready\":[{\"type\":\"type\",\"readyAtMillis\":345,\"startedAtMillis\":456,\"endedAtMillis\":567,\"state\":\"failed\",\"message\":\"(#`д´)ノ\",\"progress\":0.1,\"speed\":1.0}]}]}"); + .userIdentity(USER_ID), + "{\"enabled\":true,\"clusters\":[{\"name\":\"cluster\",\"pending\":[{\"type\":\"type\",\"requiredGeneration\":100}],\"ready\":[{\"type\":\"type\",\"readyAtMillis\":345,\"startedAtMillis\":456,\"endedAtMillis\":567,\"state\":\"failed\",\"message\":\"(#`д´)ノ\",\"progress\":0.1,\"speed\":1.0}]}]}"); // POST to request a service dump tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/environment/prod/region/us-central-1/node/host-tenant1.application1.instance1-prod.us-central-1/service-dump", POST) @@ -643,122 +643,122 @@ public class ApplicationApiTest extends ControllerContainerTest { // POST a 'restart application' command tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/us-central-1/instance/instance1/restart", POST) - .userIdentity(USER_ID), - "{\"message\":\"Requested restart of tenant1.application1.instance1 in prod.us-central-1\"}"); + .userIdentity(USER_ID), + "{\"message\":\"Requested restart of tenant1.application1.instance1 in prod.us-central-1\"}"); // POST a 'restart application' command tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/us-central-1/instance/instance1/restart", POST) - .userIdentity(HOSTED_VESPA_OPERATOR), - "{\"message\":\"Requested restart of tenant1.application1.instance1 in prod.us-central-1\"}"); + .userIdentity(HOSTED_VESPA_OPERATOR), + "{\"message\":\"Requested restart of tenant1.application1.instance1 in prod.us-central-1\"}"); addUserToHostedOperatorRole(HostedAthenzIdentities.from(SCREWDRIVER_ID)); // POST a 'restart application' in staging environment tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/staging/region/us-east-3/instance/instance1/restart", POST) - .screwdriverIdentity(SCREWDRIVER_ID), - "{\"message\":\"Requested restart of tenant1.application1.instance1 in staging.us-east-3\"}"); + .screwdriverIdentity(SCREWDRIVER_ID), + "{\"message\":\"Requested restart of tenant1.application1.instance1 in staging.us-east-3\"}"); // POST a 'restart application' in test environment tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/test/region/us-east-1/instance/instance1/restart", POST) - .screwdriverIdentity(SCREWDRIVER_ID), - "{\"message\":\"Requested restart of tenant1.application1.instance1 in test.us-east-1\"}"); + .screwdriverIdentity(SCREWDRIVER_ID), + "{\"message\":\"Requested restart of tenant1.application1.instance1 in test.us-east-1\"}"); // POST a 'restart application' in dev environment tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/dev/region/us-east-1/instance/instance1/restart", POST) - .userIdentity(USER_ID), - "{\"message\":\"Requested restart of tenant1.application1.instance1 in dev.us-east-1\"}"); + .userIdentity(USER_ID), + "{\"message\":\"Requested restart of tenant1.application1.instance1 in dev.us-east-1\"}"); // POST a 'restart application' command with a host filter (other filters not supported yet) tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/us-central-1/instance/instance1/restart", POST) - .properties(Map.of("hostname", "node-1-tenant-host-prod.us-central-1")) - .screwdriverIdentity(SCREWDRIVER_ID), - "{\"message\":\"Requested restart of tenant1.application1.instance1 in prod.us-central-1\"}", 200); + .properties(Map.of("hostname", "node-1-tenant-host-prod.us-central-1")) + .screwdriverIdentity(SCREWDRIVER_ID), + "{\"message\":\"Requested restart of tenant1.application1.instance1 in prod.us-central-1\"}", 200); // POST a 'suspend application' in dev environment tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/environment/dev/region/us-east-1/suspend", POST) - .userIdentity(USER_ID), - "{\"message\":\"Suspended orchestration of tenant1.application1.instance1 in dev.us-east-1\"}"); + .userIdentity(USER_ID), + "{\"message\":\"Suspended orchestration of tenant1.application1.instance1 in dev.us-east-1\"}"); // POST a 'resume application' in dev environment tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/environment/dev/region/us-east-1/suspend", DELETE) - .userIdentity(USER_ID), - "{\"message\":\"Resumed orchestration of tenant1.application1.instance1 in dev.us-east-1\"}"); + .userIdentity(USER_ID), + "{\"message\":\"Resumed orchestration of tenant1.application1.instance1 in dev.us-east-1\"}"); // POST a 'suspend application' in prod environment fails tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/environment/prod/region/us-east-3/suspend", POST) - .userIdentity(USER_ID), - accessDenied, 403); + .userIdentity(USER_ID), + accessDenied, 403); // GET suspended tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/us-central-1/instance/instance1/suspended", GET) - .userIdentity(USER_ID), - new File("suspended.json")); + .userIdentity(USER_ID), + new File("suspended.json")); // GET service/state/v1 tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/environment/prod/region/us-central-1/service/storagenode/host.com/state/v1/?foo=bar", GET) - .userIdentity(USER_ID), - new File("service")); + .userIdentity(USER_ID), + new File("service")); // GET orchestrator tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/environment/prod/region/us-central-1/orchestrator", GET) - .userIdentity(USER_ID), - "{\"json\":\"thank you very much\"}"); + .userIdentity(USER_ID), + "{\"json\":\"thank you very much\"}"); // GET application package which has been deployed to production tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/package", GET) - .properties(Map.of("build", "latestDeployed")) - .userIdentity(HOSTED_VESPA_OPERATOR), - (response) -> { - assertEquals("attachment; filename=\"tenant1.application1-build1.zip\"", response.getHeaders().getFirst("Content-Disposition")); - assertArrayEquals(applicationPackageInstance1.zippedContent(), response.getBody()); - }, - 200); + .properties(Map.of("build", "latestDeployed")) + .userIdentity(HOSTED_VESPA_OPERATOR), + (response) -> { + assertEquals("attachment; filename=\"tenant1.application1-build1.zip\"", response.getHeaders().getFirst("Content-Disposition")); + assertArrayEquals(applicationPackageInstance1.zippedContent(), response.getBody()); + }, + 200); // DELETE application with active deployments fails tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1", DELETE) - .userIdentity(USER_ID) - .oAuthCredentials(OKTA_CREDENTIALS), - new File("delete-with-active-deployments.json"), 400); + .userIdentity(USER_ID) + .oAuthCredentials(OKTA_CREDENTIALS), + new File("delete-with-active-deployments.json"), 400); // DELETE (deactivate) a deployment - dev tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/dev/region/us-east-1/instance/instance1", DELETE) - .userIdentity(USER_ID), - "{\"message\":\"Deactivated tenant1.application1.instance1 in dev.us-east-1\"}"); + .userIdentity(USER_ID), + "{\"message\":\"Deactivated tenant1.application1.instance1 in dev.us-east-1\"}"); // DELETE (deactivate) a deployment - prod tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/us-central-1/instance/instance1", DELETE) - .screwdriverIdentity(SCREWDRIVER_ID), - "{\"message\":\"Deactivated tenant1.application1.instance1 in prod.us-central-1\"}"); + .screwdriverIdentity(SCREWDRIVER_ID), + "{\"message\":\"Deactivated tenant1.application1.instance1 in prod.us-central-1\"}"); // DELETE (deactivate) a deployment is idempotent tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/us-central-1/instance/instance1", DELETE) - .screwdriverIdentity(SCREWDRIVER_ID), - "{\"message\":\"Deactivated tenant1.application1.instance1 in prod.us-central-1\"}"); + .screwdriverIdentity(SCREWDRIVER_ID), + "{\"message\":\"Deactivated tenant1.application1.instance1 in prod.us-central-1\"}"); // Setup for test config tests tester.controller().jobController().deploy(ApplicationId.from("tenant1", "application1", "default"), - DeploymentContext.productionUsCentral1, - Optional.empty(), - applicationPackageDefault); + DeploymentContext.productionUsCentral1, + Optional.empty(), + applicationPackageDefault); tester.controller().jobController().deploy(ApplicationId.from("tenant1", "application1", "my-user"), - DeploymentContext.devUsEast1, - Optional.empty(), - applicationPackageDefault); + DeploymentContext.devUsEast1, + Optional.empty(), + applicationPackageDefault); // GET test-config for local tests against a dev deployment tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/my-user/job/dev-us-east-1/test-config", GET) - .userIdentity(USER_ID), - new File("test-config-dev.json")); + .userIdentity(USER_ID), + new File("test-config-dev.json")); // GET test-config for local tests against a prod deployment tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/my-user/job/production-us-central-1/test-config", GET) - .userIdentity(USER_ID), - new File("test-config.json")); + .userIdentity(USER_ID), + new File("test-config.json")); tester.controller().applications().deactivate(ApplicationId.from("tenant1", "application1", "default"), - ZoneId.from("prod", "us-central-1")); + ZoneId.from("prod", "us-central-1")); tester.controller().applications().deactivate(ApplicationId.from("tenant1", "application1", "my-user"), - ZoneId.from("dev", "us-east-1")); + ZoneId.from("dev", "us-east-1")); // teardown for test config tests // Second attempt has a service under a different domain than the tenant of the application, and fails. @@ -769,9 +769,9 @@ public class ApplicationApiTest extends ControllerContainerTest { .build(); allowLaunchOfService(new com.yahoo.vespa.athenz.api.AthenzService(ATHENZ_TENANT_DOMAIN_2, "service")); tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/submit", POST) - .screwdriverIdentity(SCREWDRIVER_ID) - .data(createApplicationSubmissionData(packageWithServiceForWrongDomain, 123)), - "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Athenz domain in deployment.xml: [domain2] must match tenant domain: [domain1]\"}", 400); + .screwdriverIdentity(SCREWDRIVER_ID) + .data(createApplicationSubmissionData(packageWithServiceForWrongDomain, 123)), + "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Athenz domain in deployment.xml: [domain2] must match tenant domain: [domain1]\"}", 400); // Third attempt has a service under the domain of the tenant, and also succeeds. ApplicationPackage packageWithService = new ApplicationPackageBuilder() @@ -783,54 +783,54 @@ public class ApplicationApiTest extends ControllerContainerTest { .build(); allowLaunchOfService(new com.yahoo.vespa.athenz.api.AthenzService(ATHENZ_TENANT_DOMAIN, "service")); tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/submit", POST) - .screwdriverIdentity(SCREWDRIVER_ID) - .data(createApplicationSubmissionData(packageWithService, 123)), - "{\"message\":\"application build 2, source revision of repository 'repository1', branch 'master' with commit 'commit1', by a@b, built against 6.1 at 1970-01-01T00:00:01Z\"}"); + .screwdriverIdentity(SCREWDRIVER_ID) + .data(createApplicationSubmissionData(packageWithService, 123)), + "{\"message\":\"application build 2, source revision of repository 'repository1', branch 'master' with commit 'commit1', by a@b, built against 6.1 at 1970-01-01T00:00:01Z\"}"); tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/diff/2", GET).userIdentity(HOSTED_VESPA_OPERATOR), - (response) -> assertTrue(response.getBodyAsString(), - response.getBodyAsString().contains("+ <deployment version='1.0' athenz-domain='domain1' athenz-service='service'>\n" + - "- <deployment version='1.0' >\n")), - 200); + (response) -> assertTrue(response.getBodyAsString().contains("+ <deployment version='1.0' athenz-domain='domain1' athenz-service='service'>\n" + + "- <deployment version='1.0' >\n"), + response.getBodyAsString()), + 200); // 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-build2.zip\"", response.getHeaders().getFirst("Content-Disposition")); - assertArrayEquals(packageWithService.zippedContent(), response.getBody()); - }, - 200); + (response) -> { + assertEquals("attachment; filename=\"tenant1.application1-build2.zip\"", response.getHeaders().getFirst("Content-Disposition")); + assertArrayEquals(packageWithService.zippedContent(), response.getBody()); + }, + 200); tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/package", GET).userIdentity(HOSTED_VESPA_OPERATOR).properties(Map.of("tests", "true")), - (response) -> { - assertEquals("attachment; filename=\"tenant1.application1-tests2.zip\"", response.getHeaders().getFirst("Content-Disposition")); - assertArrayEquals("content".getBytes(UTF_8), response.getBody()); - }, - 200); + (response) -> { + assertEquals("attachment; filename=\"tenant1.application1-tests2.zip\"", response.getHeaders().getFirst("Content-Disposition")); + assertArrayEquals("content".getBytes(UTF_8), response.getBody()); + }, + 200); // GET application package for specific build tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/package", GET) - .properties(Map.of("build", "2")) - .userIdentity(HOSTED_VESPA_OPERATOR), - (response) -> { - assertEquals("attachment; filename=\"tenant1.application1-build2.zip\"", response.getHeaders().getFirst("Content-Disposition")); - assertArrayEquals(packageWithService.zippedContent(), response.getBody()); - }, - 200); + .properties(Map.of("build", "2")) + .userIdentity(HOSTED_VESPA_OPERATOR), + (response) -> { + assertEquals("attachment; filename=\"tenant1.application1-build2.zip\"", response.getHeaders().getFirst("Content-Disposition")); + assertArrayEquals(packageWithService.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) - .header("X-Content-Hash", "not/the/right/hash") - .data(createApplicationSubmissionData(packageWithService, 123)), - "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Value of X-Content-Hash header does not match computed content hash\"}", 400); + .screwdriverIdentity(SCREWDRIVER_ID) + .header("X-Content-Hash", "not/the/right/hash") + .data(createApplicationSubmissionData(packageWithService, 123)), + "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Value of X-Content-Hash header does not match computed content hash\"}", 400); // Fifth attempt has the right content hash in a header, and succeeds. MultiPartStreamer streamer = createApplicationSubmissionData(packageWithService, 123); tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/submit", POST) - .screwdriverIdentity(SCREWDRIVER_ID) - .header("X-Content-Hash", Base64.getEncoder().encodeToString(Signatures.sha256Digest(streamer::data))) - .data(streamer), - "{\"message\":\"application build 3, source revision of repository 'repository1', branch 'master' with commit 'commit1', by a@b, built against 6.1 at 1970-01-01T00:00:01Z\"}"); + .screwdriverIdentity(SCREWDRIVER_ID) + .header("X-Content-Hash", Base64.getEncoder().encodeToString(Signatures.sha256Digest(streamer::data))) + .data(streamer), + "{\"message\":\"application build 3, source revision of repository 'repository1', branch 'master' with commit 'commit1', by a@b, built against 6.1 at 1970-01-01T00:00:01Z\"}"); // Sixth attempt has a multi-instance deployment spec, and is accepted. ApplicationPackage multiInstanceSpec = new ApplicationPackageBuilder() @@ -841,53 +841,53 @@ public class ApplicationApiTest extends ControllerContainerTest { .endpoint("default", "foo", "us-central-1", "us-west-1", "us-east-3") .build(); tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/submit", POST) - .screwdriverIdentity(SCREWDRIVER_ID) - .data(createApplicationSubmissionData(multiInstanceSpec, 123)), - "{\"message\":\"application build 4, source revision of repository 'repository1', branch 'master' with commit 'commit1', by a@b, built against 6.1 at 1970-01-01T00:00:01Z\"}"); + .screwdriverIdentity(SCREWDRIVER_ID) + .data(createApplicationSubmissionData(multiInstanceSpec, 123)), + "{\"message\":\"application build 4, source revision of repository 'repository1', branch 'master' with commit 'commit1', by a@b, built against 6.1 at 1970-01-01T00:00:01Z\"}"); // DELETE submitted build, to mark it as non-deployable tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/submit/2", DELETE) - .userIdentity(USER_ID), - "{\"message\":\"Marked build '2' as non-deployable\"}"); + .userIdentity(USER_ID), + "{\"message\":\"Marked build '2' as non-deployable\"}"); // GET deployment job overview, after triggering system and staging test jobs. assertEquals(2, tester.controller().applications().deploymentTrigger().triggerReadyJobs().triggered()); tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/job", GET) - .userIdentity(USER_ID), - new File("jobs.json")); + .userIdentity(USER_ID), + new File("jobs.json")); // GET deployment job overview for whole application. tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/deployment", GET) - .userIdentity(USER_ID), - new File("deployment-overview.json")); + .userIdentity(USER_ID), + new File("deployment-overview.json")); // GET system test job overview. tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/job/system-test", GET) - .userIdentity(USER_ID), - new File("system-test-job.json")); + .userIdentity(USER_ID), + new File("system-test-job.json")); // GET system test run 1 details. tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/job/system-test/run/1", GET) - .userIdentity(USER_ID), - new File("system-test-details.json")); + .userIdentity(USER_ID), + new File("system-test-details.json")); // DELETE a running job to have it aborted. tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/job/staging-test", DELETE) - .userIdentity(USER_ID), - "{\"message\":\"Aborting run 2 of staging-test for tenant1.application1.instance1\"}"); + .userIdentity(USER_ID), + "{\"message\":\"Aborting run 2 of staging-test for tenant1.application1.instance1\"}"); // GET compile version for specific major deploymentTester.controllerTester().upgradeSystem(Version.fromString("7.0")); deploymentTester.controllerTester().flagSource().withListFlag(PermanentFlags.INCOMPATIBLE_VERSIONS.id(), List.of("*"), String.class); tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/compile-version", GET) - .userIdentity(USER_ID).properties(Map.of("allowMajor", "7")), - "{\"compileVersion\":\"7.0.0\"}"); + .userIdentity(USER_ID).properties(Map.of("allowMajor", "7")), + "{\"compileVersion\":\"7.0.0\"}"); // OPTIONS return 200 OK tester.assertResponse(request("/application/v4/", Request.Method.OPTIONS) - .userIdentity(USER_ID), - ""); + .userIdentity(USER_ID), + ""); addNotifications(TenantName.from("tenant1")); addNotifications(TenantName.from("tenant2")); @@ -902,14 +902,14 @@ public class ApplicationApiTest extends ControllerContainerTest { // DELETE the application which no longer has any deployments tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1", DELETE) - .userIdentity(USER_ID) - .oAuthCredentials(OKTA_CREDENTIALS), - "{\"message\":\"Deleted application tenant1.application1\"}"); + .userIdentity(USER_ID) + .oAuthCredentials(OKTA_CREDENTIALS), + "{\"message\":\"Deleted application tenant1.application1\"}"); // DELETE an empty tenant tester.assertResponse(request("/application/v4/tenant/tenant1", DELETE).userIdentity(USER_ID) - .oAuthCredentials(OKTA_CREDENTIALS), - "{\"message\":\"Deleted tenant tenant1\"}"); + .oAuthCredentials(OKTA_CREDENTIALS), + "{\"message\":\"Deleted tenant tenant1\"}"); // The tenant is not found tester.assertResponse(request("/application/v4/tenant/tenant1", GET).userIdentity(USER_ID) @@ -947,7 +947,7 @@ public class ApplicationApiTest extends ControllerContainerTest { } @Test - public void testRotationOverride() { + void testRotationOverride() { // Setup createAthenzDomainWithAdmin(ATHENZ_TENANT_DOMAIN, USER_ID); var westZone = ZoneId.from("prod", "us-west-1"); @@ -965,60 +965,60 @@ public class ApplicationApiTest extends ControllerContainerTest { // Invalid application fails tester.assertResponse(request("/application/v4/tenant/tenant2/application/application2/environment/prod/region/us-west-1/instance/default/global-rotation", GET) - .userIdentity(USER_ID), - "{\"error-code\":\"BAD_REQUEST\",\"message\":\"tenant2.application2 not found\"}", - 400); + .userIdentity(USER_ID), + "{\"error-code\":\"BAD_REQUEST\",\"message\":\"tenant2.application2 not found\"}", + 400); // Invalid deployment fails tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/environment/prod/region/us-central-1/global-rotation", GET) - .userIdentity(USER_ID), - "{\"error-code\":\"NOT_FOUND\",\"message\":\"application 'tenant1.application1.instance1' has no deployment in prod.us-central-1\"}", - 404); + .userIdentity(USER_ID), + "{\"error-code\":\"NOT_FOUND\",\"message\":\"application 'tenant1.application1.instance1' has no deployment in prod.us-central-1\"}", + 404); // Change status of non-existing deployment fails tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/environment/prod/region/us-central-1/global-rotation/override", PUT) - .userIdentity(USER_ID) - .data("{\"reason\":\"unit-test\"}"), - "{\"error-code\":\"NOT_FOUND\",\"message\":\"application 'tenant1.application1.instance1' has no deployment in prod.us-central-1\"}", - 404); + .userIdentity(USER_ID) + .data("{\"reason\":\"unit-test\"}"), + "{\"error-code\":\"NOT_FOUND\",\"message\":\"application 'tenant1.application1.instance1' has no deployment in prod.us-central-1\"}", + 404); // GET global rotation status tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/environment/prod/region/us-west-1/global-rotation", GET) - .userIdentity(USER_ID), - new File("global-rotation.json")); + .userIdentity(USER_ID), + new File("global-rotation.json")); // GET global rotation override status tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/environment/prod/region/us-west-1/global-rotation/override", GET) - .userIdentity(USER_ID), - new File("global-rotation-get.json")); + .userIdentity(USER_ID), + new File("global-rotation-get.json")); // SET global rotation override status tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/environment/prod/region/us-west-1/global-rotation/override", PUT) - .userIdentity(USER_ID) - .data("{\"reason\":\"unit-test\"}"), - new File("global-rotation-put.json")); + .userIdentity(USER_ID) + .data("{\"reason\":\"unit-test\"}"), + new File("global-rotation-put.json")); // Status of routing policy is changed assertGlobalRouting(app.deploymentIdIn(westZone), RoutingStatus.Value.out, RoutingStatus.Agent.tenant); // DELETE global rotation override status tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/environment/prod/region/us-west-1/global-rotation/override", DELETE) - .userIdentity(USER_ID) - .data("{\"reason\":\"unit-test\"}"), - new File("global-rotation-delete.json")); + .userIdentity(USER_ID) + .data("{\"reason\":\"unit-test\"}"), + new File("global-rotation-delete.json")); assertGlobalRouting(app.deploymentIdIn(westZone), RoutingStatus.Value.in, RoutingStatus.Agent.tenant); // SET global rotation override status by operator addUserToHostedOperatorRole(HostedAthenzIdentities.from(HOSTED_VESPA_OPERATOR)); tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/environment/prod/region/us-west-1/global-rotation/override", PUT) - .userIdentity(HOSTED_VESPA_OPERATOR) - .data("{\"reason\":\"unit-test\"}"), - new File("global-rotation-put.json")); + .userIdentity(HOSTED_VESPA_OPERATOR) + .data("{\"reason\":\"unit-test\"}"), + new File("global-rotation-put.json")); assertGlobalRouting(app.deploymentIdIn(westZone), RoutingStatus.Value.out, RoutingStatus.Agent.operator); } @Test - public void multiple_endpoints() { + void multiple_endpoints() { // Setup createAthenzDomainWithAdmin(ATHENZ_TENANT_DOMAIN, USER_ID); ApplicationPackage applicationPackage = new ApplicationPackageBuilder() @@ -1036,34 +1036,34 @@ public class ApplicationApiTest extends ControllerContainerTest { // GET global rotation status without specifying endpointId fails tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/environment/prod/region/us-west-1/global-rotation", GET) - .userIdentity(USER_ID), - "{\"error-code\":\"BAD_REQUEST\",\"message\":\"application 'tenant1.application1.instance1' has multiple rotations. Query parameter 'endpointId' must be given\"}", - 400); + .userIdentity(USER_ID), + "{\"error-code\":\"BAD_REQUEST\",\"message\":\"application 'tenant1.application1.instance1' has multiple rotations. Query parameter 'endpointId' must be given\"}", + 400); // GET global rotation status for us-west-1 in default endpoint tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/environment/prod/region/us-west-1/global-rotation", GET) - .properties(Map.of("endpointId", "default")) - .userIdentity(USER_ID), - "{\"bcpStatus\":{\"rotationStatus\":\"UNKNOWN\"}}", - 200); + .properties(Map.of("endpointId", "default")) + .userIdentity(USER_ID), + "{\"bcpStatus\":{\"rotationStatus\":\"UNKNOWN\"}}", + 200); // GET global rotation status for us-west-1 in eu endpoint tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/environment/prod/region/us-west-1/global-rotation", GET) - .properties(Map.of("endpointId", "eu")) - .userIdentity(USER_ID), - "{\"bcpStatus\":{\"rotationStatus\":\"UNKNOWN\"}}", - 200); + .properties(Map.of("endpointId", "eu")) + .userIdentity(USER_ID), + "{\"bcpStatus\":{\"rotationStatus\":\"UNKNOWN\"}}", + 200); // GET global rotation status for eu-west-1 in eu endpoint tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/environment/prod/region/eu-west-1/global-rotation", GET) - .properties(Map.of("endpointId", "eu")) - .userIdentity(USER_ID), - "{\"bcpStatus\":{\"rotationStatus\":\"UNKNOWN\"}}", - 200); + .properties(Map.of("endpointId", "eu")) + .userIdentity(USER_ID), + "{\"bcpStatus\":{\"rotationStatus\":\"UNKNOWN\"}}", + 200); } @Test - public void testDeployWithApplicationPackage() { + void testDeployWithApplicationPackage() { // Setup addUserToHostedOperatorRole(HostedAthenzIdentities.from(HOSTED_VESPA_OPERATOR)); deploymentTester.controllerTester().upgradeController(new Version("6.2")); @@ -1071,22 +1071,22 @@ public class ApplicationApiTest extends ControllerContainerTest { // POST (deploy) a system application with an application package MultiPartStreamer noAppEntity = createApplicationDeployData(Optional.empty()); tester.assertResponse(request("/application/v4/tenant/hosted-vespa/application/routing/environment/prod/region/us-central-1/instance/default/deploy", POST) - .data(noAppEntity) - .userIdentity(HOSTED_VESPA_OPERATOR), - "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Deployment of system applications during a system upgrade is not allowed\"}", - 400); + .data(noAppEntity) + .userIdentity(HOSTED_VESPA_OPERATOR), + "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Deployment of system applications during a system upgrade is not allowed\"}", + 400); deploymentTester.controllerTester() - .upgradeSystem(deploymentTester.controller().readVersionStatus().controllerVersion().get() - .versionNumber()); + .upgradeSystem(deploymentTester.controller().readVersionStatus().controllerVersion().get() + .versionNumber()); tester.assertResponse(request("/application/v4/tenant/hosted-vespa/application/routing/environment/prod/region/us-central-1/instance/default/deploy", POST) - .data(noAppEntity) - .userIdentity(HOSTED_VESPA_OPERATOR), - new File("deploy-result.json")); + .data(noAppEntity) + .userIdentity(HOSTED_VESPA_OPERATOR), + new File("deploy-result.json")); } @Test - public void testRemovingAllDeployments() { + void testRemovingAllDeployments() { createAthenzDomainWithAdmin(ATHENZ_TENANT_DOMAIN, USER_ID); ApplicationPackage applicationPackage = new ApplicationPackageBuilder() .instances("instance1") @@ -1116,100 +1116,100 @@ public class ApplicationApiTest extends ControllerContainerTest { } @Test - public void testErrorResponses() { + void testErrorResponses() { createAthenzDomainWithAdmin(ATHENZ_TENANT_DOMAIN, USER_ID); // PUT (update) non-existing tenant returns 403 as tenant access cannot be determined when the tenant does not exist tester.assertResponse(request("/application/v4/tenant/tenant1", PUT) - .userIdentity(USER_ID) - .oAuthCredentials(OKTA_CREDENTIALS) - .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}"), - accessDenied, - 403); + .userIdentity(USER_ID) + .oAuthCredentials(OKTA_CREDENTIALS) + .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}"), + accessDenied, + 403); // GET non-existing tenant tester.assertResponse(request("/application/v4/tenant/tenant1", GET) - .userIdentity(USER_ID), - "{\"error-code\":\"NOT_FOUND\",\"message\":\"Tenant 'tenant1' does not exist\"}", - 404); + .userIdentity(USER_ID), + "{\"error-code\":\"NOT_FOUND\",\"message\":\"Tenant 'tenant1' does not exist\"}", + 404); // GET non-existing tenant's applications tester.assertResponse(request("/application/v4/tenant/tenant1/application", GET) - .userIdentity(USER_ID), - "{\"error-code\":\"NOT_FOUND\",\"message\":\"Tenant 'tenant1' does not exist\"}", - 404); + .userIdentity(USER_ID), + "{\"error-code\":\"NOT_FOUND\",\"message\":\"Tenant 'tenant1' does not exist\"}", + 404); // GET non-existing application tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1", GET) - .userIdentity(USER_ID), - "{\"error-code\":\"NOT_FOUND\",\"message\":\"tenant1.application1 not found\"}", - 404); + .userIdentity(USER_ID), + "{\"error-code\":\"NOT_FOUND\",\"message\":\"tenant1.application1 not found\"}", + 404); // GET non-existing deployment tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/us-east/instance/default", GET) - .userIdentity(USER_ID), - "{\"error-code\":\"NOT_FOUND\",\"message\":\"tenant1.application1 not found\"}", - 404); + .userIdentity(USER_ID), + "{\"error-code\":\"NOT_FOUND\",\"message\":\"tenant1.application1 not found\"}", + 404); // POST (add) a tenant tester.assertResponse(request("/application/v4/tenant/tenant1", POST) - .userIdentity(USER_ID) - .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}") - .oAuthCredentials(OKTA_CREDENTIALS), - new File("tenant-without-applications.json")); + .userIdentity(USER_ID) + .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}") + .oAuthCredentials(OKTA_CREDENTIALS), + new File("tenant-without-applications.json")); // POST (add) another tenant under the same domain tester.assertResponse(request("/application/v4/tenant/tenant2", POST) - .userIdentity(USER_ID) - .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}") - .oAuthCredentials(OKTA_CREDENTIALS), - "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Could not create tenant 'tenant2': The Athens domain 'domain1' is already connected to tenant 'tenant1'\"}", - 400); + .userIdentity(USER_ID) + .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}") + .oAuthCredentials(OKTA_CREDENTIALS), + "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Could not create tenant 'tenant2': The Athens domain 'domain1' is already connected to tenant 'tenant1'\"}", + 400); // Add the same tenant again tester.assertResponse(request("/application/v4/tenant/tenant1", POST) - .userIdentity(USER_ID) - .oAuthCredentials(OKTA_CREDENTIALS) - .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}"), - "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Tenant 'tenant1' already exists\"}", - 400); + .userIdentity(USER_ID) + .oAuthCredentials(OKTA_CREDENTIALS) + .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}"), + "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Tenant 'tenant1' already exists\"}", + 400); // POST (add) an Athenz tenant with underscore in name tester.assertResponse(request("/application/v4/tenant/my_tenant_2", POST) - .userIdentity(USER_ID) - .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}") - .oAuthCredentials(OKTA_CREDENTIALS), - "{\"error-code\":\"BAD_REQUEST\",\"message\":\"New tenant or application names must start with a letter, may contain no more than 20 characters, and may only contain lowercase letters, digits or dashes, but no double-dashes.\"}", - 400); + .userIdentity(USER_ID) + .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}") + .oAuthCredentials(OKTA_CREDENTIALS), + "{\"error-code\":\"BAD_REQUEST\",\"message\":\"New tenant or application names must start with a letter, may contain no more than 20 characters, and may only contain lowercase letters, digits or dashes, but no double-dashes.\"}", + 400); // POST (add) an Athenz tenant with a reserved name tester.assertResponse(request("/application/v4/tenant/hosted-vespa", POST) - .userIdentity(USER_ID) - .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}") - .oAuthCredentials(OKTA_CREDENTIALS), - "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Tenant 'hosted-vespa' already exists\"}", - 400); + .userIdentity(USER_ID) + .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}") + .oAuthCredentials(OKTA_CREDENTIALS), + "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Tenant 'hosted-vespa' already exists\"}", + 400); // POST (create) an (empty) application tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1", POST) - .userIdentity(USER_ID) - .oAuthCredentials(OKTA_CREDENTIALS), - new File("instance-reference.json")); + .userIdentity(USER_ID) + .oAuthCredentials(OKTA_CREDENTIALS), + new File("instance-reference.json")); // Create the same application again tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1", POST) - .oAuthCredentials(OKTA_CREDENTIALS) - .userIdentity(USER_ID), - "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Could not create 'tenant1.application1.instance1': Instance already exists\"}", - 400); + .oAuthCredentials(OKTA_CREDENTIALS) + .userIdentity(USER_ID), + "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Could not create 'tenant1.application1.instance1': Instance already exists\"}", + 400); ConfigServerMock configServer = tester.serviceRegistry().configServerMock(); configServer.throwOnNextPrepare(new ConfigServerException(ConfigServerException.ErrorCode.INVALID_APPLICATION_PACKAGE, "Failed to prepare application", "Invalid application package")); // 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); + "{\"error-code\":\"NOT_FOUND\",\"message\":\"no application package has been submitted for tenant1.application1\"}", + 404); // GET non-existent application package of specific build addScrewdriverUserToDeployRole(SCREWDRIVER_ID, ATHENZ_TENANT_DOMAIN, ApplicationName.from("application1")); @@ -1218,63 +1218,63 @@ public class ApplicationApiTest extends ControllerContainerTest { .data(createApplicationSubmissionData(applicationPackageInstance1, 1000)), "{\"message\":\"application build 1, source revision of repository 'repository1', branch 'master' with commit 'commit1', by a@b, built against 6.1 at 1970-01-01T00:00:01Z\"}"); tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/package", GET) - .properties(Map.of("build", "42")) - .userIdentity(HOSTED_VESPA_OPERATOR), - "{\"error-code\":\"NOT_FOUND\",\"message\":\"No build 42 found for tenant1.application1\"}", - 404); + .properties(Map.of("build", "42")) + .userIdentity(HOSTED_VESPA_OPERATOR), + "{\"error-code\":\"NOT_FOUND\",\"message\":\"No build 42 found for tenant1.application1\"}", + 404); tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/deployment", DELETE).userIdentity(USER_ID).oAuthCredentials(OKTA_CREDENTIALS), "{\"message\":\"All deployments removed\"}"); // GET non-existent application package of invalid build tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/package", GET) - .properties(Map.of("build", "foobar")) - .userIdentity(HOSTED_VESPA_OPERATOR), - "{\"error-code\":\"BAD_REQUEST\",\"message\":\"invalid value for request parameter 'build': For input string: \\\"foobar\\\"\"}", - 400); - + .properties(Map.of("build", "foobar")) + .userIdentity(HOSTED_VESPA_OPERATOR), + "{\"error-code\":\"BAD_REQUEST\",\"message\":\"invalid value for request parameter 'build': For input string: \\\"foobar\\\"\"}", + 400); + // POST (deploy) an application to legacy deploy path MultiPartStreamer entity = createApplicationDeployData(applicationPackageInstance1); tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/dev/region/us-east-1/instance/instance1/deploy", POST) - .data(entity) - .userIdentity(USER_ID), - "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Deployment of tenant1.application1.instance1 is not supported through this API\"}", 400); + .data(entity) + .userIdentity(USER_ID), + "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Deployment of tenant1.application1.instance1 is not supported through this API\"}", 400); // DELETE tenant which has an application tester.assertResponse(request("/application/v4/tenant/tenant1", DELETE) - .userIdentity(USER_ID) - .oAuthCredentials(OKTA_CREDENTIALS), - "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Could not delete tenant 'tenant1': This tenant has active applications\"}", - 400); + .userIdentity(USER_ID) + .oAuthCredentials(OKTA_CREDENTIALS), + "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Could not delete tenant 'tenant1': This tenant has active applications\"}", + 400); // DELETE application tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1", DELETE) - .userIdentity(USER_ID) - .oAuthCredentials(OKTA_CREDENTIALS), - "{\"message\":\"Deleted instance tenant1.application1.instance1\"}"); + .userIdentity(USER_ID) + .oAuthCredentials(OKTA_CREDENTIALS), + "{\"message\":\"Deleted instance tenant1.application1.instance1\"}"); // DELETE application again - should produce 404 tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1", DELETE) - .oAuthCredentials(OKTA_CREDENTIALS) - .userIdentity(USER_ID), - "{\"error-code\":\"NOT_FOUND\",\"message\":\"Could not delete instance 'tenant1.application1.instance1': Instance not found\"}", - 404); + .oAuthCredentials(OKTA_CREDENTIALS) + .userIdentity(USER_ID), + "{\"error-code\":\"NOT_FOUND\",\"message\":\"Could not delete instance 'tenant1.application1.instance1': Instance not found\"}", + 404); // DELETE and forget an application as non-operator tester.assertResponse(request("/application/v4/tenant/tenant1", DELETE).properties(Map.of("forget", "true")) - .userIdentity(USER_ID) - .oAuthCredentials(OKTA_CREDENTIALS), - "{\"error-code\":\"FORBIDDEN\",\"message\":\"Only operators can forget a tenant\"}", - 403); + .userIdentity(USER_ID) + .oAuthCredentials(OKTA_CREDENTIALS), + "{\"error-code\":\"FORBIDDEN\",\"message\":\"Only operators can forget a tenant\"}", + 403); // DELETE tenant tester.assertResponse(request("/application/v4/tenant/tenant1", DELETE) - .userIdentity(USER_ID) - .oAuthCredentials(OKTA_CREDENTIALS), - "{\"message\":\"Deleted tenant tenant1\"}"); + .userIdentity(USER_ID) + .oAuthCredentials(OKTA_CREDENTIALS), + "{\"message\":\"Deleted tenant tenant1\"}"); // DELETE tenant again returns 403 as tenant access cannot be determined when the tenant does not exist tester.assertResponse(request("/application/v4/tenant/tenant1", DELETE) - .userIdentity(USER_ID), - accessDenied, - 403); + .userIdentity(USER_ID), + accessDenied, + 403); // Create legacy tenant name containing underscores tester.controller().curator().writeTenant(new AthenzTenant(TenantName.from("my_tenant"), ATHENZ_TENANT_DOMAIN, @@ -1282,116 +1282,116 @@ public class ApplicationApiTest extends ControllerContainerTest { // POST (add) a Athenz tenant with dashes duplicates existing one with underscores tester.assertResponse(request("/application/v4/tenant/my-tenant", POST) - .userIdentity(USER_ID) - .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}") - .oAuthCredentials(OKTA_CREDENTIALS), - "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Tenant 'my-tenant' already exists\"}", - 400); + .userIdentity(USER_ID) + .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}") + .oAuthCredentials(OKTA_CREDENTIALS), + "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Tenant 'my-tenant' already exists\"}", + 400); } @Test - public void testAuthorization() { + void testAuthorization() { UserId authorizedUser = USER_ID; UserId unauthorizedUser = new UserId("othertenant"); - + // Mutation without an user is disallowed tester.assertResponse(request("/application/v4/tenant/tenant1", POST) - .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}"), - "{\n \"message\" : \"Not authenticated\"\n}", - 401); + .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}"), + "{\n \"message\" : \"Not authenticated\"\n}", + 401); // ... but read methods are allowed for authenticated user tester.assertResponse(request("/application/v4/tenant/", GET) - .userIdentity(USER_ID) - .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}"), - "[]", - 200); + .userIdentity(USER_ID) + .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}"), + "[]", + 200); createAthenzDomainWithAdmin(ATHENZ_TENANT_DOMAIN, USER_ID); // Creating a tenant for an Athens domain the user is not admin for is disallowed tester.assertResponse(request("/application/v4/tenant/tenant1", POST) - .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}") - .oAuthCredentials(OKTA_CREDENTIALS) - .userIdentity(unauthorizedUser), - "{\"error-code\":\"FORBIDDEN\",\"message\":\"The user 'user.othertenant' is not admin in Athenz domain 'domain1'\"}", - 403); + .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}") + .oAuthCredentials(OKTA_CREDENTIALS) + .userIdentity(unauthorizedUser), + "{\"error-code\":\"FORBIDDEN\",\"message\":\"The user 'user.othertenant' is not admin in Athenz domain 'domain1'\"}", + 403); // (Create it with the right tenant id) tester.assertResponse(request("/application/v4/tenant/tenant1", POST) - .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}") - .userIdentity(authorizedUser) - .oAuthCredentials(OKTA_CREDENTIALS), - new File("tenant-without-applications.json"), - 200); + .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}") + .userIdentity(authorizedUser) + .oAuthCredentials(OKTA_CREDENTIALS), + new File("tenant-without-applications.json"), + 200); // Creating an application for an Athens domain the user is not admin for is disallowed tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1", POST) - .userIdentity(unauthorizedUser) - .oAuthCredentials(OKTA_CREDENTIALS), - accessDenied, - 403); + .userIdentity(unauthorizedUser) + .oAuthCredentials(OKTA_CREDENTIALS), + accessDenied, + 403); // (Create it with the right tenant id) tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1", POST) - .userIdentity(authorizedUser) - .oAuthCredentials(OKTA_CREDENTIALS), - new File("instance-reference.json"), - 200); + .userIdentity(authorizedUser) + .oAuthCredentials(OKTA_CREDENTIALS), + new File("instance-reference.json"), + 200); // Deploy to an authorized zone by a user tenant is disallowed MultiPartStreamer entity = createApplicationDeployData(applicationPackageDefault); tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/us-west-1/instance/default/deploy", POST) - .data(entity) - .userIdentity(USER_ID), - accessDenied, - 403); + .data(entity) + .userIdentity(USER_ID), + accessDenied, + 403); // Deleting an application for an Athens domain the user is not admin for is disallowed tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1", DELETE) - .userIdentity(unauthorizedUser), - accessDenied, - 403); + .userIdentity(unauthorizedUser), + accessDenied, + 403); // Create another instance under the application tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/default", POST) - .userIdentity(authorizedUser) - .oAuthCredentials(OKTA_CREDENTIALS), - new File("instance-reference-default.json"), - 200); + .userIdentity(authorizedUser) + .oAuthCredentials(OKTA_CREDENTIALS), + new File("instance-reference-default.json"), + 200); // (Deleting the application with the right tenant id) tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1", DELETE) - .userIdentity(authorizedUser) - .oAuthCredentials(OKTA_CREDENTIALS), - "{\"message\":\"Deleted application tenant1.application1\"}", - 200); + .userIdentity(authorizedUser) + .oAuthCredentials(OKTA_CREDENTIALS), + "{\"message\":\"Deleted application tenant1.application1\"}", + 200); // Updating a tenant for an Athens domain the user is not admin for is disallowed tester.assertResponse(request("/application/v4/tenant/tenant1", PUT) - .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}") - .userIdentity(unauthorizedUser), - accessDenied, - 403); - + .data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}") + .userIdentity(unauthorizedUser), + accessDenied, + 403); + // Change Athens domain createAthenzDomainWithAdmin(new AthenzDomain("domain2"), USER_ID); tester.assertResponse(request("/application/v4/tenant/tenant1", PUT) - .data("{\"athensDomain\":\"domain2\", \"property\":\"property1\"}") - .userIdentity(authorizedUser) - .oAuthCredentials(OKTA_CREDENTIALS), - new File("tenant1.json"), - 200); + .data("{\"athensDomain\":\"domain2\", \"property\":\"property1\"}") + .userIdentity(authorizedUser) + .oAuthCredentials(OKTA_CREDENTIALS), + new File("tenant1.json"), + 200); // Deleting a tenant for an Athens domain the user is not admin for is disallowed tester.assertResponse(request("/application/v4/tenant/tenant1", DELETE) - .userIdentity(unauthorizedUser), - accessDenied, - 403); + .userIdentity(unauthorizedUser), + accessDenied, + 403); } @Test - public void athenz_service_must_be_allowed_to_launch_and_be_under_tenant_domain() { + void athenz_service_must_be_allowed_to_launch_and_be_under_tenant_domain() { ApplicationPackage applicationPackage = new ApplicationPackageBuilder() .upgradePolicy("default") .athenzIdentity(com.yahoo.config.provision.AthenzDomain.from("another.domain"), com.yahoo.config.provision.AthenzService.from("service")) @@ -1407,10 +1407,10 @@ public class ApplicationApiTest extends ControllerContainerTest { allowLaunchOfService(new com.yahoo.vespa.athenz.api.AthenzService(new AthenzDomain("another.domain"), "service")); // Submit a package with a service under a different Athenz domain from that of the tenant tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/submit/", POST) - .data(createApplicationSubmissionData(applicationPackage, 123)) - .screwdriverIdentity(screwdriverId), - "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Athenz domain in deployment.xml: [another.domain] must match tenant domain: [domain1]\"}", - 400); + .data(createApplicationSubmissionData(applicationPackage, 123)) + .screwdriverIdentity(screwdriverId), + "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Athenz domain in deployment.xml: [another.domain] must match tenant domain: [domain1]\"}", + 400); // Set the correct domain in the application package, but do not yet allow Vespa to launch the service. applicationPackage = new ApplicationPackageBuilder() @@ -1420,22 +1420,22 @@ public class ApplicationApiTest extends ControllerContainerTest { .build(); tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/submit", POST) - .data(createApplicationSubmissionData(applicationPackage, 123)) - .screwdriverIdentity(screwdriverId), - "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Not allowed to launch Athenz service domain1.service\"}", - 400); + .data(createApplicationSubmissionData(applicationPackage, 123)) + .screwdriverIdentity(screwdriverId), + "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Not allowed to launch Athenz service domain1.service\"}", + 400); // Allow Vespa to launch the Athenz service. allowLaunchOfService(new com.yahoo.vespa.athenz.api.AthenzService(ATHENZ_TENANT_DOMAIN, "service")); tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/submit/", POST) - .data(createApplicationSubmissionData(applicationPackage, 123)) - .screwdriverIdentity(screwdriverId), - "{\"message\":\"application build 1, source revision of repository 'repository1', branch 'master' with commit 'commit1', by a@b, built against 6.1 at 1970-01-01T00:00:01Z\"}"); + .data(createApplicationSubmissionData(applicationPackage, 123)) + .screwdriverIdentity(screwdriverId), + "{\"message\":\"application build 1, source revision of repository 'repository1', branch 'master' with commit 'commit1', by a@b, built against 6.1 at 1970-01-01T00:00:01Z\"}"); } @Test - public void personal_deployment_with_athenz_service_requires_user_is_admin() { + void personal_deployment_with_athenz_service_requires_user_is_admin() { // Setup UserId tenantAdmin = new UserId("tenant-admin"); UserId userId = new UserId("new-user"); @@ -1450,26 +1450,26 @@ public class ApplicationApiTest extends ControllerContainerTest { MultiPartStreamer entity = createApplicationDeployData(applicationPackage); // POST (deploy) an application to dev through a deployment job, with user instance and a proper tenant tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/new-user/deploy/dev-us-east-1", POST) - .data(entity) - .userIdentity(userId), - accessDenied, - 403); + .data(entity) + .userIdentity(userId), + accessDenied, + 403); // Add "new-user" to the admin role, to allow service launches. tester.athenzClientFactory().getSetup() .domains.get(ATHENZ_TENANT_DOMAIN) - .admin(HostedAthenzIdentities.from(userId)); + .admin(HostedAthenzIdentities.from(userId)); // POST (deploy) an application to dev through a deployment job tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/new-user/deploy/dev-us-east-1", POST) - .data(entity) - .userIdentity(userId), - "{\"message\":\"Deployment started in run 1 of dev-us-east-1 for tenant1.application1.new-user. This may take about 15 minutes the first time.\",\"run\":1}"); + .data(entity) + .userIdentity(userId), + "{\"message\":\"Deployment started in run 1 of dev-us-east-1 for tenant1.application1.new-user. This may take about 15 minutes the first time.\",\"run\":1}"); } - @Test // Deploy to sandbox tenant launching a service from another domain. - public void developers_can_deploy_when_privileged() { + @Test + void developers_can_deploy_when_privileged() { // Create an athenz domain where the developer is not yet authorized UserId tenantAdmin = new UserId("tenant-admin"); createAthenzDomainWithAdmin(ATHENZ_TENANT_DOMAIN, tenantAdmin); @@ -1503,7 +1503,7 @@ public class ApplicationApiTest extends ControllerContainerTest { // Allow developer launch privilege to domain1.service. Deployment now completes. AthenzDbMock.Domain domainMock = tester.athenzClientFactory().getSetup().getOrCreateDomain(ATHENZ_TENANT_DOMAIN); - domainMock.withPolicy("launch-" +developer.id(), "user." + developer.id(), "launch", "service.service"); + domainMock.withPolicy("launch-" + developer.id(), "user." + developer.id(), "launch", "service.service"); tester.assertResponse(request("/application/v4/tenant/sandbox/application/myapp/instance/default/deploy/dev-us-east-1", POST) @@ -1526,25 +1526,25 @@ public class ApplicationApiTest extends ControllerContainerTest { // POST (deploy) an application package as content type application/zip — not multipart tester.assertResponse(request("/application/v4/tenant/sandbox/application/myapp/instance/default/deploy/dev-us-east-1", POST) - .data(applicationPackageInstance1.zippedContent()) - .contentType("application/zip") - .userIdentity(developer2), - "{\"message\":\"Deployment started in run 3 of dev-us-east-1 for sandbox.myapp. This may take about 15 minutes the first time.\",\"run\":3}"); + .data(applicationPackageInstance1.zippedContent()) + .contentType("application/zip") + .userIdentity(developer2), + "{\"message\":\"Deployment started in run 3 of dev-us-east-1 for sandbox.myapp. This may take about 15 minutes the first time.\",\"run\":3}"); // POST (deploy) an application package not as content type application/zip — not multipart — is disallowed tester.assertResponse(request("/application/v4/tenant/sandbox/application/myapp/instance/default/deploy/dev-us-east-1", POST) - .data(applicationPackageInstance1.zippedContent()) - .contentType("application/gzip") - .userIdentity(developer2), - "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Expected a multipart or application/zip message, but got Content-Type: application/gzip\"}", 400); + .data(applicationPackageInstance1.zippedContent()) + .contentType("application/gzip") + .userIdentity(developer2), + "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Expected a multipart or application/zip message, but got Content-Type: application/gzip\"}", 400); } @Test - public void applicationWithRoutingPolicy() { + void applicationWithRoutingPolicy() { var app = deploymentTester.newDeploymentContext(createTenantAndApplication()); var zone = ZoneId.from(Environment.prod, RegionName.from("us-west-1")); deploymentTester.controllerTester().zoneRegistry().setRoutingMethod(ZoneApiMock.from(zone), - RoutingMethod.exclusive); + RoutingMethod.exclusive); ApplicationPackage applicationPackage = new ApplicationPackageBuilder() .athenzIdentity(com.yahoo.config.provision.AthenzDomain.from("domain"), AthenzService.from("service")) .instances("instance1") @@ -1555,22 +1555,22 @@ public class ApplicationApiTest extends ControllerContainerTest { // GET application tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1", GET) - .userIdentity(USER_ID), - new File("instance-with-routing-policy.json")); + .userIdentity(USER_ID), + new File("instance-with-routing-policy.json")); // GET deployment tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/us-west-1/instance/instance1", GET) - .userIdentity(USER_ID), - new File("deployment-with-routing-policy.json")); + .userIdentity(USER_ID), + new File("deployment-with-routing-policy.json")); // GET deployment tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/us-west-1/instance/instance1", GET) - .userIdentity(USER_ID), - new File("deployment-without-shared-endpoints.json")); + .userIdentity(USER_ID), + new File("deployment-without-shared-endpoints.json")); } @Test - public void support_access() { + void support_access() { var app = deploymentTester.newDeploymentContext(createTenantAndApplication()); var zone = ZoneId.from(Environment.prod, RegionName.from("us-west-1")); deploymentTester.controllerTester().zoneRegistry().setRoutingMethod(ZoneApiMock.from(zone), RoutingMethod.exclusive); @@ -1601,15 +1601,15 @@ public class ApplicationApiTest extends ControllerContainerTest { // Grant access to support user X509Certificate support_cert = grantCertificate(now, now.plusSeconds(3600)); - String grantPayload= "{\n" + - " \"applicationId\": \"tenant1:application1:instance1\",\n" + - " \"zone\": \"prod.us-west-1\",\n" + - " \"certificate\":\""+X509CertificateUtils.toPem(support_cert)+ "\"\n" + - "}"; - tester.assertResponse(request("/controller/v1/access/grants/"+HOSTED_VESPA_OPERATOR.id(), POST) - .data(grantPayload) - .userIdentity(HOSTED_VESPA_OPERATOR), - "{\"message\":\"Operator user.johnoperator granted access and job production-us-west-1 triggered\"}"); + String grantPayload = "{\n" + + " \"applicationId\": \"tenant1:application1:instance1\",\n" + + " \"zone\": \"prod.us-west-1\",\n" + + " \"certificate\":\"" + X509CertificateUtils.toPem(support_cert) + "\"\n" + + "}"; + tester.assertResponse(request("/controller/v1/access/grants/" + HOSTED_VESPA_OPERATOR.id(), POST) + .data(grantPayload) + .userIdentity(HOSTED_VESPA_OPERATOR), + "{\"message\":\"Operator user.johnoperator granted access and job production-us-west-1 triggered\"}"); // GET shows grant String grantResponse = allowedResponse.replaceAll("\"grants\":\\[]", @@ -1631,7 +1631,7 @@ public class ApplicationApiTest extends ControllerContainerTest { // DELETE removes access String disallowedResponse = grantResponse .replaceAll("ALLOWED\".*?}", "NOT_ALLOWED\"}") - .replace("history\":[", "history\":[{\"state\":\"disallowed\",\"at\":\""+ serializeInstant(now) +"\",\"by\":\"user.myuser\"},"); + .replace("history\":[", "history\":[{\"state\":\"disallowed\",\"at\":\"" + serializeInstant(now) + "\",\"by\":\"user.myuser\"},"); tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/environment/prod/region/us-west-1/access/support", DELETE) .userIdentity(USER_ID), disallowedResponse, 200 @@ -1646,7 +1646,7 @@ public class ApplicationApiTest extends ControllerContainerTest { } @Test - public void create_application_on_deploy() { + void create_application_on_deploy() { // Setup createAthenzDomainWithAdmin(ATHENZ_TENANT_DOMAIN, USER_ID); addUserToHostedOperatorRole(HostedAthenzIdentities.from(HOSTED_VESPA_OPERATOR)); @@ -1668,7 +1668,7 @@ public class ApplicationApiTest extends ControllerContainerTest { tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/instance/instance1/deploy/dev-us-east-1/", POST) .data(entity) .oAuthCredentials(OKTA_CREDENTIALS) - + .userIdentity(USER_ID), "{\"message\":\"Deployment started in run 1 of dev-us-east-1 for tenant1.application1.instance1. This may take about 15 minutes the first time.\",\"run\":1}"); |