diff options
Diffstat (limited to 'controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi')
56 files changed, 637 insertions, 463 deletions
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ApplicationRequestToDiscFilterRequestWrapper.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ApplicationRequestToDiscFilterRequestWrapper.java index 52fd7393c4d..54a592ca070 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ApplicationRequestToDiscFilterRequestWrapper.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ApplicationRequestToDiscFilterRequestWrapper.java @@ -1,4 +1,4 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.restapi; import com.yahoo.application.container.handler.Request; diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ContainerTester.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ContainerTester.java index 4194131e7fb..f2826bad5b5 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ContainerTester.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ContainerTester.java @@ -1,4 +1,4 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.restapi; import com.yahoo.application.container.JDisc; @@ -143,6 +143,13 @@ public class ContainerTester { assertResponse(() -> request, expectedResponse, expectedStatusCode); } + public void assertJsonResponse(Supplier<Request> request, String expectedResponse, int expectedStatusCode) { + assertResponse(request, + (response) -> assertEquals(SlimeUtils.toJson(SlimeUtils.jsonToSlimeOrThrow(expectedResponse).get(), false), + SlimeUtils.toJson(SlimeUtils.jsonToSlimeOrThrow(response.getBodyAsString()).get(), false)), + expectedStatusCode); + } + public void assertResponse(Supplier<Request> request, String expectedResponse, int expectedStatusCode) { assertResponse(request, (response) -> assertEquals(expectedResponse, new String(response.getBody(), UTF_8)), @@ -226,4 +233,4 @@ public class ContainerTester { public interface ConsumerThrowingException<T> { void accept(T t) throws Exception; } -}
\ No newline at end of file +} diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerCloudTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerCloudTest.java index 5fe44038d73..06c2a03d98a 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerCloudTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerCloudTest.java @@ -1,4 +1,4 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.restapi; import ai.vespa.hosted.api.MultiPartStreamer; diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerTest.java index 7522f42f91b..3ada598f4f8 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerTest.java @@ -1,4 +1,4 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.restapi; import com.yahoo.application.Networking; diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ResponseHandlerToApplicationResponseWrapper.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ResponseHandlerToApplicationResponseWrapper.java index d57920e8b3c..765da006deb 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ResponseHandlerToApplicationResponseWrapper.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ResponseHandlerToApplicationResponseWrapper.java @@ -1,4 +1,4 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.restapi; import com.yahoo.jdisc.Response; diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java index 3b74fea2b9c..32f0247b3bc 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java @@ -1,4 +1,4 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.restapi.application; import ai.vespa.hosted.api.MultiPartStreamer; @@ -6,14 +6,19 @@ import com.yahoo.component.Version; import com.yahoo.config.provision.ApplicationId; import com.yahoo.config.provision.ApplicationName; import com.yahoo.config.provision.CloudAccount; +import com.yahoo.config.provision.HostName; import com.yahoo.config.provision.InstanceName; import com.yahoo.config.provision.TenantName; import com.yahoo.restapi.RestApiException; +import com.yahoo.slime.Cursor; +import com.yahoo.slime.SlimeUtils; import com.yahoo.vespa.flags.InMemoryFlagSource; import com.yahoo.vespa.flags.PermanentFlags; import com.yahoo.vespa.hosted.controller.ControllerTester; import com.yahoo.vespa.hosted.controller.LockedTenant; import com.yahoo.vespa.hosted.controller.api.integration.billing.PlanId; +import com.yahoo.vespa.hosted.controller.api.integration.dataplanetoken.FingerPrint; +import com.yahoo.vespa.hosted.controller.api.integration.dataplanetoken.TokenId; import com.yahoo.vespa.hosted.controller.api.integration.deployment.ApplicationVersion; import com.yahoo.vespa.hosted.controller.api.integration.deployment.JobType; import com.yahoo.vespa.hosted.controller.api.integration.secrets.TenantSecretStore; @@ -35,14 +40,15 @@ import org.junit.jupiter.api.Test; import java.io.File; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; import static com.yahoo.application.container.handler.Request.Method.DELETE; import static com.yahoo.application.container.handler.Request.Method.GET; import static com.yahoo.application.container.handler.Request.Method.POST; import static com.yahoo.application.container.handler.Request.Method.PUT; -import static java.nio.charset.StandardCharsets.UTF_8; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -72,7 +78,7 @@ public class ApplicationApiCloudTest extends ControllerContainerCloudTest { void tenant_info_profile() { var request = request("/application/v4/tenant/scoober/info/profile", GET) .roles(Set.of(Role.reader(tenantName))); - tester.assertResponse(request, "{}", 200); + tester.assertResponse(request, "{\"contact\":{\"name\":\"\",\"email\":\"\",\"emailVerified\":false},\"tenant\":{\"company\":\"\",\"website\":\"\"}}", 200); var updateRequest = request("/application/v4/tenant/scoober/info/profile", PUT) .data("{\"contact\":{\"name\":\"Some Name\",\"email\":\"foo@example.com\"},\"tenant\":{\"company\":\"Scoober, Inc.\",\"website\":\"https://example.com/\"}}") @@ -92,34 +98,103 @@ public class ApplicationApiCloudTest extends ControllerContainerCloudTest { @Test void tenant_info_billing() { + var expectedResponse = """ + { + "contact": { + "name":"", + "email":"", + "emailVerified":false, + "phone":"" + }, + "taxId":"", + "purchaseOrder":"", + "invoiceEmail":"" + } + """; var request = request("/application/v4/tenant/scoober/info/billing", GET) .roles(Set.of(Role.reader(tenantName))); - tester.assertResponse(request, "{}", 200); - - var fullAddress = "{\"addressLines\":\"addressLines\",\"postalCodeOrZip\":\"postalCodeOrZip\",\"city\":\"city\",\"stateRegionProvince\":\"stateRegionProvince\",\"country\":\"country\"}"; - var fullBillingContact = "{\"contact\":{\"name\":\"name\",\"email\":\"foo@example\",\"phone\":\"phone\"},\"address\":" + fullAddress + "}"; - + tester.assertJsonResponse(request, expectedResponse, 200); + + var fullBillingContact = """ + { + "contact": { + "name":"name", + "email":"foo@example", + "phone":"phone" + }, + "taxId":"1234L", + "purchaseOrder":"PO9001", + "invoiceEmail":"billing@mycomp.any", + "address": { + "addressLines":"addressLines", + "postalCodeOrZip":"postalCodeOrZip", + "city":"city", + "stateRegionProvince":"stateRegionProvince", + "country":"country" + } + } + """; var updateRequest = request("/application/v4/tenant/scoober/info/billing", PUT) .data(fullBillingContact) .roles(Set.of(Role.administrator(tenantName))); tester.assertResponse(updateRequest, "{\"message\":\"Tenant info updated\"}", 200); - tester.assertResponse(request, "{\"contact\":{\"name\":\"name\",\"email\":\"foo@example\",\"phone\":\"phone\"},\"address\":{\"addressLines\":\"addressLines\",\"postalCodeOrZip\":\"postalCodeOrZip\",\"city\":\"city\",\"stateRegionProvince\":\"stateRegionProvince\",\"country\":\"country\"}}", 200); + expectedResponse = """ + { + "contact": { + "name":"name", + "email":"foo@example", + "emailVerified": false, + "phone":"phone" + }, + "taxId":"1234L", + "purchaseOrder":"PO9001", + "invoiceEmail":"billing@mycomp.any", + "address": { + "addressLines":"addressLines", + "postalCodeOrZip":"postalCodeOrZip", + "city":"city", + "stateRegionProvince":"stateRegionProvince", + "country":"country" + } + } + """; + tester.assertJsonResponse(request, expectedResponse, 200); } @Test void tenant_info_contacts() { var request = request("/application/v4/tenant/scoober/info/contacts", GET) .roles(Set.of(Role.reader(tenantName))); - tester.assertResponse(request, "{\"contacts\":[]}", 200); - - - var fullContacts = "{\"contacts\":[{\"audiences\":[\"tenant\"],\"email\":\"contact1@example.com\",\"emailVerified\":false},{\"audiences\":[\"notifications\"],\"email\":\"contact2@example.com\",\"emailVerified\":false},{\"audiences\":[\"tenant\",\"notifications\"],\"email\":\"contact3@example.com\",\"emailVerified\":false}]}"; + tester.assertResponse(request, "{\"contacts\":[{\"audiences\":[\"tenant\",\"notifications\"],\"email\":\"developer@scoober\",\"emailVerified\":true}]}", 200); + + + var fullContacts = """ + { + "contacts":[ + { + "audiences":["tenant"] + ,"email":"contact1@example.com", + "emailVerified":false + }, + { + "audiences":["notifications"], + "email":"contact2@example.com", + "emailVerified":false + }, + { + "audiences":["tenant","notifications"], + "email":"contact3@example.com", + "emailVerified":false + } + ] + } + """; var updateRequest = request("/application/v4/tenant/scoober/info/contacts", PUT) .data(fullContacts) .roles(Set.of(Role.administrator(tenantName))); tester.assertResponse(updateRequest, "{\"message\":\"Tenant info updated\"}", 200); - tester.assertResponse(request, fullContacts, 200); + tester.assertJsonResponse(request, fullContacts, 200); } @Test @@ -127,7 +202,7 @@ public class ApplicationApiCloudTest extends ControllerContainerCloudTest { var infoRequest = request("/application/v4/tenant/scoober/info", GET) .roles(Set.of(Role.reader(tenantName))); - tester.assertResponse(infoRequest, "{}", 200); + tester.assertResponse(infoRequest, "{\"name\":\"\",\"email\":\"\",\"website\":\"\",\"contactName\":\"\",\"contactEmail\":\"\",\"contactEmailVerified\":false,\"contacts\":[{\"audiences\":[\"tenant\",\"notifications\"],\"email\":\"developer@scoober\",\"emailVerified\":true}]}", 200); String partialInfo = "{\"contactName\":\"newName\", \"contactEmail\": \"foo@example.com\", \"billingContact\":{\"name\":\"billingName\"}}"; var postPartial = @@ -144,13 +219,79 @@ public class ApplicationApiCloudTest extends ControllerContainerCloudTest { tester.assertResponse(postPartialContacts, "{\"message\":\"Tenant info updated\"}", 200); // Read back the updated info - tester.assertResponse(infoRequest, "{\"name\":\"\",\"email\":\"\",\"website\":\"\",\"contactName\":\"newName\",\"contactEmail\":\"foo@example.com\",\"contactEmailVerified\":false,\"billingContact\":{\"name\":\"billingName\",\"email\":\"\",\"phone\":\"\"},\"contacts\":[{\"audiences\":[\"tenant\"],\"email\":\"contact1@example.com\",\"emailVerified\":false}]}", 200); - - String fullAddress = "{\"addressLines\":\"addressLines\",\"postalCodeOrZip\":\"postalCodeOrZip\",\"city\":\"city\",\"stateRegionProvince\":\"stateRegionProvince\",\"country\":\"country\"}"; - String fullBillingContact = "{\"name\":\"name\",\"email\":\"foo@example\",\"phone\":\"phone\",\"address\":" + fullAddress + "}"; - String fullContacts = "[{\"audiences\":[\"tenant\"],\"email\":\"contact1@example.com\",\"emailVerified\":false},{\"audiences\":[\"notifications\"],\"email\":\"contact2@example.com\",\"emailVerified\":false},{\"audiences\":[\"tenant\",\"notifications\"],\"email\":\"contact3@example.com\",\"emailVerified\":false}]"; - String fullInfo = "{\"name\":\"name\",\"email\":\"foo@example\",\"website\":\"https://yahoo.com\",\"contactName\":\"contactName\",\"contactEmail\":\"contact@example.com\",\"contactEmailVerified\":false,\"address\":" + fullAddress + ",\"billingContact\":" + fullBillingContact + ",\"contacts\":" + fullContacts + "}"; - + var expectedResponse = """ + { + "name":"", + "email":"", + "website":"", + "contactName":"newName", + "contactEmail":"foo@example.com", + "contactEmailVerified":false, + "billingContact": { + "name":"billingName", + "email":"","emailVerified":false, + "phone":"", + "taxId":"", + "purchaseOrder":"", + "invoiceEmail":"" + }, + "contacts": [ + {"audiences":["tenant"],"email":"contact1@example.com","emailVerified":false} + ] + } + """; + tester.assertJsonResponse(infoRequest, expectedResponse, 200); + + var fullInfo = """ + { + "name":"name", + "email":"foo@example", + "website":"https://yahoo.com", + "contactName":"contactName", + "contactEmail":"contact@example.com", + "contactEmailVerified":false, + "address": { + "addressLines":"addressLines", + "postalCodeOrZip":"postalCodeOrZip", + "city":"city", + "stateRegionProvince":"stateRegionProvince", + "country":"country" + }, + "billingContact": { + "name":"name", + "email":"foo@example", + "emailVerified":false, + "phone":"phone", + "taxId":"", + "purchaseOrder":"", + "invoiceEmail":"", + "address": { + "addressLines":"addressLines", + "postalCodeOrZip":"postalCodeOrZip", + "city":"city", + "stateRegionProvince":"stateRegionProvince", + "country":"country" + } + }, + "contacts": [ + { + "audiences":["tenant"], + "email":"contact1@example.com", + "emailVerified":false + }, + { + "audiences":["notifications"], + "email":"contact2@example.com", + "emailVerified":false + }, + { + "audiences":["tenant","notifications"] + ,"email":"contact3@example.com", + "emailVerified":false + } + ] + } + """; // Now set all fields var postFull = request("/application/v4/tenant/scoober/info", PUT) @@ -159,7 +300,7 @@ public class ApplicationApiCloudTest extends ControllerContainerCloudTest { tester.assertResponse(postFull, "{\"message\":\"Tenant info updated\"}", 200); // Now compare the updated info with the full info we sent - tester.assertResponse(infoRequest, fullInfo, 200); + tester.assertJsonResponse(infoRequest, fullInfo, 200); var invalidBody = "{\"mail\":\"contact1@example.com\", \"mailType\":\"blurb\"}"; var resendMailRequest = @@ -182,7 +323,7 @@ public class ApplicationApiCloudTest extends ControllerContainerCloudTest { var infoRequest = request("/application/v4/tenant/scoober/info", GET) .roles(Set.of(Role.reader(tenantName))); - tester.assertResponse(infoRequest, "{}", 200); + tester.assertResponse(infoRequest, "{\"name\":\"\",\"email\":\"\",\"website\":\"\",\"contactName\":\"\",\"contactEmail\":\"\",\"contactEmailVerified\":false,\"contacts\":[{\"audiences\":[\"tenant\",\"notifications\"],\"email\":\"developer@scoober\",\"emailVerified\":true}]}", 200); // name needs to be present and not blank var partialInfoMissingName = "{\"contactName\": \" \"}"; @@ -470,17 +611,83 @@ public class ApplicationApiCloudTest extends ControllerContainerCloudTest { .roles(Role.developer(tenantName)), "{\"tokens\":[]}", 200); - String regexGenerateToken = "\\{\"id\":\"myTokenId\",\"token\":\"vespa_cloud_.*\",\"fingerprint\":\".*\"}"; + AtomicReference<String> tokenValue = new AtomicReference<>(); + AtomicReference<String> fingerprint = new AtomicReference<>(); tester.assertResponse(request("/application/v4/tenant/scoober/token/myTokenId", POST).roles(Role.developer(tenantName)), - (response) -> assertTrue(new String(response.getBody(), UTF_8).matches(regexGenerateToken)), - 200); - - String regexListTokens = "\\{\"tokens\":\\[\\{\"id\":\"myTokenId\",\"versions\":\\[\\{\"fingerprint\":\".*\",\"created\":\".*\",\"author\":\"user@test\",\"expiration\":\".*\"}]}]}"; - tester.assertResponse(request("/application/v4/tenant/scoober/token", GET) - .roles(Role.developer(tenantName)), - (response) -> assertTrue(new String(response.getBody(), UTF_8).matches(regexListTokens)), + (response) -> { + Cursor root = SlimeUtils.jsonToSlimeOrThrow(response.getBody()).get(); + tokenValue.set(root.field("token").asString()); + fingerprint.set(root.field("fingerprint").asString()); + assertEquals(""" + { + "id": "myTokenId", + "token": "%s", + "fingerprint": "%s", + "expiration": "2020-10-13T12:26:40Z" + } + """.formatted(tokenValue.get(), fingerprint.get()), + SlimeUtils.toJson(root, false)); + }, 200); + tester.assertJsonResponse(request("/application/v4/tenant/scoober/token", GET) + .roles(Role.developer(tenantName)), + """ + { + "tokens": [ + { + "id": "myTokenId", + "lastUpdatedMillis": 1600000000000, + "versions": [ + { + "fingerprint": "%s", + "created": "2020-09-13T12:26:40Z", + "author": "user@test", + "expiration": "2020-10-13T12:26:40Z", + "state": "unused" + } + ] + } + ] + } + """.formatted(fingerprint.get()), + 200); + + ControllerTester wrapped = new ControllerTester(tester); + wrapped.upgradeSystem(Version.fromString("7.1")); + new DeploymentTester(wrapped).newDeploymentContext(ApplicationId.from(tenantName, applicationName, InstanceName.defaultName())) + .submit() + .deploy(); + wrapped.serviceRegistry().configServer().activeTokenFingerprints(null) + .put(HostName.of("host1"), Map.of(TokenId.of("myTokenId"), List.of(FingerPrint.of(fingerprint.get()), FingerPrint.of("ff:01")))); + + tester.assertJsonResponse(request("/application/v4/tenant/scoober/token", GET) + .roles(Role.developer(tenantName)), + """ + { + "tokens": [ + { + "id": "myTokenId", + "lastUpdatedMillis": 1600000000000, + "versions": [ + { + "fingerprint": "%s", + "created": "2020-09-13T12:26:40Z", + "author": "user@test", + "expiration": "2020-10-13T12:26:40Z", + "state": "active" + }, + { + "fingerprint": "ff:01", + "state": "revoking" + } + ] + } + ] + } + """.formatted(fingerprint.get()), + 200); + // Rejects invalid tokenIds on create tester.assertResponse(request("/application/v4/tenant/scoober/token/foo+bar", POST).roles(Role.developer(tenantName)), "{\"error-code\":\"BAD_REQUEST\",\"message\":\"tokenId must match '[A-Za-z][A-Za-z0-9_-]{0,59}', but got: 'foo bar'\"}", 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 6b377e2069b..66fb17410fd 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 @@ -1,4 +1,4 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.restapi.application; import ai.vespa.hosted.api.MultiPartStreamer; @@ -61,7 +61,6 @@ import com.yahoo.vespa.hosted.controller.integration.ConfigServerMock; import com.yahoo.vespa.hosted.controller.integration.NodeRepositoryMock; import com.yahoo.vespa.hosted.controller.integration.ZoneApiMock; import com.yahoo.vespa.hosted.controller.metric.ApplicationMetrics; -import com.yahoo.vespa.hosted.controller.notification.Notification; import com.yahoo.vespa.hosted.controller.notification.NotificationSource; import com.yahoo.vespa.hosted.controller.restapi.ContainerTester; import com.yahoo.vespa.hosted.controller.restapi.ControllerContainerTest; @@ -1979,15 +1978,11 @@ public class ApplicationApiTest extends ControllerContainerTest { } private void addNotifications(TenantName tenantName) { - tester.controller().notificationsDb().setNotification( + tester.controller().notificationsDb().setApplicationPackageNotification( NotificationSource.from(TenantAndApplicationId.from(tenantName.value(), "app1")), - Notification.Type.applicationPackage, - Notification.Level.warning, - "Something something deprecated..."); - tester.controller().notificationsDb().setNotification( - NotificationSource.from(new RunId(ApplicationId.from(tenantName.value(), "app2", "instance1"), DeploymentContext.systemTest, 12)), - Notification.Type.deployment, - Notification.Level.error, + List.of("Something something deprecated...")); + tester.controller().notificationsDb().setDeploymentNotification( + new RunId(ApplicationId.from(tenantName.value(), "app2", "instance1"), DeploymentContext.systemTest, 12), "Failed to deploy: Node allocation failure"); } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/CliApiHandlerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/CliApiHandlerTest.java index 4166ce8b81e..9c169213b58 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/CliApiHandlerTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/CliApiHandlerTest.java @@ -1,4 +1,4 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.restapi.application; import com.yahoo.vespa.hosted.controller.restapi.ContainerTester; diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/JobControllerApiHandlerHelperTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/JobControllerApiHandlerHelperTest.java index 905330c6daf..f9ba5850d2d 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/JobControllerApiHandlerHelperTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/JobControllerApiHandlerHelperTest.java @@ -1,4 +1,4 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.restapi.application; import com.yahoo.component.Version; diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/MultipartParserTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/MultipartParserTest.java index 37f4c19e27a..2a1caafe1ec 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/MultipartParserTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/MultipartParserTest.java @@ -1,4 +1,4 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.restapi.application; import com.yahoo.container.jdisc.HttpRequest; diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/notifications-tenant1-app2.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/notifications-tenant1-app2.json index 556440c40d5..6206e3b277a 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/notifications-tenant1-app2.json +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/notifications-tenant1-app2.json @@ -4,6 +4,7 @@ "at": 1600000000000, "level": "error", "type": "deployment", + "title": "[System test #12](https://console.tld/tenant/tenant1/application/app2/prod/instance/instance1/job/system-test/run/12) for application **app2.instance1** has failed", "messages": [ "Failed to deploy: Node allocation failure" ], diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/notifications-tenant1.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/notifications-tenant1.json index 1a731dfe4a9..78deea65008 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/notifications-tenant1.json +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/notifications-tenant1.json @@ -4,6 +4,7 @@ "at": 1600000000000, "level": "warning", "type": "applicationPackage", + "title": "Application package for [app1](https://console.tld/tenant/tenant1/application/app1/prod/instance) has a warning", "messages": [ "Something something deprecated..." ], @@ -13,6 +14,7 @@ "at": 1600000000000, "level": "error", "type": "deployment", + "title": "[System test #12](https://console.tld/tenant/tenant1/application/app2/prod/instance/instance1/job/system-test/run/12) for application **app2.instance1** has failed", "messages": [ "Failed to deploy: Node allocation failure" ], diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/overview-enclave.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/overview-enclave.json index ef9c8a608ab..1d2cd8eaabb 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/overview-enclave.json +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/responses/overview-enclave.json @@ -81,6 +81,9 @@ "commit": "commit1" } }, + "enclave": { + "cloudAccount": "aws:123456789012" + }, "steps": [ { "name": "deployTester", @@ -177,6 +180,9 @@ "commit": "commit1" } }, + "enclave": { + "cloudAccount": "aws:123456789012" + }, "steps": [ { "name": "deployTester", @@ -264,6 +270,9 @@ "commit": "commit1" } }, + "enclave": { + "cloudAccount": "aws:123456789012" + }, "steps": [ { "name": "deployReal", diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/athenz/AthenzApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/athenz/AthenzApiTest.java index 3a539987443..b7b8e0f8484 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/athenz/AthenzApiTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/athenz/AthenzApiTest.java @@ -1,4 +1,4 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.restapi.athenz; import com.yahoo.application.container.handler.Request; diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerTest.java deleted file mode 100644 index f247b0ed3b6..00000000000 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerTest.java +++ /dev/null @@ -1,236 +0,0 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.hosted.controller.restapi.billing; - -import com.yahoo.config.provision.SystemName; -import com.yahoo.config.provision.TenantName; -import com.yahoo.vespa.hosted.controller.api.integration.billing.Bill; -import com.yahoo.vespa.hosted.controller.api.integration.billing.CollectionMethod; -import com.yahoo.vespa.hosted.controller.api.integration.billing.MockBillingController; -import com.yahoo.vespa.hosted.controller.api.integration.billing.PlanId; -import com.yahoo.vespa.hosted.controller.api.role.Role; -import com.yahoo.vespa.hosted.controller.restapi.ContainerTester; -import com.yahoo.vespa.hosted.controller.restapi.ControllerContainerCloudTest; -import com.yahoo.vespa.hosted.controller.security.Auth0Credentials; -import com.yahoo.vespa.hosted.controller.security.CloudTenantSpec; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.io.File; -import java.math.BigDecimal; -import java.time.LocalDate; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.TreeMap; - -import static com.yahoo.application.container.handler.Request.Method.DELETE; -import static com.yahoo.application.container.handler.Request.Method.GET; -import static com.yahoo.application.container.handler.Request.Method.PATCH; -import static com.yahoo.application.container.handler.Request.Method.POST; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - -/** - * @author olaa - */ -public class BillingApiHandlerTest extends ControllerContainerCloudTest { - - private static final String responseFiles = "src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/responses/"; - private static final TenantName tenant = TenantName.from("tenant1"); - private static final TenantName tenant2 = TenantName.from("tenant2"); - private static final Set<Role> tenantRole = Set.of(Role.administrator(tenant)); - private static final Set<Role> financeAdmin = Set.of(Role.hostedAccountant()); - private MockBillingController billingController; - - private ContainerTester tester; - - @BeforeEach - public void setup() { - tester = new ContainerTester(container, responseFiles); - billingController = (MockBillingController) tester.serviceRegistry().billingController(); - } - - @Override - protected SystemName system() { - return SystemName.PublicCd; - } - - @Override - protected String variablePartXml() { - return " <component id='com.yahoo.vespa.hosted.controller.security.CloudAccessControlRequests'/>\n" + - " <component id='com.yahoo.vespa.hosted.controller.security.CloudAccessControl'/>\n" + - - " <handler id='com.yahoo.vespa.hosted.controller.restapi.billing.BillingApiHandler'>\n" + - " <binding>http://*/billing/v1/*</binding>\n" + - " </handler>\n" + - - " <http>\n" + - " <server id='default' port='8080' />\n" + - " <filtering>\n" + - " <request-chain id='default'>\n" + - " <filter id='com.yahoo.vespa.hosted.controller.restapi.filter.ControllerAuthorizationFilter'/>\n" + - " <binding>http://*/*</binding>\n" + - " </request-chain>\n" + - " </filtering>\n" + - " </http>\n"; - } - - @Test - void list_plans() { - var listPlansRequest = request("/billing/v1/plans", GET) - .roles(Role.hostedAccountant()); - tester.assertResponse(listPlansRequest, "{\"plans\":[{\"id\":\"trial\",\"name\":\"Free Trial - for testing purposes\"},{\"id\":\"paid\",\"name\":\"Paid Plan - for testing purposes\"},{\"id\":\"none\",\"name\":\"None Plan - for testing purposes\"}]}"); - } - - @Test - void response_list_bills() { - var bill = createBill(); - - billingController.addBill(tenant, bill, true); - billingController.addBill(tenant, bill, false); - billingController.setPlan(tenant, PlanId.from("some-plan"), true, false); - - var request = request("/billing/v1/tenant/tenant1/billing?until=2020-05-28").roles(tenantRole); - tester.assertResponse(request, new File("tenant-billing-view.json")); - - } - - @Test - void test_bill_creation() { - var bills = billingController.getBillsForTenant(tenant); - assertEquals(0, bills.size()); - - String requestBody = "{\"tenant\":\"tenant1\", \"startTime\":\"2020-04-20\", \"endTime\":\"2020-05-20\"}"; - var request = request("/billing/v1/invoice", POST) - .data(requestBody) - .roles(tenantRole); - - tester.assertResponse(request, accessDenied, 403); - request.roles(financeAdmin); - tester.assertResponse(request, new File("invoice-creation-response.json")); - - bills = billingController.getBillsForTenant(tenant); - assertEquals(1, bills.size()); - Bill bill = bills.get(0); - assertEquals("2020-04-20T00:00Z", bill.getStartTime().toString()); - assertEquals("2020-05-21T00:00Z", bill.getEndTime().toString()); - - assertEquals("2020-04-20", bill.getStartDate().toString()); - assertEquals("2020-05-20", bill.getEndDate().toString()); - } - - @Test - void adding_and_listing_line_item() { - - var requestBody = "{" + - "\"description\":\"some description\"," + - "\"amount\":\"123.45\" " + - "}"; - - var request = request("/billing/v1/invoice/tenant/tenant1/line-item", POST) - .data(requestBody) - .roles(financeAdmin); - - tester.assertResponse(request, "{\"message\":\"Added line item for tenant tenant1\"}"); - - var lineItems = billingController.getUnusedLineItems(tenant); - assertEquals(1, lineItems.size()); - Bill.LineItem lineItem = lineItems.get(0); - assertEquals("some description", lineItem.description()); - assertEquals(new BigDecimal("123.45"), lineItem.amount()); - - request = request("/billing/v1/invoice/tenant/tenant1/line-item") - .roles(financeAdmin); - - tester.assertResponse(request, new File("line-item-list.json")); - } - - @Test - void adding_new_status() { - billingController.addBill(tenant, createBill(), true); - - var requestBody = "{\"status\":\"DONE\"}"; - var request = request("/billing/v1/invoice/id-1/status", POST) - .data(requestBody) - .roles(financeAdmin); - tester.assertResponse(request, "{\"message\":\"Updated status of invoice id-1\"}"); - - var bill = billingController.getBillsForTenant(tenant).get(0); - assertEquals("DONE", bill.status()); - } - - @Test - void list_all_unbilled_items() { - tester.controller().tenants().create(new CloudTenantSpec(tenant, ""), new Auth0Credentials(() -> "foo", Set.of(Role.hostedOperator()))); - tester.controller().tenants().create(new CloudTenantSpec(tenant2, ""), new Auth0Credentials(() -> "foo", Set.of(Role.hostedOperator()))); - - var bill = createBill(); - billingController.setPlan(tenant, PlanId.from("some-plan"), true, false); - billingController.setPlan(tenant2, PlanId.from("some-plan"), true, false); - billingController.addBill(tenant, bill, false); - billingController.addLineItem(tenant, "support", new BigDecimal("42"), Optional.empty(), "Smith"); - billingController.addBill(tenant2, bill, false); - - var request = request("/billing/v1/billing?until=2020-05-28").roles(financeAdmin); - - tester.assertResponse(request, new File("billing-all-tenants.json")); - } - - @Test - void csv_export() { - var bill = createBill(); - billingController.addBill(tenant, bill, true); - var csvRequest = request("/billing/v1/invoice/export", GET).roles(financeAdmin); - tester.assertResponse(csvRequest.get(), new File("billing-all-invoices"), 200, false); - } - - @Test - void patch_collection_method() { - test_patch_collection_with_field_name("collectionMethod"); - test_patch_collection_with_field_name("collection"); - } - - private void test_patch_collection_with_field_name(String fieldName) { - var planRequest = request("/billing/v1/tenant/tenant1/collection", PATCH) - .data("{\"" + fieldName + "\": \"invoice\"}") - .roles(financeAdmin); - tester.assertResponse(planRequest, "Collection method updated to INVOICE"); - assertEquals(CollectionMethod.INVOICE, billingController.getCollectionMethod(tenant)); - - // Test that not event tenant administrators can do this - planRequest = request("/billing/v1/tenant/tenant1/collection", PATCH) - .data("{\"collectionMethod\": \"epay\"}") - .roles(tenantRole); - tester.assertResponse(planRequest, accessDenied, 403); - assertEquals(CollectionMethod.INVOICE, billingController.getCollectionMethod(tenant)); - } - - static Bill createBill() { - var start = LocalDate.of(2020, 5, 23).atStartOfDay(ZoneOffset.UTC); - var end = start.toLocalDate().plusDays(6).atStartOfDay(ZoneOffset.UTC); - var statusHistory = new Bill.StatusHistory(new TreeMap<>(Map.of(start, "OPEN"))); - return new Bill( - Bill.Id.of("id-1"), - TenantName.defaultName(), - statusHistory, - List.of(createLineItem(start)), - start, - end - ); - } - - static Bill.LineItem createLineItem(ZonedDateTime addedAt) { - return new Bill.LineItem( - "some-id", - "description", - new BigDecimal("123.00"), - "paid", - "Smith", - addedAt - ); - } - -} diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerV2Test.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerV2Test.java index 43271277ce9..46c1aa107f0 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerV2Test.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerV2Test.java @@ -1,10 +1,13 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.restapi.billing; import com.yahoo.application.container.handler.Request; import com.yahoo.config.provision.TenantName; import com.yahoo.test.ManualClock; +import com.yahoo.vespa.hosted.controller.api.integration.billing.Bill; +import com.yahoo.vespa.hosted.controller.api.integration.billing.BillStatus; import com.yahoo.vespa.hosted.controller.api.integration.billing.MockBillingController; +import com.yahoo.vespa.hosted.controller.api.integration.billing.StatusHistory; import com.yahoo.vespa.hosted.controller.api.role.Role; import com.yahoo.vespa.hosted.controller.restapi.ContainerTester; import com.yahoo.vespa.hosted.controller.restapi.ControllerContainerCloudTest; @@ -13,8 +16,15 @@ import com.yahoo.vespa.hosted.controller.security.CloudTenantSpec; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import java.math.BigDecimal; import java.time.Instant; +import java.time.LocalDate; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.util.List; +import java.util.Map; import java.util.Set; +import java.util.TreeMap; /** * @author ogronnesby @@ -29,11 +39,6 @@ public class BillingApiHandlerV2Test extends ControllerContainerCloudTest { private static final Set<Role> tenantAdmin = Set.of(Role.administrator(tenant)); private static final Set<Role> financeAdmin = Set.of(Role.hostedAccountant()); - private static final String ACCESS_DENIED = "{\n" + - " \"code\" : 403,\n" + - " \"message\" : \"Access denied\"\n" + - "}"; - private MockBillingController billingController; private ContainerTester tester; @@ -44,7 +49,7 @@ public class BillingApiHandlerV2Test extends ControllerContainerCloudTest { var clock = (ManualClock) tester.controller().serviceRegistry().clock(); clock.setInstant(Instant.parse("2021-04-13T00:00:00Z")); billingController = (MockBillingController) tester.serviceRegistry().billingController(); - billingController.addBill(tenant, BillingApiHandlerTest.createBill(), true); + billingController.addBill(tenant, createBill(), true); } @Override @@ -103,7 +108,7 @@ public class BillingApiHandlerV2Test extends ControllerContainerCloudTest { var singleRequest = request("/billing/v2/tenant/" + tenant + "/bill/id-1").roles(tenantReader); tester.assertResponse(singleRequest, """ - {"id":"id-1","from":"2020-05-23","to":"2020-05-28","total":"123.00","status":"OPEN","statusHistory":[{"at":"2020-05-23T00:00:00Z","status":"OPEN"}],"items":[{"id":"some-id","description":"description","amount":"123.00","plan":{"id":"paid","name":"Paid Plan - for testing purposes"},"majorVersion":0,"cpu":{},"memory":{},"disk":{}}]}"""); + {"id":"id-1","from":"2020-05-23","to":"2020-05-28","total":"123.00","status":"OPEN","statusHistory":[{"at":"2020-05-23T00:00:00Z","status":"OPEN"}],"items":[{"id":"some-id","description":"description","amount":"123.00","plan":{"id":"paid","name":"Paid Plan - for testing purposes"},"majorVersion":0,"cpu":{},"memory":{},"disk":{},"gpu":{}}]}"""); } @Test @@ -116,18 +121,27 @@ public class BillingApiHandlerV2Test extends ControllerContainerCloudTest { var accountantRequest = request("/billing/v2/accountant").roles(Role.hostedAccountant()); tester.assertResponse(accountantRequest, """ - {"tenants":[{"tenant":"tenant1","plan":{"id":"trial","name":"Free Trial - for testing purposes"},"quota":{"budget":-1.0},"collection":"AUTO","lastBill":null,"unbilled":"0.00"}]}"""); + {"tenants":[{"tenant":"tenant1","plan":{"id":"trial","name":"Free Trial - for testing purposes"},"quota":{"budget":-1.0},"collection":"AUTO","lastBill":"1970-01-01","unbilled":"0.00"}]}"""); + } + + @Test + void require_accountant_preview() { + var accountantRequest = request("/billing/v2/accountant/preview").roles(Role.hostedAccountant()); + billingController.uncommittedBills.put(tenant, createBill()); + + tester.assertResponse(accountantRequest, """ + {"tenants":[{"tenant":"tenant1","plan":{"id":"trial","name":"Free Trial - for testing purposes"},"quota":{"budget":-1.0},"collection":"AUTO","lastBill":"2020-05-23","unbilled":"123.00"}]}"""); } @Test void require_accountant_tenant_preview() { - var accountantRequest = request("/billing/v2/accountant/preview/tenant/tenant1").roles(Role.hostedAccountant()); + var accountantRequest = request("/billing/v2/accountant/tenant/tenant1/preview").roles(Role.hostedAccountant()); tester.assertResponse(accountantRequest, "{\"id\":\"empty\",\"from\":\"2021-04-13\",\"to\":\"2021-04-12\",\"total\":\"0.00\",\"status\":\"OPEN\",\"statusHistory\":[{\"at\":\"2021-04-13T00:00:00Z\",\"status\":\"OPEN\"}],\"items\":[]}"); } @Test void require_accountant_tenant_bill() { - var accountantRequest = request("/billing/v2/accountant/preview/tenant/tenant1", Request.Method.POST) + var accountantRequest = request("/billing/v2/accountant/tenant/tenant1/preview", Request.Method.POST) .roles(Role.hostedAccountant()) .data("{\"from\": \"2020-05-01\",\"to\": \"2020-06-01\"}"); tester.assertResponse(accountantRequest, "{\"message\":\"Created bill id-123\"}"); @@ -139,4 +153,126 @@ public class BillingApiHandlerV2Test extends ControllerContainerCloudTest { .roles(Role.hostedAccountant()); tester.assertResponse(accountantRequest, "{\"plans\":[{\"id\":\"trial\",\"name\":\"Free Trial - for testing purposes\"},{\"id\":\"paid\",\"name\":\"Paid Plan - for testing purposes\"},{\"id\":\"none\",\"name\":\"None Plan - for testing purposes\"}]}"); } + + @Test + void require_additional_items_empty() { + var accountantRequest = request("/billing/v2/accountant/tenant/tenant1/items") + .roles(Role.hostedAccountant()); + tester.assertResponse(accountantRequest, """ + {"items":[]}"""); + } + + @Test + void require_additional_items_with_content() { + { + var accountantRequest = request("/billing/v2/accountant/tenant/tenant1/items", Request.Method.POST) + .roles(Role.hostedAccountant()) + .data(""" + { + "description": "Additional support costs", + "amount": "123.45" + }"""); + tester.assertResponse(accountantRequest, """ + {"message":"Added line item for tenant tenant1"}"""); + } + + { + var accountantRequest = request("/billing/v2/accountant/tenant/tenant1/items") + .roles(Role.hostedAccountant()); + tester.assertResponse(accountantRequest, """ + {"items":[{"id":"line-item-id","description":"Additional support costs","amount":"123.45","plan":{"id":"paid","name":"Paid Plan - for testing purposes"},"majorVersion":0,"cpu":{},"memory":{},"disk":{},"gpu":{}}]}"""); + } + + { + var accountantRequest = request("/billing/v2/accountant/tenant/tenant1/item/line-item-id", Request.Method.DELETE) + .roles(Role.hostedAccountant()); + tester.assertResponse(accountantRequest, """ + {"message":"Successfully deleted line item line-item-id"}"""); + } + } + + @Test + void require_current_plan() { + { + var accountantRequest = request("/billing/v2/accountant/tenant/tenant1/plan") + .roles(Role.hostedAccountant()); + tester.assertResponse(accountantRequest, """ + {"id":"trial","name":"Free Trial - for testing purposes"}"""); + } + + { + var accountantRequest = request("/billing/v2/accountant/tenant/tenant1/plan", Request.Method.POST) + .roles(Role.hostedAccountant()) + .data(""" + {"id": "paid"}"""); + tester.assertResponse(accountantRequest, """ + {"message":"Plan: paid"}"""); + } + + { + var accountantRequest = request("/billing/v2/accountant/tenant/tenant1/plan") + .roles(Role.hostedAccountant()); + tester.assertResponse(accountantRequest, """ + {"id":"paid","name":"Paid Plan - for testing purposes"}"""); + } + } + + @Test + void require_current_collection() { + { + var accountantRequest = request("/billing/v2/accountant/tenant/tenant1/collection") + .roles(Role.hostedAccountant()); + tester.assertResponse(accountantRequest, """ + {"collection":"AUTO"}"""); + } + + { + var accountantRequest = request("/billing/v2/accountant/tenant/tenant1/collection", Request.Method.POST) + .roles(Role.hostedAccountant()) + .data(""" + {"collection": "INVOICE"}"""); + tester.assertResponse(accountantRequest, """ + {"message":"Collection: INVOICE"}"""); + } + + { + var accountantRequest = request("/billing/v2/accountant/tenant/tenant1/collection") + .roles(Role.hostedAccountant()); + tester.assertResponse(accountantRequest, """ + {"collection":"INVOICE"}"""); + } + } + + @Test + void require_accountant_tenant() { + var accountantRequest = request("/billing/v2/accountant/tenant/tenant1") + .roles(Role.hostedAccountant()); + tester.assertResponse(accountantRequest, """ + {"tenant":"tenant1","plan":{"id":"trial","name":"Free Trial - for testing purposes","billed":false,"supported":false},"billing":{},"collection":"AUTO"}"""); + } + + private static Bill createBill() { + var start = LocalDate.of(2020, 5, 23).atStartOfDay(ZoneOffset.UTC); + var end = start.toLocalDate().plusDays(6).atStartOfDay(ZoneOffset.UTC); + var statusHistory = new StatusHistory(new TreeMap<>(Map.of(start, BillStatus.OPEN))); + return new Bill( + Bill.Id.of("id-1"), + TenantName.defaultName(), + statusHistory, + List.of(createLineItem(start)), + start, + end + ); + } + + static Bill.LineItem createLineItem(ZonedDateTime addedAt) { + return new Bill.LineItem( + "some-id", + "description", + new BigDecimal("123.00"), + "paid", + "Smith", + addedAt + ); + } } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/responses/billing-all-invoices b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/responses/billing-all-invoices deleted file mode 100644 index 957ed858951..00000000000 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/responses/billing-all-invoices +++ /dev/null @@ -1,2 +0,0 @@ -ID,Tenant,From,To,CpuHours,MemoryHours,DiskHours,Cpu,Memory,Disk,Additional -id-1,default,2020-05-23,2020-05-28,0.00,0.00,0.00,0.00,0.00,0.00,123.00 diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/responses/billing-all-tenants.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/responses/billing-all-tenants.json deleted file mode 100644 index d761439667a..00000000000 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/responses/billing-all-tenants.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "until": "2020-05-28", - "tenants": [ - { - "tenant": "tenant1", - "plan": "some-plan", - "planName": "Plan with id: some-plan", - "collection": "AUTO", - "current": { - "amount": "123.00", - "status": "accrued", - "from": "2020-05-23", - "items": [ - { - "id": "some-id", - "description": "description", - "amount": "123.00", - "plan": "paid", - "planName": "Plan with id: paid", - "majorVersion": 0 - } - ] - }, - "additional": { - "items": [ - { - "id": "line-item-id", - "description": "support", - "amount": "42.00", - "plan": "some-plan", - "planName": "Plan with id: some-plan", - "majorVersion": 0 - } - ] - } - }, - { - "tenant": "tenant2", - "plan": "some-plan", - "planName": "Plan with id: some-plan", - "collection": "AUTO", - "current": { - "amount": "123.00", - "status": "accrued", - "from": "2020-05-23", - "items": [ - { - "id": "some-id", - "description": "description", - "amount": "123.00", - "plan": "paid", - "planName": "Plan with id: paid", - "majorVersion": 0 - } - ] - }, - "additional": { - "items": [ ] - } - } - ] -} diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/responses/invoice-creation-response.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/responses/invoice-creation-response.json deleted file mode 100644 index 49fde010c58..00000000000 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/responses/invoice-creation-response.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "message": "Created invoice with ID id-123", - "id": "id-123" -} diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/responses/line-item-list.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/responses/line-item-list.json deleted file mode 100644 index fbfc5ce09ee..00000000000 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/responses/line-item-list.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "lineItems": [ - { - "id": "line-item-id", - "description": "some description", - "amount": "123.45", - "plan": "some-plan", - "planName": "Plan with id: some-plan", - "majorVersion": 0 - } - ] -} diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/responses/tenant-billing-view.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/responses/tenant-billing-view.json deleted file mode 100644 index 4e255205e19..00000000000 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/responses/tenant-billing-view.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "until": "2020-05-28", - "plan": "some-plan", - "planName": "Plan with id: some-plan", - "current": { - "amount": "123.00", - "status": "accrued", - "from": "2020-05-23", - "items": [ - { - "id": "some-id", - "description": "description", - "amount": "123.00", - "plan": "paid", - "planName": "Plan with id: paid", - "majorVersion": 0 - } - ] - }, - "additional": { - "items": [ ] - }, - "bills": [ - { - "id": "id-1", - "from": "2020-05-23", - "to": "2020-05-28", - "amount": "123.00", - "status": "OPEN", - "statusHistory": [ - { - "at": "2020-05-23", - "status": "OPEN" - } - ], - "items": [ - { - "id": "some-id", - "description": "description", - "amount": "123.00", - "plan": "paid", - "planName": "Plan with id: paid", - "majorVersion": 0 - } - ] - } - ], - "collection": "AUTO" -} diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/changemanagement/ChangeManagementApiHandlerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/changemanagement/ChangeManagementApiHandlerTest.java index 8a915d72b25..80368f4b134 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/changemanagement/ChangeManagementApiHandlerTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/changemanagement/ChangeManagementApiHandlerTest.java @@ -1,4 +1,4 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.restapi.changemanagement; import com.yahoo.application.container.handler.Request; diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/configserver/ConfigServerApiHandlerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/configserver/ConfigServerApiHandlerTest.java index 82783485158..87be4519177 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/configserver/ConfigServerApiHandlerTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/configserver/ConfigServerApiHandlerTest.java @@ -1,4 +1,4 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.restapi.configserver; import com.yahoo.application.container.handler.Request; diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/ControllerApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/ControllerApiTest.java index 966c7f02cee..eb023aa9fe9 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/ControllerApiTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/ControllerApiTest.java @@ -1,9 +1,10 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.restapi.controller; import com.yahoo.application.container.handler.Request; import com.yahoo.component.Version; import com.yahoo.config.provision.ApplicationId; +import com.yahoo.config.provision.CloudAccount; import com.yahoo.config.provision.NodeResources; import com.yahoo.config.provision.zone.ZoneId; import com.yahoo.container.jdisc.HttpRequest; @@ -162,7 +163,7 @@ public class ControllerApiTest extends ControllerContainerTest { new NodeResources(12, 48, 1200, 0, NodeResources.DiskSpeed.any, NodeResources.StorageType.any, NodeResources.Architecture.arm64), new NodeResources(24, 96, 2400, 0, NodeResources.DiskSpeed.any, NodeResources.StorageType.any, NodeResources.Architecture.x86_64)); - var snapshots = resources.stream().map(x -> new ResourceSnapshot(applicationId, x, timestamp, zoneId, 0)).toList(); + var snapshots = resources.stream().map(x -> new ResourceSnapshot(applicationId, x, timestamp, zoneId, 0, CloudAccount.empty)).toList(); tester.controller().serviceRegistry().resourceDatabase().writeResourceSnapshots(snapshots); tester.assertResponse( diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/WellKnownApiHandlerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/WellKnownApiHandlerTest.java index d46fc3f18cc..ffdf6796d9d 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/WellKnownApiHandlerTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/WellKnownApiHandlerTest.java @@ -1,3 +1,4 @@ +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.restapi.controller; import com.yahoo.application.container.handler.Request; @@ -47,4 +48,4 @@ class WellKnownApiHandlerTest extends ControllerContainerTest { """, SECURITY_TXT); } -}
\ No newline at end of file +} diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/responses/maintenance.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/responses/maintenance.json index 8b76613676c..e7f48bf4ffa 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/responses/maintenance.json +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/responses/maintenance.json @@ -49,6 +49,9 @@ "name": "CostReportMaintainer" }, { + "name": "DataPlaneTokenRedeployer" + }, + { "name": "DefaultOsUpgrader" }, { @@ -133,5 +136,7 @@ "name": "VersionStatusUpdater" } ], - "inactive": ["DeploymentExpirer"] + "inactive": [ + "DeploymentExpirer" + ] } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/dataplanetoken/DataplaneTokenServiceTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/dataplanetoken/DataplaneTokenServiceTest.java index acfba03a700..87facaf1218 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/dataplanetoken/DataplaneTokenServiceTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/dataplanetoken/DataplaneTokenServiceTest.java @@ -1,33 +1,172 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.restapi.dataplanetoken; +import com.yahoo.config.provision.HostName; import com.yahoo.config.provision.SystemName; import com.yahoo.config.provision.TenantName; +import com.yahoo.config.provision.zone.AuthMethod; import com.yahoo.vespa.hosted.controller.ControllerTester; import com.yahoo.vespa.hosted.controller.api.integration.dataplanetoken.DataplaneToken; import com.yahoo.vespa.hosted.controller.api.integration.dataplanetoken.DataplaneTokenVersions; import com.yahoo.vespa.hosted.controller.api.integration.dataplanetoken.FingerPrint; import com.yahoo.vespa.hosted.controller.api.integration.dataplanetoken.TokenId; +import com.yahoo.vespa.hosted.controller.api.integration.deployment.JobType; import com.yahoo.vespa.hosted.controller.api.role.SimplePrincipal; +import com.yahoo.vespa.hosted.controller.application.pkg.ApplicationPackage; +import com.yahoo.vespa.hosted.controller.deployment.ApplicationPackageBuilder; +import com.yahoo.vespa.hosted.controller.deployment.DeploymentContext; +import com.yahoo.vespa.hosted.controller.deployment.DeploymentTester; +import com.yahoo.vespa.hosted.controller.restapi.dataplanetoken.DataplaneTokenService.State; import org.junit.jupiter.api.Test; import java.security.Principal; import java.time.Duration; import java.util.Collection; import java.util.List; +import java.util.Map; import java.util.Set; +import java.util.TreeMap; +import static java.util.stream.Collectors.toMap; import static java.util.stream.Collectors.toSet; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertThrows; public class DataplaneTokenServiceTest { + private final ControllerTester tester = new ControllerTester(SystemName.Public); private final DataplaneTokenService dataplaneTokenService = new DataplaneTokenService(tester.controller()); private final TenantName tenantName = TenantName.from("tenant"); - Principal principal = new SimplePrincipal("user"); + private final Principal principal = new SimplePrincipal("user"); private final TokenId tokenId = TokenId.of("myTokenId"); + private final Map<HostName, Map<TokenId, List<FingerPrint>>> activeTokens = tester.configServer().activeTokenFingerprints(null); + + @Test + void triggers_token_redeployments() { + DeploymentTester deploymentTester = new DeploymentTester(tester); + DeploymentContext app = deploymentTester.newDeploymentContext(tenantName.value(), "app", "default"); + ApplicationPackage appPackage = new ApplicationPackageBuilder().region("aws-us-east-1c") + .container("default", AuthMethod.token, AuthMethod.token) + .build(); + app.submit(appPackage).deploy(); + + // First token version is added after deployment, so re-trigger. + dataplaneTokenService.triggerTokenChangeDeployments(); + assertEquals(List.of(), deploymentTester.jobs().active()); + FingerPrint print1 = dataplaneTokenService.generateToken(tenantName, TokenId.of("token-1"), null, principal).fingerPrint(); + dataplaneTokenService.triggerTokenChangeDeployments(); + app.runJob(JobType.prod("aws-us-east-1c")); + assertEquals(List.of(), deploymentTester.jobs().active()); + + // New token version is added, so re-trigger. + tester.clock().advance(Duration.ofSeconds(1)); + dataplaneTokenService.triggerTokenChangeDeployments(); + assertEquals(List.of(), deploymentTester.jobs().active()); + FingerPrint print2 = dataplaneTokenService.generateToken(tenantName, TokenId.of("token-1"), null, principal).fingerPrint(); + dataplaneTokenService.triggerTokenChangeDeployments(); + app.runJob(JobType.prod("aws-us-east-1c")); + assertEquals(List.of(), deploymentTester.jobs().active()); + + // Another token version is added, so re-trigger. + tester.clock().advance(Duration.ofSeconds(1)); + dataplaneTokenService.triggerTokenChangeDeployments(); + assertEquals(List.of(), deploymentTester.jobs().active()); + FingerPrint print3 = dataplaneTokenService.generateToken(tenantName, TokenId.of("token-1"), tester.clock().instant().plusSeconds(10), principal).fingerPrint(); + dataplaneTokenService.triggerTokenChangeDeployments(); + app.runJob(JobType.prod("aws-us-east-1c")); + assertEquals(List.of(), deploymentTester.jobs().active()); + + // An expired token version is deleted, so do _not_ re-trigger. + tester.clock().advance(Duration.ofSeconds(11)); + dataplaneTokenService.triggerTokenChangeDeployments(); + assertEquals(List.of(), deploymentTester.jobs().active()); + dataplaneTokenService.deleteToken(tenantName, TokenId.of("token-1"), print3); + dataplaneTokenService.triggerTokenChangeDeployments(); + assertEquals(List.of(), deploymentTester.jobs().active()); + + // Some unused token version is added, so do _not_ re-trigger. + tester.clock().advance(Duration.ofSeconds(1)); + dataplaneTokenService.triggerTokenChangeDeployments(); + assertEquals(List.of(), deploymentTester.jobs().active()); + dataplaneTokenService.generateToken(tenantName, TokenId.of("token-3"), null, principal); + dataplaneTokenService.triggerTokenChangeDeployments(); + assertEquals(List.of(), deploymentTester.jobs().active()); + + // One token version is deleted, so re-trigger. + tester.clock().advance(Duration.ofSeconds(1)); + dataplaneTokenService.triggerTokenChangeDeployments(); + assertEquals(List.of(), deploymentTester.jobs().active()); + dataplaneTokenService.deleteToken(tenantName, TokenId.of("token-1"), print2); + dataplaneTokenService.triggerTokenChangeDeployments(); + app.runJob(JobType.prod("aws-us-east-1c")); + assertEquals(List.of(), deploymentTester.jobs().active()); + + // Last token version is deleted, the token is no longer known, so re-trigger. + tester.clock().advance(Duration.ofSeconds(1)); + dataplaneTokenService.triggerTokenChangeDeployments(); + assertEquals(List.of(), deploymentTester.jobs().active()); + dataplaneTokenService.deleteToken(tenantName, TokenId.of("token-1"), print1); + dataplaneTokenService.triggerTokenChangeDeployments(); + app.runJob(JobType.prod("aws-us-east-1c")); + assertEquals(List.of(), deploymentTester.jobs().active()); + } + + @Test + void computes_aggregate_state() { + DeploymentTester deploymentTester = new DeploymentTester(tester); + DeploymentContext app = deploymentTester.newDeploymentContext(tenantName.value(), "app", "default"); + app.submit().deploy(); + + TokenId[] id = new TokenId[5]; + FingerPrint[][] print = new FingerPrint[5][3]; + for (int i = 0; i < id.length; i++) { + id[i] = TokenId.of("id" + i); + for (int j = 0; j < 3; j++) { + print[i][j] = dataplaneTokenService.generateToken(tenantName, id[i], null, principal).fingerPrint(); + } + } + for (int j = 0; j < 2; j++) { + dataplaneTokenService.deleteToken(tenantName, id[2], print[2][j]); + dataplaneTokenService.deleteToken(tenantName, id[4], print[4][j]); + } + for (int j = 0; j < 3; j++) { + dataplaneTokenService.deleteToken(tenantName, id[3], print[3][j]); + } + // "host1" has all versions of all current tokens, except the first versions of tokens 1 and 2. + activeTokens.put(HostName.of("host1"), + Map.of(id[0], List.of(print[0]), + id[1], List.of(print[1][1], print[1][2]), + id[2], List.of(print[2][1], print[2][2]))); + // "host2" has all versions of all current tokens, except the last version of token 1. + activeTokens.put(HostName.of("host2"), + Map.of(id[0], List.of(print[0]), + id[1], List.of(print[1][0], print[1][1]), + id[2], List.of(print[2]))); + // "host3" has no current tokens at all, but has the last version of token 3 + activeTokens.put(HostName.of("host3"), + Map.of(id[3], List.of(print[3][2]))); + + // All fingerprints of token 0 are active on all hosts where token 0 is found, so they are all active. + // The first and last fingerprints of token 1 are missing from one host each, so these are activating. + // The first fingerprints of token 2 are no longer current, but the second is found on a host; both deactivating. + // The whole of token 3 is forgotten, but the last fingerprint is found on a host; deactivating. + // Only the last fingerprint of token 4 remains, but this token is not used anywhere; unused. + assertEquals(new TreeMap<>(Map.of(id[0], new TreeMap<>(Map.of(print[0][0], State.ACTIVE, + print[0][1], State.ACTIVE, + print[0][2], State.ACTIVE)), + id[1], new TreeMap<>(Map.of(print[1][0], State.DEPLOYING, + print[1][1], State.ACTIVE, + print[1][2], State.DEPLOYING)), + id[2], new TreeMap<>(Map.of(print[2][0], State.REVOKING, + print[2][1], State.REVOKING, + print[2][2], State.ACTIVE)), + id[3], new TreeMap<>(Map.of(print[3][2], State.REVOKING)), + id[4], new TreeMap<>(Map.of(print[4][2], State.UNUSED)))), + new TreeMap<>(dataplaneTokenService.listTokensWithState(tenantName).entrySet().stream() + .collect(toMap(tokens -> tokens.getKey().tokenId(), + tokens -> new TreeMap<>(tokens.getValue()))))); + } @Test void generates_and_persists_token() { @@ -82,4 +221,5 @@ public class DataplaneTokenServiceTest { IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> dataplaneTokenService.deleteToken(tenantName, tokenId, dataplaneToken.fingerPrint())); assertEquals("Token does not exist: " + tokenId, exception.getMessage()); } + } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/BadgeApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/BadgeApiTest.java index 5dd57b09af4..cfacbfe77f4 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/BadgeApiTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/BadgeApiTest.java @@ -1,6 +1,7 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.restapi.deployment; +import com.yahoo.application.container.handler.Request.Method; import com.yahoo.component.Version; import com.yahoo.vespa.hosted.controller.ControllerTester; import com.yahoo.vespa.hosted.controller.application.pkg.ApplicationPackage; @@ -9,12 +10,15 @@ import com.yahoo.vespa.hosted.controller.deployment.DeploymentContext; import com.yahoo.vespa.hosted.controller.deployment.DeploymentTester; import com.yahoo.vespa.hosted.controller.restapi.ContainerTester; import com.yahoo.vespa.hosted.controller.restapi.ControllerContainerTest; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.time.Duration; +import java.util.List; +import java.util.Map; /** * @author jonmv @@ -79,6 +83,18 @@ public class BadgeApiTest extends ControllerContainerTest { tester.assertResponse(authenticatedRequest("http://localhost:8080/badge/v1/tenant/application/default/production-us-west-1?historyLength=0"), Files.readString(Paths.get(responseFiles + "single-done.svg")), 200); + + tester.assertResponse(() -> authenticatedRequest("http://localhost:8080/badge/v1/tenant/application/default", "", Method.HEAD), + __ -> { }, + 200); + + tester.assertResponse(() -> authenticatedRequest("http://localhost:8080/badge/v1/tenant/application/default", "", Method.OPTIONS), + response -> Assertions.assertEquals(List.of(Map.entry("Access-Control-Allow-Methods", "GET, HEAD, OPTIONS"), + Map.entry("Access-Control-Allow-Origin", "*"), + Map.entry("Allow", "GET, HEAD, OPTIONS"), + Map.entry("Content-Type", "image/svg+xml; charset=UTF-8")), + response.getHeaders().entries()), + 200); } } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/DeploymentApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/DeploymentApiTest.java index eea5c9bdccf..5d0608b8bd9 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/DeploymentApiTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/DeploymentApiTest.java @@ -1,4 +1,4 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.restapi.deployment; import com.yahoo.component.Version; diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/filter/AthenzRoleFilterTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/filter/AthenzRoleFilterTest.java index 877ca4a99d2..fe0a3551860 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/filter/AthenzRoleFilterTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/filter/AthenzRoleFilterTest.java @@ -1,4 +1,4 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.restapi.filter; import com.yahoo.config.provision.ApplicationName; diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/filter/ControllerAuthorizationFilterTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/filter/ControllerAuthorizationFilterTest.java index 64dce08e735..0b993fc70a3 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/filter/ControllerAuthorizationFilterTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/filter/ControllerAuthorizationFilterTest.java @@ -1,4 +1,4 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.restapi.filter; import com.fasterxml.jackson.databind.ObjectMapper; diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/filter/LastLoginUpdateFilterTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/filter/LastLoginUpdateFilterTest.java index b85c93a5d90..8abf32c45f9 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/filter/LastLoginUpdateFilterTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/filter/LastLoginUpdateFilterTest.java @@ -1,4 +1,4 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.restapi.filter; import com.yahoo.application.container.handler.Request; diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/filter/SignatureFilterTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/filter/SignatureFilterTest.java index 001e02e1b16..9477e71af33 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/filter/SignatureFilterTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/filter/SignatureFilterTest.java @@ -1,4 +1,4 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.restapi.filter; import ai.vespa.hosted.api.Method; @@ -11,6 +11,7 @@ import com.yahoo.security.KeyUtils; import com.yahoo.vespa.hosted.controller.Application; import com.yahoo.vespa.hosted.controller.ApplicationController; import com.yahoo.vespa.hosted.controller.ControllerTester; +import com.yahoo.vespa.hosted.controller.api.integration.billing.PlanId; import com.yahoo.vespa.hosted.controller.api.role.Role; import com.yahoo.vespa.hosted.controller.api.role.SecurityContext; import com.yahoo.vespa.hosted.controller.api.role.SimplePrincipal; @@ -70,7 +71,7 @@ public class SignatureFilterTest { filter = new SignatureFilter(tester.controller()); signer = new RequestSigner(privateKey, id.serializedForm(), tester.clock()); - tester.curator().writeTenant(CloudTenant.create(appId.tenant(), Instant.EPOCH, null)); + tester.curator().writeTenant(CloudTenant.create(appId.tenant(), Instant.EPOCH, new SimplePrincipal("owner@my-tenant.my-app"))); tester.curator().writeApplication(new Application(appId, tester.clock().instant())); } @@ -120,7 +121,8 @@ public class SignatureFilterTest { Optional.empty(), Instant.EPOCH, List.of(), - Optional.empty())); + Optional.empty(), + PlanId.from("none"))); verifySecurityContext(requestOf(signer.signed(request.copy(), Method.POST, () -> new ByteArrayInputStream(hiBytes)), hiBytes), new SecurityContext(new SimplePrincipal("user"), Set.of(Role.reader(id.tenant()), diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/flags/AuditedFlagsApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/flags/AuditedFlagsApiTest.java index ee89f506f17..643ac82b223 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/flags/AuditedFlagsApiTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/flags/AuditedFlagsApiTest.java @@ -1,4 +1,4 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.restapi.flags; import com.yahoo.application.container.handler.Request; diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/horizon/HorizonApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/horizon/HorizonApiTest.java index fabae508057..87b4bf7e84c 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/horizon/HorizonApiTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/horizon/HorizonApiTest.java @@ -1,4 +1,4 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.restapi.horizon; import com.yahoo.config.provision.SystemName; diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/horizon/TsdbQueryRewriterTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/horizon/TsdbQueryRewriterTest.java index 7f826566ebc..87d34874631 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/horizon/TsdbQueryRewriterTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/horizon/TsdbQueryRewriterTest.java @@ -1,4 +1,4 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.restapi.horizon; import com.yahoo.config.provision.SystemName; diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/os/OsApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/os/OsApiTest.java index acb07102008..7a1b9979cfd 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/os/OsApiTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/os/OsApiTest.java @@ -1,4 +1,4 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.restapi.os; import com.yahoo.application.container.handler.Request; diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/AllowingFilter.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/AllowingFilter.java index ec3328fbf61..9798f95e703 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/AllowingFilter.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/AllowingFilter.java @@ -1,4 +1,4 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.restapi.playground; import com.yahoo.jdisc.http.filter.DiscFilterRequest; diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/DeploymentPlayground.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/DeploymentPlayground.java index 38019ec725b..38ae1502b6e 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/DeploymentPlayground.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/DeploymentPlayground.java @@ -1,4 +1,4 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.restapi.playground; import ai.vespa.validation.StringWrapper; diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/deployment.xml b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/deployment.xml index 61749cd89f0..1097a197d96 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/deployment.xml +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/deployment.xml @@ -1,3 +1,4 @@ +<!-- Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. --> <deployment version='1.0'> <notifications> <email role="author" /> @@ -129,4 +130,4 @@ </steps> </parallel> -</deployment>
\ No newline at end of file +</deployment> diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/deployment_alt_full.xml b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/deployment_alt_full.xml index 61749cd89f0..1097a197d96 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/deployment_alt_full.xml +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/deployment_alt_full.xml @@ -1,3 +1,4 @@ +<!-- Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. --> <deployment version='1.0'> <notifications> <email role="author" /> @@ -129,4 +130,4 @@ </steps> </parallel> -</deployment>
\ No newline at end of file +</deployment> diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/deployment_alternative.xml b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/deployment_alternative.xml index 8bd24e977b1..b074792f716 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/deployment_alternative.xml +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/deployment_alternative.xml @@ -1,3 +1,4 @@ +<!-- Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. --> <deployment version='1.0'> <notifications> <email role="author" /> diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/deployment_base.xml b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/deployment_base.xml index e3d7933d5e7..715ff4fdb3f 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/deployment_base.xml +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/deployment_base.xml @@ -1,3 +1,4 @@ +<!-- Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. --> <deployment version='1.0'> <notifications> <email role="author" /> diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/deployment_full.xml b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/deployment_full.xml index 5a7b44f966d..0b85852abdb 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/deployment_full.xml +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/deployment_full.xml @@ -1,3 +1,4 @@ +<!-- Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. --> <deployment version='1.0'> <notifications> <email role="author" /> diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/deployment_simple.xml b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/deployment_simple.xml index cdcaadbd957..16986df174c 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/deployment_simple.xml +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/deployment_simple.xml @@ -1,3 +1,4 @@ +<!-- Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. --> <deployment version='1.0'> <parallel> diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/deployment_simpler.xml b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/deployment_simpler.xml index f0b0ae79d81..8be40e84495 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/deployment_simpler.xml +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/deployment_simpler.xml @@ -1,3 +1,4 @@ +<!-- Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. --> <deployment version='1.0'> <instance id="alpha"> <!-- Runs system and stress tests --> diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/deployment_simplest.xml b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/deployment_simplest.xml index b023587b6a9..37efaf82b5a 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/deployment_simplest.xml +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/playground/deployment_simplest.xml @@ -1,3 +1,4 @@ +<!-- Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. --> <deployment version='1.0'> <instance id="beta"> <!-- Runs system and production tests --> diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/routing/RoutingApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/routing/RoutingApiTest.java index b90c886f10d..309501f5679 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/routing/RoutingApiTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/routing/RoutingApiTest.java @@ -1,4 +1,4 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.restapi.routing; import com.yahoo.application.container.handler.Request; diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/systemflags/SystemFlagsDeployResultTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/systemflags/SystemFlagsDeployResultTest.java index 8d643534e0c..44fc86e314e 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/systemflags/SystemFlagsDeployResultTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/systemflags/SystemFlagsDeployResultTest.java @@ -1,4 +1,4 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.restapi.systemflags; import com.yahoo.config.provision.SystemName; @@ -73,4 +73,4 @@ public class SystemFlagsDeployResultTest { OperationError error = errors.get(0); assertEquals(error.targets(), Set.of(controllerTarget, prodUsWest1Target)); } -}
\ No newline at end of file +} diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/systemflags/SystemFlagsDeployerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/systemflags/SystemFlagsDeployerTest.java index cb330d28d22..b53a0847ddb 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/systemflags/SystemFlagsDeployerTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/systemflags/SystemFlagsDeployerTest.java @@ -1,4 +1,4 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.restapi.systemflags; import com.yahoo.config.provision.SystemName; diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiOnPremTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiOnPremTest.java index f7e270b3c68..81db6b02a50 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiOnPremTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiOnPremTest.java @@ -1,4 +1,4 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.restapi.user; import com.yahoo.application.container.handler.Request; diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiTest.java index b3c992cdac7..63ae56e4207 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiTest.java @@ -1,4 +1,4 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.restapi.user; import com.yahoo.config.provision.ApplicationId; diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserFlagsSerializerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserFlagsSerializerTest.java index eb3f9daef53..d0a374dbb3a 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserFlagsSerializerTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserFlagsSerializerTest.java @@ -1,4 +1,4 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.restapi.user; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @@ -130,4 +130,4 @@ public class UserFlagsSerializerTest { return Objects.hash(integer, string); } } -}
\ No newline at end of file +} diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/tenant-info-after-created.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/tenant-info-after-created.json index 6702eff8dde..1926dcc9f82 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/tenant-info-after-created.json +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/responses/tenant-info-after-created.json @@ -5,5 +5,14 @@ "contactName": "administrator", "contactEmail": "administrator@tenant", "contactEmailVerified": true, - "contacts": [ ] + "contacts": [ + { + "audiences": [ + "tenant", + "notifications" + ], + "email": "administrator@tenant", + "emailVerified": true + } + ] } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/zone/v1/ZoneApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/zone/v1/ZoneApiTest.java index 5d5e310503d..183e9968878 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/zone/v1/ZoneApiTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/zone/v1/ZoneApiTest.java @@ -1,4 +1,4 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.restapi.zone.v1; import com.yahoo.config.provision.Environment; diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/zone/v2/ZoneApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/zone/v2/ZoneApiTest.java index 81484f05d1e..b680a4341f3 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/zone/v2/ZoneApiTest.java +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/zone/v2/ZoneApiTest.java @@ -1,4 +1,4 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.restapi.zone.v2; import com.yahoo.application.container.handler.Request.Method; |