Search in sources :

Example 11 with ResourceList

use of bio.terra.workspace.model.ResourceList in project terra-workspace-manager by DataBiosphere.

the class PrivateControlledAiNotebookInstanceLifecycle method doUserJourney.

@Override
@SuppressFBWarnings(value = "DLS_DEAD_LOCAL_STORE")
protected void doUserJourney(TestUserSpecification testUser, WorkspaceApi workspaceApi) throws Exception {
    CloudContextMaker.createGcpCloudContext(getWorkspaceId(), workspaceApi);
    workspaceApi.grantRole(new GrantRoleRequestBody().memberEmail(resourceUser.userEmail), getWorkspaceId(), IamRole.WRITER);
    workspaceApi.grantRole(new GrantRoleRequestBody().memberEmail(otherWorkspaceUser.userEmail), getWorkspaceId(), IamRole.WRITER);
    ControlledGcpResourceApi resourceUserApi = ClientTestUtils.getControlledGcpResourceClient(resourceUser, server);
    CreatedControlledGcpAiNotebookInstanceResult creationResult = NotebookUtils.makeControlledNotebookUserPrivate(getWorkspaceId(), instanceId, /*location=*/
    null, resourceUserApi);
    UUID resourceId = creationResult.getAiNotebookInstance().getMetadata().getResourceId();
    GcpAiNotebookInstanceResource resource = resourceUserApi.getAiNotebookInstance(getWorkspaceId(), resourceId);
    assertEquals(instanceId, resource.getAttributes().getInstanceId(), "Notebook instance id is correct in GET response from WSM");
    assertEquals(instanceId, creationResult.getAiNotebookInstance().getAttributes().getInstanceId(), "Notebook instance id is correct in create response from WSM");
    assertEquals(resourceUser.userEmail, resource.getMetadata().getControlledResourceMetadata().getPrivateResourceUser().getUserName(), "User is the private user of the notebook");
    assertEquals("us-central1-a", resource.getAttributes().getLocation(), "The notebook uses the default location because location is not specified.");
    createAControlledAiNotebookInstanceWithoutSpecifiedInstanceId_validInstanceIdIsGenerated(resourceUserApi);
    createAControlledAiNotebookInstanceWithoutSpecifiedInstanceId_specifyLocation(resourceUserApi);
    String instanceName = String.format("projects/%s/locations/%s/instances/%s", resource.getAttributes().getProjectId(), resource.getAttributes().getLocation(), resource.getAttributes().getInstanceId());
    AIPlatformNotebooks userNotebooks = ClientTestUtils.getAIPlatformNotebooksClient(resourceUser);
    assertTrue(NotebookUtils.userHasProxyAccess(creationResult, resourceUser, resource.getAttributes().getProjectId()), "Private resource user has access to their notebook");
    assertFalse(NotebookUtils.userHasProxyAccess(creationResult, otherWorkspaceUser, resource.getAttributes().getProjectId()), "Other workspace user does not have access to a private notebook");
    // The user should be able to stop their notebook.
    userNotebooks.projects().locations().instances().stop(instanceName, new StopInstanceRequest());
    // The user should not be able to directly delete their notebook.
    GoogleJsonResponseException directDeleteForbidden = assertThrows(GoogleJsonResponseException.class, () -> userNotebooks.projects().locations().instances().delete(instanceName).execute());
    assertEquals(HttpStatus.SC_FORBIDDEN, directDeleteForbidden.getStatusCode(), "User may not delete notebook directly on GCP");
    // Any workspace user should be able to enumerate all created notebooks, even though they can't
    // read or write them.
    ResourceApi otherUserApi = ClientTestUtils.getResourceClient(otherWorkspaceUser, server);
    ResourceList notebookList = otherUserApi.enumerateResources(getWorkspaceId(), 0, 5, ResourceType.AI_NOTEBOOK, StewardshipType.CONTROLLED);
    assertEquals(3, notebookList.getResources().size());
    MultiResourcesUtils.assertResourceType(ResourceType.AI_NOTEBOOK, notebookList);
    // Delete the AI Notebook through WSM.
    DeleteControlledGcpAiNotebookInstanceResult deleteResult = resourceUserApi.deleteAiNotebookInstance(new DeleteControlledGcpAiNotebookInstanceRequest().jobControl(new JobControl().id(UUID.randomUUID().toString())), getWorkspaceId(), resourceId);
    String deleteJobId = deleteResult.getJobReport().getId();
    deleteResult = ClientTestUtils.pollWhileRunning(deleteResult, () -> resourceUserApi.getDeleteAiNotebookInstanceResult(getWorkspaceId(), deleteJobId), DeleteControlledGcpAiNotebookInstanceResult::getJobReport, Duration.ofSeconds(10));
    ClientTestUtils.assertJobSuccess("delete ai notebook", deleteResult.getJobReport(), deleteResult.getErrorReport());
    // Verify the notebook was deleted from WSM metadata.
    ApiException notebookIsMissing = assertThrows(ApiException.class, () -> resourceUserApi.getAiNotebookInstance(getWorkspaceId(), resourceId), "Notebook is deleted from WSM");
    assertEquals(HttpStatus.SC_NOT_FOUND, notebookIsMissing.getCode(), "Error from WSM is 404");
    // Verify the notebook was deleted from GCP.
    GoogleJsonResponseException notebookNotFound = assertThrows(GoogleJsonResponseException.class, () -> userNotebooks.projects().locations().instances().get(instanceName).execute(), "Notebook is deleted from GCP");
    // GCP may respond with either 403 or 404 depending on how quickly this is called after deleting
    // the notebook. Either response is valid in this case.
    assertThat("Error from GCP is 403 or 404", notebookNotFound.getStatusCode(), anyOf(equalTo(HttpStatus.SC_NOT_FOUND), equalTo(HttpStatus.SC_FORBIDDEN)));
}
Also used : GrantRoleRequestBody(bio.terra.workspace.model.GrantRoleRequestBody) CreatedControlledGcpAiNotebookInstanceResult(bio.terra.workspace.model.CreatedControlledGcpAiNotebookInstanceResult) DeleteControlledGcpAiNotebookInstanceRequest(bio.terra.workspace.model.DeleteControlledGcpAiNotebookInstanceRequest) DeleteControlledGcpAiNotebookInstanceResult(bio.terra.workspace.model.DeleteControlledGcpAiNotebookInstanceResult) JobControl(bio.terra.workspace.model.JobControl) AIPlatformNotebooks(com.google.api.services.notebooks.v1.AIPlatformNotebooks) GcpAiNotebookInstanceResource(bio.terra.workspace.model.GcpAiNotebookInstanceResource) StopInstanceRequest(com.google.api.services.notebooks.v1.model.StopInstanceRequest) GoogleJsonResponseException(com.google.api.client.googleapis.json.GoogleJsonResponseException) ControlledGcpResourceApi(bio.terra.workspace.api.ControlledGcpResourceApi) ResourceApi(bio.terra.workspace.api.ResourceApi) ResourceList(bio.terra.workspace.model.ResourceList) ControlledGcpResourceApi(bio.terra.workspace.api.ControlledGcpResourceApi) UUID(java.util.UUID) ApiException(bio.terra.workspace.client.ApiException) SuppressFBWarnings(edu.umd.cs.findbugs.annotations.SuppressFBWarnings)

