Search in sources :

Example 1 with UserId

use of com.yahoo.vespa.hosted.controller.api.identifiers.UserId in project vespa by vespa-engine.

the class ApplicationApiTest method testAuthorization.

@Test
public void testAuthorization() throws Exception {
    ContainerTester tester = new ContainerTester(container, responseFiles);
    UserId authorizedUser = USER_ID;
    UserId unauthorizedUser = new UserId("othertenant");
    // Mutation without an user is disallowed
    tester.assertResponse(request("/application/v4/tenant/tenant1", POST).data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}"), "{\n  \"message\" : \"Not authenticated\"\n}", 401);
    // ... but read methods are allowed for authenticated user
    tester.assertResponse(request("/application/v4/tenant/", GET).userIdentity(USER_ID).data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}"), "[]", 200);
    createAthenzDomainWithAdmin(ATHENZ_TENANT_DOMAIN, USER_ID);
    // Creating a tenant for an Athens domain the user is not admin for is disallowed
    tester.assertResponse(request("/application/v4/tenant/tenant1", POST).data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}").userIdentity(unauthorizedUser), "{\"error-code\":\"FORBIDDEN\",\"message\":\"The user 'user.othertenant' is not admin in Athenz domain 'domain1'\"}", 403);
    // (Create it with the right tenant id)
    tester.assertResponse(request("/application/v4/tenant/tenant1", POST).data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}").userIdentity(authorizedUser).nToken(N_TOKEN), new File("tenant-without-applications.json"), 200);
    // Creating an application for an Athens domain the user is not admin for is disallowed
    tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1", POST).userIdentity(unauthorizedUser).nToken(N_TOKEN), "{\n  \"message\" : \"Tenant admin or Vespa operator role required\"\n}", 403);
    // (Create it with the right tenant id)
    tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1", POST).userIdentity(authorizedUser).nToken(N_TOKEN), new File("application-reference.json"), 200);
    // Deploy to an authorized zone by a user tenant is disallowed
    HttpEntity entity = createApplicationDeployData(applicationPackage, Optional.empty());
    tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/us-west-1/instance/default/deploy", POST).data(entity).userIdentity(USER_ID), "{\n  \"message\" : \"'user.myuser' is not a Screwdriver identity. Only Screwdriver is allowed to deploy to this environment.\"\n}", 403);
    // Deleting an application for an Athens domain the user is not admin for is disallowed
    tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1", DELETE).userIdentity(unauthorizedUser), "{\n  \"message\" : \"Tenant admin or Vespa operator role required\"\n}", 403);
    // (Deleting it with the right tenant id)
    tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1", DELETE).userIdentity(authorizedUser).nToken(N_TOKEN), "", 200);
    // Updating a tenant for an Athens domain the user is not admin for is disallowed
    tester.assertResponse(request("/application/v4/tenant/tenant1", PUT).data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}").userIdentity(unauthorizedUser), "{\n  \"message\" : \"Tenant admin or Vespa operator role required\"\n}", 403);
    // Change Athens domain
    createAthenzDomainWithAdmin(new AthenzDomain("domain2"), USER_ID);
    tester.assertResponse(request("/application/v4/tenant/tenant1", PUT).data("{\"athensDomain\":\"domain2\", \"property\":\"property1\"}").userIdentity(authorizedUser).nToken(N_TOKEN), "{\"tenant\":\"tenant1\",\"type\":\"ATHENS\",\"athensDomain\":\"domain2\",\"property\":\"property1\",\"applications\":[]}", 200);
    // Deleting a tenant for an Athens domain the user is not admin for is disallowed
    tester.assertResponse(request("/application/v4/tenant/tenant1", DELETE).userIdentity(unauthorizedUser), "{\n  \"message\" : \"Tenant admin or Vespa operator role required\"\n}", 403);
}
Also used : HttpEntity(org.apache.http.HttpEntity) AthenzDomain(com.yahoo.vespa.athenz.api.AthenzDomain) UserId(com.yahoo.vespa.hosted.controller.api.identifiers.UserId) ContainerTester(com.yahoo.vespa.hosted.controller.restapi.ContainerTester) File(java.io.File) ControllerContainerTest(com.yahoo.vespa.hosted.controller.restapi.ControllerContainerTest) Test(org.junit.Test)

Example 2 with UserId