Example 12 with ResourceList

use of bio.terra.workspace.model.ResourceList in project terra-workspace-manager by DataBiosphere.

the class ReferencedGcsResourceLifecycle method doUserJourney.

@Override
protected void doUserJourney(TestUserSpecification testUser, WorkspaceApi workspaceApi) throws Exception {
    ReferencedGcpResourceApi referencedGcpResourceApi = ClientTestUtils.getReferencedGcpResourceClient(testUser, server);
    // Grant secondary users READER permission in the workspace.
    workspaceApi.grantRole(new GrantRoleRequestBody().memberEmail(partialAccessUser.userEmail), getWorkspaceId(), IamRole.READER);
    workspaceApi.grantRole(new GrantRoleRequestBody().memberEmail(noAccessUser.userEmail), getWorkspaceId(), IamRole.READER);
    // Create the references
    GcpGcsBucketResource referencedBucket = GcsBucketUtils.makeGcsBucketReference(gcsUniformAccessBucketAttributes, referencedGcpResourceApi, getWorkspaceId(), MultiResourcesUtils.makeName(), CloningInstructionsEnum.REFERENCE);
    bucketResourceId = referencedBucket.getMetadata().getResourceId();
    GcpGcsBucketResource fineGrainedBucket = GcsBucketUtils.makeGcsBucketReference(gcsFineGrainedAccessBucketAttributes, referencedGcpResourceApi, getWorkspaceId(), MultiResourcesUtils.makeName(), CloningInstructionsEnum.REFERENCE);
    fineGrainedBucketResourceId = fineGrainedBucket.getMetadata().getResourceId();
    GcpGcsObjectResource referencedGcsFile = GcsBucketObjectUtils.makeGcsObjectReference(gcsFileAttributes, referencedGcpResourceApi, getWorkspaceId(), MultiResourcesUtils.makeName(), CloningInstructionsEnum.REFERENCE);
    fileResourceId = referencedGcsFile.getMetadata().getResourceId();
    GcpGcsObjectResource referencedGcsFolder = GcsBucketObjectUtils.makeGcsObjectReference(gcsFolderAttributes, referencedGcpResourceApi, getWorkspaceId(), MultiResourcesUtils.makeName(), CloningInstructionsEnum.REFERENCE);
    folderResourceId = referencedGcsFolder.getMetadata().getResourceId();
    // Get the references
    testGetReferences(referencedBucket, fineGrainedBucket, referencedGcsFile, referencedGcsFolder, referencedGcpResourceApi);
    // Create a second workspace to clone references into, owned by the same user
    testCloneReference(referencedBucket, fineGrainedBucket, referencedGcsFile, referencedGcsFolder, referencedGcpResourceApi, workspaceApi);
    // Validate reference access
    testValidateReference(testUser);
    // Update the references
    testUpdateReferences(fineGrainedBucket, referencedGcpResourceApi);
    // Delete the references
    referencedGcpResourceApi.deleteBucketReference(getWorkspaceId(), bucketResourceId);
    referencedGcpResourceApi.deleteBucketReference(getWorkspaceId(), fineGrainedBucketResourceId);
    referencedGcpResourceApi.deleteGcsObjectReference(getWorkspaceId(), fileResourceId);
    referencedGcpResourceApi.deleteGcsObjectReference(getWorkspaceId(), folderResourceId);
    // Enumerating all resources with no filters should be empty
    ResourceApi resourceApi = ClientTestUtils.getResourceClient(testUser, server);
    ResourceList enumerateResult = resourceApi.enumerateResources(getWorkspaceId(), 0, 100, null, null);
    assertTrue(enumerateResult.getResources().isEmpty());
}
Also used : GcpGcsBucketResource(bio.terra.workspace.model.GcpGcsBucketResource) GcpGcsObjectResource(bio.terra.workspace.model.GcpGcsObjectResource) ReferencedGcpResourceApi(bio.terra.workspace.api.ReferencedGcpResourceApi) ResourceApi(bio.terra.workspace.api.ResourceApi) ResourceList(bio.terra.workspace.model.ResourceList) GrantRoleRequestBody(bio.terra.workspace.model.GrantRoleRequestBody) ReferencedGcpResourceApi(bio.terra.workspace.api.ReferencedGcpResourceApi)

Example 13 with ResourceList

use of bio.terra.workspace.model.ResourceList in project terra-workspace-manager by DataBiosphere.

the class ReferencedGcsResourceLifecycle method testGetReferences.

private void testGetReferences(GcpGcsBucketResource uniformBucketReference, GcpGcsBucketResource fineGrainedBucketReference, GcpGcsObjectResource fileReference, GcpGcsObjectResource folderReference, ReferencedGcpResourceApi referencedGcpResourceApi) throws Exception {
    GcpGcsBucketResource fetchedBucket = referencedGcpResourceApi.getBucketReference(getWorkspaceId(), bucketResourceId);
    assertEquals(uniformBucketReference, fetchedBucket);
    GcpGcsBucketResource fetchedFineGrainedBucket = referencedGcpResourceApi.getBucketReference(getWorkspaceId(), fineGrainedBucketResourceId);
    assertEquals(fineGrainedBucketReference, fetchedFineGrainedBucket);
    GcpGcsObjectResource fetchedGcsFile = referencedGcpResourceApi.getGcsObjectReference(getWorkspaceId(), fileResourceId);
    assertEquals(fileReference, fetchedGcsFile);
    GcpGcsObjectResource fetchedGcsFolder = referencedGcpResourceApi.getGcsObjectReference(getWorkspaceId(), folderResourceId);
    assertEquals(folderReference, fetchedGcsFolder);
    // Enumerate the references
    // Any workspace member can view references in WSM, even if they can't view the underlying cloud
    // resource or contents.
    ResourceApi noAccessApi = ClientTestUtils.getResourceClient(noAccessUser, server);
    ResourceList referenceList = noAccessApi.enumerateResources(getWorkspaceId(), 0, 5, /*referenceType=*/
    null, StewardshipType.REFERENCED);
    assertEquals(4, referenceList.getResources().size());
    ResourceList bucketList = noAccessApi.enumerateResources(getWorkspaceId(), 0, 5, /*referenceType=*/
    ResourceType.GCS_BUCKET, StewardshipType.REFERENCED);
    assertEquals(2, bucketList.getResources().size());
    MultiResourcesUtils.assertResourceType(ResourceType.GCS_BUCKET, bucketList);
    ResourceList fileList = noAccessApi.enumerateResources(getWorkspaceId(), 0, 5, /*referenceType=*/
    ResourceType.GCS_OBJECT, StewardshipType.REFERENCED);
    assertEquals(2, fileList.getResources().size());
    MultiResourcesUtils.assertResourceType(ResourceType.GCS_OBJECT, fileList);
}
Also used : GcpGcsBucketResource(bio.terra.workspace.model.GcpGcsBucketResource) GcpGcsObjectResource(bio.terra.workspace.model.GcpGcsObjectResource) ReferencedGcpResourceApi(bio.terra.workspace.api.ReferencedGcpResourceApi) ResourceApi(bio.terra.workspace.api.ResourceApi) ResourceList(bio.terra.workspace.model.ResourceList)