use of com.yahoo.vespa.hosted.controller.api.identifiers.UserId in project vespa by vespa-engine.

the class ApplicationApiHandler method authenticatedUser.

private HttpResponse authenticatedUser(HttpRequest request) {
    String userIdString = request.getProperty("userOverride");
    if (userIdString == null)
        userIdString = getUserId(request).map(UserId::id).orElseThrow(() -> new ForbiddenException("You must be authenticated or specify userOverride"));
    UserId userId = new UserId(userIdString);
    List<Tenant> tenants = controller.tenants().asList(userId);
    Slime slime = new Slime();
    Cursor response = slime.setObject();
    response.setString("user", userId.id());
    Cursor tenantsArray = response.setArray("tenants");
    for (Tenant tenant : tenants) tenantInTenantsListToSlime(tenant, request.getUri(), tenantsArray.addObject());
    response.setBool("tenantExists", tenants.stream().map(Tenant::getId).anyMatch(id -> id.isTenantFor(userId)));
    return new SlimeJsonResponse(slime);
}
Also used : AlreadyExistsException(com.yahoo.vespa.hosted.controller.AlreadyExistsException) EndpointStatus(com.yahoo.vespa.hosted.controller.api.application.v4.model.EndpointStatus) Inject(com.google.inject.Inject) URISyntaxException(java.net.URISyntaxException) SlimeJsonResponse(com.yahoo.vespa.hosted.controller.restapi.SlimeJsonResponse) Scanner(java.util.Scanner) DeploymentJobs(com.yahoo.vespa.hosted.controller.application.DeploymentJobs) ConfigServerException(com.yahoo.vespa.hosted.controller.api.integration.configserver.ConfigServerException) RegionName(com.yahoo.config.provision.RegionName) TenantName(com.yahoo.config.provision.TenantName) ResourceResponse(com.yahoo.vespa.hosted.controller.restapi.ResourceResponse) Tenant(com.yahoo.vespa.hosted.controller.api.Tenant) ZoneId(com.yahoo.vespa.hosted.controller.api.integration.zone.ZoneId) ClusterUtilization(com.yahoo.vespa.hosted.controller.application.ClusterUtilization) Duration(java.time.Duration) Map(java.util.Map) LogLevel(com.yahoo.log.LogLevel) Path(com.yahoo.vespa.hosted.controller.restapi.Path) JobStatus(com.yahoo.vespa.hosted.controller.application.JobStatus) GitRevision(com.yahoo.vespa.hosted.controller.api.application.v4.model.GitRevision) ClusterCost(com.yahoo.vespa.hosted.controller.application.ClusterCost) BadRequestException(javax.ws.rs.BadRequestException) DeployOptions(com.yahoo.vespa.hosted.controller.api.application.v4.model.DeployOptions) URI(java.net.URI) DeploymentCost(com.yahoo.vespa.hosted.controller.application.DeploymentCost) ScrewdriverBuildJob(com.yahoo.vespa.hosted.controller.api.application.v4.model.ScrewdriverBuildJob) Exceptions(com.yahoo.yolean.Exceptions) AthenzDomain(com.yahoo.vespa.athenz.api.AthenzDomain) ImmutableSet(com.google.common.collect.ImmutableSet) Inspector(com.yahoo.slime.Inspector) NotExistsException(com.yahoo.vespa.hosted.controller.NotExistsException) ApplicationVersion(com.yahoo.vespa.hosted.controller.application.ApplicationVersion) InternalServerErrorException(javax.ws.rs.InternalServerErrorException) ErrorResponse(com.yahoo.vespa.hosted.controller.restapi.ErrorResponse) RestartAction(com.yahoo.vespa.hosted.controller.api.application.v4.model.configserverbindings.RestartAction) Property(com.yahoo.vespa.hosted.controller.api.identifiers.Property) ApplicationView(com.yahoo.vespa.serviceview.bindings.ApplicationView) Objects(java.util.Objects) ZmsException(com.yahoo.vespa.hosted.controller.api.integration.athenz.ZmsException) List(java.util.List) Principal(java.security.Principal) AthenzPrincipal(com.yahoo.vespa.athenz.api.AthenzPrincipal) NotAuthorizedException(javax.ws.rs.NotAuthorizedException) Optional(java.util.Optional) Deployment(com.yahoo.vespa.hosted.controller.application.Deployment) HttpResponse(com.yahoo.container.jdisc.HttpResponse) Controller(com.yahoo.vespa.hosted.controller.Controller) Joiner(com.google.common.base.Joiner) Log(com.yahoo.vespa.hosted.controller.api.integration.configserver.Log) AthenzClientFactory(com.yahoo.vespa.hosted.controller.api.integration.athenz.AthenzClientFactory) GitRepository(com.yahoo.vespa.hosted.controller.api.identifiers.GitRepository) ApplicationName(com.yahoo.config.provision.ApplicationName) AthenzUser(com.yahoo.vespa.athenz.api.AthenzUser) Version(com.yahoo.component.Version) ApplicationId(com.yahoo.config.provision.ApplicationId) PropertyId(com.yahoo.vespa.hosted.controller.api.identifiers.PropertyId) RefeedAction(com.yahoo.vespa.hosted.controller.api.application.v4.model.configserverbindings.RefeedAction) DeploymentId(com.yahoo.vespa.hosted.controller.api.identifiers.DeploymentId) Slime(com.yahoo.slime.Slime) AthenzIdentity(com.yahoo.vespa.athenz.api.AthenzIdentity) IOUtils(com.yahoo.io.IOUtils) NToken(com.yahoo.vespa.athenz.api.NToken) Level(java.util.logging.Level) DeploymentMetrics(com.yahoo.vespa.hosted.controller.application.DeploymentMetrics) ApplicationResource(com.yahoo.vespa.hosted.controller.api.application.v4.ApplicationResource) SlimeUtils(com.yahoo.vespa.config.SlimeUtils) Change(com.yahoo.vespa.hosted.controller.application.Change) TenantId(com.yahoo.vespa.hosted.controller.api.identifiers.TenantId) GitBranch(com.yahoo.vespa.hosted.controller.api.identifiers.GitBranch) ServiceInfo(com.yahoo.vespa.hosted.controller.api.application.v4.model.configserverbindings.ServiceInfo) SetBouncerPassthruHeaderFilter(com.yahoo.vespa.hosted.controller.restapi.filter.SetBouncerPassthruHeaderFilter) EnvironmentResource(com.yahoo.vespa.hosted.controller.api.application.v4.EnvironmentResource) TenantResource(com.yahoo.vespa.hosted.controller.api.application.v4.TenantResource) Application(com.yahoo.vespa.hosted.controller.Application) ActivateResult(com.yahoo.vespa.hosted.controller.api.ActivateResult) Cursor(com.yahoo.slime.Cursor) StringResponse(com.yahoo.vespa.hosted.controller.restapi.StringResponse) ForbiddenException(javax.ws.rs.ForbiddenException) Hostname(com.yahoo.vespa.hosted.controller.api.identifiers.Hostname) Environment(com.yahoo.config.provision.Environment) GitCommit(com.yahoo.vespa.hosted.controller.api.identifiers.GitCommit) HttpRequest(com.yahoo.container.jdisc.HttpRequest) SourceRevision(com.yahoo.vespa.hosted.controller.application.SourceRevision) IOException(java.io.IOException) MessageResponse(com.yahoo.vespa.hosted.controller.restapi.MessageResponse) ApplicationPackage(com.yahoo.vespa.hosted.controller.application.ApplicationPackage) LoggingRequestHandler(com.yahoo.container.jdisc.LoggingRequestHandler) User(com.yahoo.vespa.hosted.controller.api.integration.organization.User) UserId(com.yahoo.vespa.hosted.controller.api.identifiers.UserId) RotationStatus(com.yahoo.vespa.hosted.controller.api.integration.routing.RotationStatus) DeploymentSpec(com.yahoo.config.application.api.DeploymentSpec) DayOfWeek(java.time.DayOfWeek) ScrewdriverId(com.yahoo.vespa.hosted.controller.api.identifiers.ScrewdriverId) Collections(java.util.Collections) InputStream(java.io.InputStream) ForbiddenException(javax.ws.rs.ForbiddenException) Tenant(com.yahoo.vespa.hosted.controller.api.Tenant) SlimeJsonResponse(com.yahoo.vespa.hosted.controller.restapi.SlimeJsonResponse) UserId(com.yahoo.vespa.hosted.controller.api.identifiers.UserId) Slime(com.yahoo.slime.Slime) Cursor(com.yahoo.slime.Cursor)

Example 3 with UserId

use of com.yahoo.vespa.hosted.controller.api.identifiers.UserId in project vespa by vespa-engine.

the class UserAuthWithAthenzPrincipalFilter method rewriteUserPrincipalToAthenz.

private void rewriteUserPrincipalToAthenz(DiscFilterRequest request) {
    Principal userPrincipal = request.getUserPrincipal();
    log.log(LogLevel.DEBUG, () -> "Original user principal: " + userPrincipal.toString());
    UserId userId = new UserId(userPrincipal.getName());
    AthenzUser athenzIdentity = AthenzUser.fromUserId(userId.id());
    request.setRemoteUser(athenzIdentity.getFullName());
    NToken nToken = Optional.ofNullable(request.getHeader(principalHeaderName)).map(NToken::new).orElse(null);
    request.setUserPrincipal(new AthenzPrincipal(athenzIdentity, nToken));
}
Also used : UserId(com.yahoo.vespa.hosted.controller.api.identifiers.UserId) NToken(com.yahoo.vespa.athenz.api.NToken) AthenzPrincipal(com.yahoo.vespa.athenz.api.AthenzPrincipal) AthenzUser(com.yahoo.vespa.athenz.api.AthenzUser) Principal(java.security.Principal) AthenzPrincipal(com.yahoo.vespa.athenz.api.AthenzPrincipal)