Example 14 with ResourceList

use of bio.terra.workspace.model.ResourceList in project terra-workspace-manager by DataBiosphere.

the class EnumerateResources method doUserJourney.

@Override
public void doUserJourney(TestUserSpecification testUser, WorkspaceApi workspaceApi) throws Exception {
    // Add second user to the workspace as a reader
    workspaceApi.grantRole(new GrantRoleRequestBody().memberEmail(workspaceReader.userEmail), getWorkspaceId(), IamRole.READER);
    // Case 1: fetch all
    ResourceList enumList = ownerResourceApi.enumerateResources(getWorkspaceId(), 0, RESOURCE_COUNT, null, null);
    logResult("fetchall", enumList);
    // Make sure we got all of the expected ids
    matchFullResourceList(enumList.getResources());
    // Repeat case 1 as the workspace reader.
    // As this is the first operation after modifying workspace IAM groups, retry here to compensate
    // for the delay in GCP IAM propagation.
    ResourceList readerEnumList = ClientTestUtils.getWithRetryOnException(() -> readerResourceApi.enumerateResources(getWorkspaceId(), 0, RESOURCE_COUNT, null, null));
    logResult("fetchall reader", readerEnumList);
    matchFullResourceList(readerEnumList.getResources());
    // Case 2: fetch by pages
    ResourceList page1List = ownerResourceApi.enumerateResources(getWorkspaceId(), 0, PAGE_SIZE, null, null);
    logResult("page1", page1List);
    assertThat(page1List.getResources().size(), equalTo(PAGE_SIZE));
    ResourceList page2List = ownerResourceApi.enumerateResources(getWorkspaceId(), PAGE_SIZE, PAGE_SIZE, null, null);
    logResult("page2", page2List);
    assertThat(page2List.getResources().size(), equalTo(PAGE_SIZE));
    ResourceList page3List = ownerResourceApi.enumerateResources(getWorkspaceId(), 2 * PAGE_SIZE, PAGE_SIZE, null, null);
    logResult("page3", page3List);
    assertThat(page3List.getResources().size(), lessThan(PAGE_SIZE));
    List<ResourceDescription> descriptionList = new ArrayList<>();
    descriptionList.addAll(page1List.getResources());
    descriptionList.addAll(page2List.getResources());
    descriptionList.addAll(page3List.getResources());
    matchFullResourceList(descriptionList);
    // Case 3: no results if offset is too high
    ResourceList enumEmptyList = ownerResourceApi.enumerateResources(getWorkspaceId(), 10 * PAGE_SIZE, PAGE_SIZE, null, null);
    assertThat(enumEmptyList.getResources().size(), equalTo(0));
    // Case 4: filter by resource type
    ResourceList buckets = ownerResourceApi.enumerateResources(getWorkspaceId(), 0, RESOURCE_COUNT, ResourceType.GCS_BUCKET, null);
    logResult("buckets", buckets);
    long expectedBuckets = resourceList.stream().filter(m -> m.getResourceType() == ResourceType.GCS_BUCKET).count();
    logger.info("Counted {} buckets created", expectedBuckets);
    // Note - assertThat exits out on an int -> long compare, so just don't do that.
    long actualBuckets = buckets.getResources().size();
    assertThat(actualBuckets, equalTo(expectedBuckets));
    // Case 5: filter by stewardship type
    ResourceList referencedList = ownerResourceApi.enumerateResources(getWorkspaceId(), 0, RESOURCE_COUNT, null, StewardshipType.REFERENCED);
    logResult("referenced", referencedList);
    long expectedReferenced = resourceList.stream().filter(m -> m.getStewardshipType() == StewardshipType.REFERENCED).count();
    logger.info("Counted {} referenced created", expectedReferenced);
    long actualReferenced = referencedList.getResources().size();
    assertThat(actualReferenced, equalTo(expectedReferenced));
    // Case 6: filter by resource and stewardship
    ResourceList controlledBucketList = ownerResourceApi.enumerateResources(getWorkspaceId(), 0, RESOURCE_COUNT, ResourceType.GCS_BUCKET, StewardshipType.CONTROLLED);
    logResult("controlledBucket", controlledBucketList);
    long expectedControlledBuckets = resourceList.stream().filter(m -> (m.getStewardshipType() == StewardshipType.CONTROLLED && m.getResourceType() == ResourceType.GCS_BUCKET)).count();
    logger.info("Counted {} controlled buckets created", expectedControlledBuckets);
    long actualControlledBuckets = controlledBucketList.getResources().size();
    assertThat(actualControlledBuckets, equalTo(expectedControlledBuckets));
    // Case 7: validate error on invalid pagination params
    ApiException invalidPaginationException = assertThrows(ApiException.class, () -> ownerResourceApi.enumerateResources(getWorkspaceId(), -11, 2, ResourceType.GCS_BUCKET, StewardshipType.CONTROLLED));
    assertThat(invalidPaginationException.getMessage(), containsString("Invalid pagination"));
    invalidPaginationException = assertThrows(ApiException.class, () -> ownerResourceApi.enumerateResources(getWorkspaceId(), 0, 0, ResourceType.GCS_BUCKET, StewardshipType.CONTROLLED));
    assertThat(invalidPaginationException.getMessage(), containsString("Invalid pagination"));
}
Also used : Assertions.assertThrows(org.junit.jupiter.api.Assertions.assertThrows) ControlledGcpResourceApi(bio.terra.workspace.api.ControlledGcpResourceApi) ClientTestUtils(scripts.utils.ClientTestUtils) CloudContextMaker(scripts.utils.CloudContextMaker) LoggerFactory(org.slf4j.LoggerFactory) ResourceList(bio.terra.workspace.model.ResourceList) ArrayList(java.util.ArrayList) WorkspaceAllocateTestScriptBase(scripts.utils.WorkspaceAllocateTestScriptBase) Matchers.lessThan(org.hamcrest.Matchers.lessThan) MultiResourcesUtils(scripts.utils.MultiResourcesUtils) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) ReferencedGcpResourceApi(bio.terra.workspace.api.ReferencedGcpResourceApi) StewardshipType(bio.terra.workspace.model.StewardshipType) ControlledResourceMetadata(bio.terra.workspace.model.ControlledResourceMetadata) WorkspaceApi(bio.terra.workspace.api.WorkspaceApi) ResourceMetadata(bio.terra.workspace.model.ResourceMetadata) ResourceType(bio.terra.workspace.model.ResourceType) Logger(org.slf4j.Logger) ApiException(bio.terra.workspace.client.ApiException) ApiClient(bio.terra.workspace.client.ApiClient) UUID(java.util.UUID) Collectors(java.util.stream.Collectors) IamRole(bio.terra.workspace.model.IamRole) List(java.util.List) TestUserSpecification(bio.terra.testrunner.runner.config.TestUserSpecification) Matchers.equalTo(org.hamcrest.Matchers.equalTo) GrantRoleRequestBody(bio.terra.workspace.model.GrantRoleRequestBody) ResourceDescription(bio.terra.workspace.model.ResourceDescription) Matchers.greaterThan(org.hamcrest.Matchers.greaterThan) Matchers.containsString(org.hamcrest.Matchers.containsString) ResourceApi(bio.terra.workspace.api.ResourceApi) ResourceList(bio.terra.workspace.model.ResourceList) GrantRoleRequestBody(bio.terra.workspace.model.GrantRoleRequestBody) ResourceDescription(bio.terra.workspace.model.ResourceDescription) ArrayList(java.util.ArrayList) ApiException(bio.terra.workspace.client.ApiException)