Example 4 with UserId

use of com.yahoo.vespa.hosted.controller.api.identifiers.UserId in project vespa by vespa-engine.

the class TenantController method createUserTenant.

public Tenant createUserTenant(String userName) {
    TenantId userTenantId = new UserId(userName).toTenantId();
    try (Lock lock = lock(userTenantId)) {
        Tenant tenant = Tenant.createUserTenant(userTenantId);
        internalCreateTenant(tenant, Optional.empty());
        return tenant;
    }
}
Also used : TenantId(com.yahoo.vespa.hosted.controller.api.identifiers.TenantId) Tenant(com.yahoo.vespa.hosted.controller.api.Tenant) UserId(com.yahoo.vespa.hosted.controller.api.identifiers.UserId) Lock(com.yahoo.vespa.curator.Lock)

Example 5 with UserId

use of com.yahoo.vespa.hosted.controller.api.identifiers.UserId in project vespa by vespa-engine.

the class ApplicationApiTest method testApplicationApi.

@Test
public void testApplicationApi() throws Exception {
    ContainerControllerTester controllerTester = new ContainerControllerTester(container, responseFiles);
    ContainerTester tester = controllerTester.containerTester();
    tester.updateSystemVersion();
    // (Necessary but not provided in this API)
    createAthenzDomainWithAdmin(ATHENZ_TENANT_DOMAIN, USER_ID);
    // GET API root
    tester.assertResponse(request("/application/v4/", GET).userIdentity(USER_ID), new File("root.json"));
    // GET athens domains
    tester.assertResponse(request("/application/v4/athensDomain/", GET).userIdentity(USER_ID), new File("athensDomain-list.json"));
    // GET OpsDB properties
    tester.assertResponse(request("/application/v4/property/", GET).userIdentity(USER_ID), new File("property-list.json"));
    // GET cookie freshness
    tester.assertResponse(request("/application/v4/cookiefreshness/", GET).userIdentity(USER_ID), new File("cookiefreshness.json"));
    // POST (add) a tenant without property ID
    tester.assertResponse(request("/application/v4/tenant/tenant1", POST).userIdentity(USER_ID).data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}").nToken(N_TOKEN), new File("tenant-without-applications.json"));
    // PUT (modify) a tenant
    tester.assertResponse(request("/application/v4/tenant/tenant1", PUT).userIdentity(USER_ID).nToken(N_TOKEN).data("{\"athensDomain\":\"domain1\", \"property\":\"property1\"}"), new File("tenant-without-applications.json"));
    // GET the authenticated user (with associated tenants)
    tester.assertResponse(request("/application/v4/user", GET).userIdentity(USER_ID), new File("user.json"));
    // GET all tenants
    tester.assertResponse(request("/application/v4/tenant/", GET).userIdentity(USER_ID), new File("tenant-list.json"));
    // Add another Athens domain, so we can try to create more tenants
    // New domain to test tenant w/property ID
    createAthenzDomainWithAdmin(new AthenzDomain("domain2"), USER_ID);
    // Add property info for that property id, as well, in the mock organization.
    addPropertyData((MockOrganization) controllerTester.controller().organization(), "1234");
    // POST (add) a tenant with property ID
    tester.assertResponse(request("/application/v4/tenant/tenant2", POST).userIdentity(USER_ID).nToken(N_TOKEN).data("{\"athensDomain\":\"domain2\", \"property\":\"property2\", \"propertyId\":\"1234\"}"), new File("tenant-without-applications-with-id.json"));
    // PUT (modify) a tenant with property ID
    tester.assertResponse(request("/application/v4/tenant/tenant2", PUT).userIdentity(USER_ID).nToken(N_TOKEN).data("{\"athensDomain\":\"domain2\", \"property\":\"property2\", \"propertyId\":\"1234\"}"), new File("tenant-without-applications-with-id.json"));
    // GET a tenant with property ID
    tester.assertResponse(request("/application/v4/tenant/tenant2", GET).userIdentity(USER_ID), new File("tenant-without-applications-with-id.json"));
    // POST (create) an application
    tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1", POST).userIdentity(USER_ID).nToken(N_TOKEN), new File("application-reference.json"));
    // GET a tenant
    tester.assertResponse(request("/application/v4/tenant/tenant1", GET).userIdentity(USER_ID), new File("tenant-with-application.json"));
    // GET tenant applications
    tester.assertResponse(request("/application/v4/tenant/tenant1/application/", GET).userIdentity(USER_ID), new File("application-list.json"));
    addUserToHostedOperatorRole(HostedAthenzIdentities.from(HOSTED_VESPA_OPERATOR));
    // POST (deploy) an application to a zone - manual user deployment
    HttpEntity entity = createApplicationDeployData(applicationPackage, Optional.empty());
    tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/dev/region/us-west-1/instance/default/deploy", POST).data(entity).userIdentity(USER_ID), new File("deploy-result.json"));
    // POST (deploy) an application to a zone. This simulates calls done by our tenant pipeline.
    ApplicationId id = ApplicationId.from("tenant1", "application1", "default");
    long screwdriverProjectId = 123;
    addScrewdriverUserToDeployRole(SCREWDRIVER_ID, ATHENZ_TENANT_DOMAIN, // (Necessary but not provided in this API)
    new com.yahoo.vespa.hosted.controller.api.identifiers.ApplicationId(id.application().value()));
    // Trigger deployment from completion of component job
    controllerTester.jobCompletion(DeploymentJobs.JobType.component).application(id).projectId(screwdriverProjectId).uploadArtifact(applicationPackage).submit();
    // ... systemtest
    tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/test/region/us-east-1/instance/default/", POST).data(createApplicationDeployData(applicationPackage, Optional.of(screwdriverProjectId))).screwdriverIdentity(SCREWDRIVER_ID), new File("deploy-result.json"));
    tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/test/region/us-east-1/instance/default", DELETE).screwdriverIdentity(SCREWDRIVER_ID), "Deactivated tenant/tenant1/application/application1/environment/test/region/us-east-1/instance/default");
    // Called through the separate screwdriver/v1 API
    controllerTester.jobCompletion(DeploymentJobs.JobType.systemTest).application(id).projectId(screwdriverProjectId).submit();
    // ... staging
    tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/staging/region/us-east-3/instance/default/", POST).data(createApplicationDeployData(applicationPackage, Optional.of(screwdriverProjectId))).screwdriverIdentity(SCREWDRIVER_ID), new File("deploy-result.json"));
    tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/staging/region/us-east-3/instance/default", DELETE).screwdriverIdentity(SCREWDRIVER_ID), "Deactivated tenant/tenant1/application/application1/environment/staging/region/us-east-3/instance/default");
    controllerTester.jobCompletion(DeploymentJobs.JobType.stagingTest).application(id).projectId(screwdriverProjectId).submit();
    // ... prod zone
    tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/corp-us-east-1/instance/default/", POST).data(createApplicationDeployData(applicationPackage, Optional.of(screwdriverProjectId))).screwdriverIdentity(SCREWDRIVER_ID), new File("deploy-result.json"));
    controllerTester.jobCompletion(DeploymentJobs.JobType.productionCorpUsEast1).application(id).projectId(screwdriverProjectId).unsuccessful().submit();
    // GET tenant screwdriver projects
    tester.assertResponse(request("/application/v4/tenant-pipeline/", GET).userIdentity(USER_ID), new File("tenant-pipelines.json"));
    setDeploymentMaintainedInfo(controllerTester);
    // GET tenant application deployments
    tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1", GET).userIdentity(USER_ID), new File("application.json"));
    // GET an application deployment
    tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/corp-us-east-1/instance/default", GET).userIdentity(USER_ID), new File("deployment.json"));
    addIssues(controllerTester, ApplicationId.from("tenant1", "application1", "default"));
    // GET at root, with "&recursive=deployment", returns info about all tenants, their applications and their deployments
    tester.assertResponse(request("/application/v4/", GET).userIdentity(USER_ID).recursive("deployment"), new File("recursive-root.json"));
    // GET at root, with "&recursive=tenant", returns info about all tenants, with limited info about their applications.
    tester.assertResponse(request("/application/v4/", GET).userIdentity(USER_ID).recursive("tenant"), new File("recursive-until-tenant-root.json"));
    // GET at a tenant, with "&recursive=true", returns full info about their applications and their deployments
    tester.assertResponse(request("/application/v4/tenant/tenant1/", GET).userIdentity(USER_ID).recursive("true"), new File("tenant1-recursive.json"));
    // GET at an application, with "&recursive=true", returns full info about its deployments
    tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/", GET).userIdentity(USER_ID).recursive("true"), new File("application1-recursive.json"));
    // DELETE (cancel) ongoing change
    tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/deploying", DELETE).userIdentity(HOSTED_VESPA_OPERATOR), new File("application-deployment-cancelled.json"));
    // DELETE (cancel) again is a no-op
    tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/deploying", DELETE).userIdentity(HOSTED_VESPA_OPERATOR), new File("application-deployment-cancelled-no-op.json"));
    // POST triggering of a full deployment to an application (if version is omitted, current system version is used)
    tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/deploying", POST).userIdentity(HOSTED_VESPA_OPERATOR).data("6.1.0"), new File("application-deployment.json"));
    // POST a 'restart application' command
    tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/corp-us-east-1/instance/default/restart", POST).screwdriverIdentity(SCREWDRIVER_ID), "Requested restart of tenant/tenant1/application/application1/environment/prod/region/corp-us-east-1/instance/default");
    // POST a 'restart application' command with a host filter (other filters not supported yet)
    tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/corp-us-east-1/instance/default/restart?hostname=host1", POST).screwdriverIdentity(SCREWDRIVER_ID), "Requested restart of tenant/tenant1/application/application1/environment/prod/region/corp-us-east-1/instance/default");
    // POST a 'log' command
    tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/corp-us-east-1/instance/default/log", POST).screwdriverIdentity(SCREWDRIVER_ID), // Proxied to config server, not sure about the expected return format
    new File("log-response.json"));
    // GET (wait for) convergence
    tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/corp-us-east-1/instance/default/converge", GET).userIdentity(USER_ID), new File("convergence.json"));
    // GET services
    tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/corp-us-east-1/instance/default/service", GET).userIdentity(USER_ID), new File("services.json"));
    // GET service
    tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/corp-us-east-1/instance/default/service/storagenode-awe3slno6mmq2fye191y324jl/state/v1/", GET).userIdentity(USER_ID), new File("service.json"));
    // DELETE application with active deployments fails
    tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1", DELETE).userIdentity(USER_ID), new File("delete-with-active-deployments.json"), 400);
    // DELETE (deactivate) a deployment - dev
    tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/dev/region/us-west-1/instance/default", DELETE).userIdentity(USER_ID), "Deactivated tenant/tenant1/application/application1/environment/dev/region/us-west-1/instance/default");
    // DELETE (deactivate) a deployment - prod
    tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/corp-us-east-1/instance/default", DELETE).screwdriverIdentity(SCREWDRIVER_ID), "Deactivated tenant/tenant1/application/application1/environment/prod/region/corp-us-east-1/instance/default");
    // DELETE (deactivate) a deployment is idempotent
    tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/corp-us-east-1/instance/default", DELETE).screwdriverIdentity(SCREWDRIVER_ID), "Deactivated tenant/tenant1/application/application1/environment/prod/region/corp-us-east-1/instance/default");
    // PUT (create) the authenticated user
    byte[] data = new byte[0];
    tester.assertResponse(request("/application/v4/user?user=newuser&domain=by", PUT).data(data).userIdentity(new UserId("newuser")), new File("create-user-response.json"));
    // OPTIONS return 200 OK
    tester.assertResponse(request("/application/v4/", Request.Method.OPTIONS), "");
    // GET global rotation status
    tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/us-west-1/instance/default/global-rotation", GET).userIdentity(USER_ID), new File("global-rotation.json"));
    // GET global rotation override status
    tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/us-west-1/instance/default/global-rotation/override", GET).userIdentity(USER_ID), new File("global-rotation-get.json"));
    // SET global rotation override status
    tester.assertResponse(request("/application/v4/tenant/tenant2/application/application2/environment/prod/region/us-west-1/instance/default/global-rotation/override", PUT).userIdentity(USER_ID).data("{\"reason\":\"because i can\"}"), new File("global-rotation-put.json"));
    // DELETE global rotation override status
    tester.assertResponse(request("/application/v4/tenant/tenant2/application/application2/environment/prod/region/us-west-1/instance/default/global-rotation/override", DELETE).userIdentity(USER_ID).data("{\"reason\":\"because i can\"}"), new File("global-rotation-delete.json"));
    tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/promote", POST).screwdriverIdentity(SCREWDRIVER_ID), "{\"message\":\"Successfully copied environment hosted-verified-prod to hosted-instance_tenant1_application1_placeholder_component_default\"}");
    tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1/environment/prod/region/us-west-1/instance/default/promote", POST).screwdriverIdentity(SCREWDRIVER_ID), "{\"message\":\"Successfully copied environment hosted-instance_tenant1_application1_placeholder_component_default to hosted-instance_tenant1_application1_us-west-1_prod_default\"}");
    // DELETE an application
    tester.assertResponse(request("/application/v4/tenant/tenant1/application/application1", DELETE).userIdentity(USER_ID).nToken(N_TOKEN), "");
    // DELETE a tenant
    tester.assertResponse(request("/application/v4/tenant/tenant1", DELETE).userIdentity(USER_ID).nToken(N_TOKEN), new File("tenant-without-applications.json"));
    controllerTester.controller().deconstruct();
}
Also used : AthenzDomain(com.yahoo.vespa.athenz.api.AthenzDomain) HttpEntity(org.apache.http.HttpEntity) ContainerTester(com.yahoo.vespa.hosted.controller.restapi.ContainerTester) ContainerControllerTester(com.yahoo.vespa.hosted.controller.restapi.ContainerControllerTester) UserId(com.yahoo.vespa.hosted.controller.api.identifiers.UserId) ApplicationId(com.yahoo.config.provision.ApplicationId) File(java.io.File) ControllerContainerTest(com.yahoo.vespa.hosted.controller.restapi.ControllerContainerTest) Test(org.junit.Test)