Example 15 with ResourceList

use of bio.terra.workspace.model.ResourceList in project terra-workspace-manager by DataBiosphere.

the class ReferencedGitRepoLifecycle method doUserJourney.

@Override
protected void doUserJourney(TestUserSpecification testUser, WorkspaceApi workspaceApi) throws Exception {
    ReferencedGcpResourceApi referencedGcpResourceApi = ClientTestUtils.getReferencedGcpResourceClient(testUser, server);
    // Create the reference
    GitRepoResource gitResource = GitRepoUtils.makeGitRepoReference(gitRepoAttributes, referencedGcpResourceApi, getWorkspaceId(), MultiResourcesUtils.makeName());
    gitResourceId = gitResource.getMetadata().getResourceId();
    // Read the reference
    ResourceApi resourceApi = ClientTestUtils.getResourceClient(testUser, server);
    testGetReference(gitResource, referencedGcpResourceApi, resourceApi);
    // Clone the reference
    testCloneReference(gitResource, referencedGcpResourceApi, workspaceApi);
    // No validation checks yet, we don't validate access to git repos.
    // Update the reference
    testUpdateReference(referencedGcpResourceApi);
    // Delete the reference
    referencedGcpResourceApi.deleteGitRepoReference(getWorkspaceId(), gitResourceId);
    // Enumerating all resources with no filters should be empty
    ResourceList enumerateResult = resourceApi.enumerateResources(getWorkspaceId(), 0, 100, null, null);
    assertTrue(enumerateResult.getResources().isEmpty());
}
Also used : ReferencedGcpResourceApi(bio.terra.workspace.api.ReferencedGcpResourceApi) ResourceApi(bio.terra.workspace.api.ResourceApi) ResourceList(bio.terra.workspace.model.ResourceList) GitRepoResource(bio.terra.workspace.model.GitRepoResource) ReferencedGcpResourceApi(bio.terra.workspace.api.ReferencedGcpResourceApi)

Aggregations

ResourceList (bio.terra.workspace.model.ResourceList)16 ResourceApi (bio.terra.workspace.api.ResourceApi)14 GrantRoleRequestBody (bio.terra.workspace.model.GrantRoleRequestBody)9 ControlledGcpResourceApi (bio.terra.workspace.api.ControlledGcpResourceApi)8 ReferencedGcpResourceApi (bio.terra.workspace.api.ReferencedGcpResourceApi)8 ApiException (bio.terra.workspace.client.ApiException)6 UUID (java.util.UUID)5 GcpGcsBucketResource (bio.terra.workspace.model.GcpGcsBucketResource)4 ApiClient (bio.terra.workspace.client.ApiClient)3 CreatedControlledGcpGcsBucket (bio.terra.workspace.model.CreatedControlledGcpGcsBucket)3 GcpBigQueryDatasetResource (bio.terra.workspace.model.GcpBigQueryDatasetResource)3 WorkspaceApplicationApi (bio.terra.workspace.api.WorkspaceApplicationApi)2 DataRepoSnapshotResource (bio.terra.workspace.model.DataRepoSnapshotResource)2 GcpBigQueryDataTableResource (bio.terra.workspace.model.GcpBigQueryDataTableResource)2 GcpGcsObjectResource (bio.terra.workspace.model.GcpGcsObjectResource)2 GitRepoResource (bio.terra.workspace.model.GitRepoResource)2 ResourceDescription (bio.terra.workspace.model.ResourceDescription)2 WorkspaceApplicationDescription (bio.terra.workspace.model.WorkspaceApplicationDescription)2 Bucket (com.google.cloud.storage.Bucket)2 Storage (com.google.cloud.storage.Storage)2