Aggregations

UserId (com.yahoo.vespa.hosted.controller.api.identifiers.UserId)5 AthenzDomain (com.yahoo.vespa.athenz.api.AthenzDomain)3 ApplicationId (com.yahoo.config.provision.ApplicationId)2 AthenzPrincipal (com.yahoo.vespa.athenz.api.AthenzPrincipal)2 AthenzUser (com.yahoo.vespa.athenz.api.AthenzUser)2 NToken (com.yahoo.vespa.athenz.api.NToken)2 Tenant (com.yahoo.vespa.hosted.controller.api.Tenant)2 Joiner (com.google.common.base.Joiner)1 ImmutableSet (com.google.common.collect.ImmutableSet)1 Inject (com.google.inject.Inject)1 Version (com.yahoo.component.Version)1 DeploymentSpec (com.yahoo.config.application.api.DeploymentSpec)1 ApplicationName (com.yahoo.config.provision.ApplicationName)1 Environment (com.yahoo.config.provision.Environment)1 RegionName (com.yahoo.config.provision.RegionName)1 TenantName (com.yahoo.config.provision.TenantName)1 HttpRequest (com.yahoo.container.jdisc.HttpRequest)1 HttpResponse (com.yahoo.container.jdisc.HttpResponse)1 LoggingRequestHandler (com.yahoo.container.jdisc.LoggingRequestHandler)1 IOUtils (com.yahoo.io.IOUtils)1