From d9d90999147a72d55a6b803d104591aa27ef66e1 Mon Sep 17 00:00:00 2001 From: Josh Ladieu <111856+jladieu@users.noreply.github.com> Date: Mon, 13 Nov 2023 12:42:28 -0500 Subject: [PATCH] AJ-1451: More pacts with workspacemanager (#403) AJ-1451: More pacts with `workspacemanager` Add additional contract coverage to `WsmPactTest` to cover interactions with `workspacemanager`. --- .../dataimport/TdrSnapshotSupport.java | 4 +- .../{TDRPactTest.java => TdrPactTest.java} | 36 +- .../pact/WsmPactTest.java | 411 +++++++++++++++--- 3 files changed, 373 insertions(+), 78 deletions(-) rename service/src/test/java/org/databiosphere/workspacedataservice/pact/{TDRPactTest.java => TdrPactTest.java} (77%) diff --git a/service/src/main/java/org/databiosphere/workspacedataservice/dataimport/TdrSnapshotSupport.java b/service/src/main/java/org/databiosphere/workspacedataservice/dataimport/TdrSnapshotSupport.java index 3dfb2498b..f8c96a08d 100644 --- a/service/src/main/java/org/databiosphere/workspacedataservice/dataimport/TdrSnapshotSupport.java +++ b/service/src/main/java/org/databiosphere/workspacedataservice/dataimport/TdrSnapshotSupport.java @@ -4,6 +4,7 @@ import bio.terra.workspace.model.ResourceAttributesUnion; import bio.terra.workspace.model.ResourceDescription; import bio.terra.workspace.model.ResourceList; +import com.google.common.annotations.VisibleForTesting; import java.util.List; import java.util.Objects; import java.util.UUID; @@ -36,7 +37,8 @@ public TdrSnapshotSupport( * @param pageSize how many references to return in each paginated request to WSM * @return the list of unique ids for all pre-existing snapshot references */ - protected List existingPolicySnapshotIds(int pageSize) { + @VisibleForTesting + public List existingPolicySnapshotIds(int pageSize) { return extractSnapshotIds(listAllSnapshots(pageSize)); } diff --git a/service/src/test/java/org/databiosphere/workspacedataservice/pact/TDRPactTest.java b/service/src/test/java/org/databiosphere/workspacedataservice/pact/TdrPactTest.java similarity index 77% rename from service/src/test/java/org/databiosphere/workspacedataservice/pact/TDRPactTest.java rename to service/src/test/java/org/databiosphere/workspacedataservice/pact/TdrPactTest.java index c6b51ce66..ff776ea20 100644 --- a/service/src/test/java/org/databiosphere/workspacedataservice/pact/TDRPactTest.java +++ b/service/src/test/java/org/databiosphere/workspacedataservice/pact/TdrPactTest.java @@ -7,9 +7,8 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import au.com.dius.pact.consumer.MockServer; -import au.com.dius.pact.consumer.dsl.PactDslJsonBody; import au.com.dius.pact.consumer.dsl.PactDslWithProvider; -import au.com.dius.pact.consumer.junit5.PactConsumerTestExt; +import au.com.dius.pact.consumer.junit5.PactConsumerTest; import au.com.dius.pact.consumer.junit5.PactTestFor; import au.com.dius.pact.core.model.PactSpecVersion; import au.com.dius.pact.core.model.RequestResponsePact; @@ -21,29 +20,16 @@ import org.databiosphere.workspacedataservice.datarepo.DataRepoDao; import org.databiosphere.workspacedataservice.datarepo.DataRepoException; import org.databiosphere.workspacedataservice.datarepo.HttpDataRepoClientFactory; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.ServletRequestAttributes; @Tag("pact-test") -@ExtendWith(PactConsumerTestExt.class) -class TDRPactTest { - - @BeforeEach - void setUp() { - // Without this setup, the HttpClient throws a "No thread-bound request found" error - MockHttpServletRequest request = new MockHttpServletRequest(); - // Set the mock request as the current request context - RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request)); - } - +@PactConsumerTest +@PactTestFor(providerName = "datarepo", pactVersion = PactSpecVersion.V3) +class TdrPactTest { static final UUID dummySnapshotId = UUID.fromString("12345678-abc9-012d-3456-e7fab89cd01e"); - @Pact(consumer = "wds", provider = "datarepo") + @Pact(consumer = "wds") public RequestResponsePact noSnapshotPact(PactDslWithProvider builder) { return builder .given("snapshot with given id doesn't exist", Map.of("id", dummySnapshotId.toString())) @@ -56,7 +42,7 @@ public RequestResponsePact noSnapshotPact(PactDslWithProvider builder) { .toPact(); } - @Pact(consumer = "wds", provider = "datarepo") + @Pact(consumer = "wds") public RequestResponsePact noAccessToSnapshotPact(PactDslWithProvider builder) { return builder .given( @@ -71,10 +57,8 @@ public RequestResponsePact noAccessToSnapshotPact(PactDslWithProvider builder) { .toPact(); } - @Pact(consumer = "wds", provider = "datarepo") + @Pact(consumer = "wds") public RequestResponsePact userHasAccessToSnapshotPact(PactDslWithProvider builder) { - var snapshotResponseShape = - new PactDslJsonBody().stringValue("id", dummySnapshotId.toString()).stringType("name"); return builder .given( "user has access to snapshot with given id", Map.of("id", dummySnapshotId.toString())) @@ -101,7 +85,7 @@ public RequestResponsePact userHasAccessToSnapshotPact(PactDslWithProvider build } @Test - @PactTestFor(pactMethod = "noSnapshotPact", pactVersion = PactSpecVersion.V3) + @PactTestFor(pactMethod = "noSnapshotPact") void testNoSnapshot(MockServer mockServer) { DataRepoClientFactory clientFactory = new HttpDataRepoClientFactory(mockServer.getUrl()); DataRepoDao dataRepoDao = new DataRepoDao(clientFactory); @@ -113,7 +97,7 @@ void testNoSnapshot(MockServer mockServer) { } @Test - @PactTestFor(pactMethod = "noAccessToSnapshotPact", pactVersion = PactSpecVersion.V3) + @PactTestFor(pactMethod = "noAccessToSnapshotPact") void testNoAccessToSnapshot(MockServer mockServer) { DataRepoClientFactory clientFactory = new HttpDataRepoClientFactory(mockServer.getUrl()); DataRepoDao dataRepoDao = new DataRepoDao(clientFactory); @@ -125,7 +109,7 @@ void testNoAccessToSnapshot(MockServer mockServer) { } @Test - @PactTestFor(pactMethod = "userHasAccessToSnapshotPact", pactVersion = PactSpecVersion.V3) + @PactTestFor(pactMethod = "userHasAccessToSnapshotPact") void testUserHasAccessToSnapshot(MockServer mockServer) { DataRepoClientFactory clientFactory = new HttpDataRepoClientFactory(mockServer.getUrl()); DataRepoDao dataRepoDao = new DataRepoDao(clientFactory); diff --git a/service/src/test/java/org/databiosphere/workspacedataservice/pact/WsmPactTest.java b/service/src/test/java/org/databiosphere/workspacedataservice/pact/WsmPactTest.java index 17d2ef0d4..3ace8cd16 100644 --- a/service/src/test/java/org/databiosphere/workspacedataservice/pact/WsmPactTest.java +++ b/service/src/test/java/org/databiosphere/workspacedataservice/pact/WsmPactTest.java @@ -2,70 +2,64 @@ import static au.com.dius.pact.consumer.dsl.LambdaDsl.newJsonBody; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import au.com.dius.pact.consumer.MockServer; import au.com.dius.pact.consumer.dsl.DslPart; import au.com.dius.pact.consumer.dsl.PactDslWithProvider; -import au.com.dius.pact.consumer.junit5.PactConsumerTestExt; +import au.com.dius.pact.consumer.junit5.PactConsumerTest; import au.com.dius.pact.consumer.junit5.PactTestFor; import au.com.dius.pact.core.model.PactSpecVersion; import au.com.dius.pact.core.model.RequestResponsePact; import au.com.dius.pact.core.model.annotations.Pact; import bio.terra.datarepo.model.SnapshotModel; import bio.terra.workspace.model.CloningInstructionsEnum; +import bio.terra.workspace.model.ResourceType; +import bio.terra.workspace.model.StewardshipType; import java.util.HashMap; import java.util.Map; import java.util.UUID; +import org.databiosphere.workspacedataservice.dataimport.TdrSnapshotSupport; import org.databiosphere.workspacedataservice.retry.RestClientRetry; import org.databiosphere.workspacedataservice.workspacemanager.HttpWorkspaceManagerClientFactory; import org.databiosphere.workspacedataservice.workspacemanager.WorkspaceManagerClientFactory; import org.databiosphere.workspacedataservice.workspacemanager.WorkspaceManagerDao; import org.databiosphere.workspacedataservice.workspacemanager.WorkspaceManagerException; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.ServletRequestAttributes; +import org.springframework.http.HttpStatus; @Tag("pact-test") -@ExtendWith(PactConsumerTestExt.class) +@PactConsumerTest +@PactTestFor(providerName = "workspacemanager", pactVersion = PactSpecVersion.V3) public class WsmPactTest { + public static final int NUM_SNAPSHOTS_THAT_EXIST = 3; + public static final int NUM_SNAPSHOTS_REQUESTED = NUM_SNAPSHOTS_THAT_EXIST + 2; // copied from DslPart.UUID_REGEX, used to configure Pact to accept a wildcard UUID as the // workspaceId path param private static final String UUID_REGEX_PATTERN = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"; - // the two UUIDs are hardcoded to prevent churn in pactfiles, and intended to be human memorable + // UUIDs are hardcoded to prevent churn in pactfiles, and intended to be human memorable private static final UUID WORKSPACE_UUID = UUID.fromString("facade00-0000-4000-a000-000000000000"); private static final UUID SNAPSHOT_UUID = UUID.fromString("decade00-0000-4000-a000-000000000000"); + private static final UUID RESOURCE_UUID = UUID.fromString("5ca1ab1e-0000-4000-a000-000000000000"); private static final String SNAPSHOT_NAME = "hardcodedSnapshotName"; private static final String SNAPSHOT_CREATOR_EMAIL = "snapshot.creator@e.mail"; - @BeforeEach - void setUp() { - // Without this setup, the HttpClient throws a "No thread-bound request found" error - RequestContextHolder.setRequestAttributes( - new ServletRequestAttributes(new MockHttpServletRequest())); - } - - private String snapshotPath(String workspaceIdPart) { - return String.format( - "/api/workspaces/v1/%s/resources/referenced/datarepo/snapshots", workspaceIdPart); - } - - @Pact(consumer = "wds", provider = "workspacemanager") + @Pact(consumer = "wds") RequestResponsePact linkSnapshotForPolicySuccess(PactDslWithProvider builder) { return builder - .given("a workspace with the given id exists", Map.of("id", WORKSPACE_UUID.toString())) + .given("a workspace with the given {id} exists", Map.of("id", WORKSPACE_UUID.toString())) .given("authenticated with the given email", Map.of("email", SNAPSHOT_CREATOR_EMAIL)) .given("policies allowing snapshot reference creation") .uponReceiving("a request to create a snapshot reference") - .matchPath(snapshotPath(UUID_REGEX_PATTERN), snapshotPath(WORKSPACE_UUID.toString())) .method("POST") + .matchPath(snapshotPath(UUID_REGEX_PATTERN), snapshotPath(WORKSPACE_UUID.toString())) .headers(contentTypeJson()) .body(createSnapshotReferenceBody(SNAPSHOT_NAME)) .willRespondWith() @@ -81,19 +75,24 @@ RequestResponsePact linkSnapshotForPolicySuccess(PactDslWithProvider builder) { .toPact(); } - private String conditions(String... conditions) { - return String.join(" and ", conditions); + @Test + @PactTestFor(pactMethod = "linkSnapshotForPolicySuccess") + void testLinkSnapshotForPolicySuccess(MockServer mockServer) { + var wsmDao = buildWsmDao(mockServer); + var snapshotModel = buildSnapshotModel(); + + assertDoesNotThrow(() -> wsmDao.linkSnapshotForPolicy(snapshotModel)); } - @Pact(consumer = "wds", provider = "workspacemanager") + @Pact(consumer = "wds") RequestResponsePact linkSnapshotForPolicyConflict(PactDslWithProvider builder) { return builder .given("a workspace with the given id exists", Map.of("id", WORKSPACE_UUID.toString())) .given("authenticated with the given email", Map.of("email", SNAPSHOT_CREATOR_EMAIL)) .given("policies preventing snapshot reference creation") .uponReceiving("a request to create a snapshot reference") - .matchPath(snapshotPath(UUID_REGEX_PATTERN), snapshotPath(WORKSPACE_UUID.toString())) .method("POST") + .matchPath(snapshotPath(UUID_REGEX_PATTERN), snapshotPath(WORKSPACE_UUID.toString())) .headers(contentTypeJson()) .body(createSnapshotReferenceBody(SNAPSHOT_NAME)) .willRespondWith() @@ -111,22 +110,7 @@ RequestResponsePact linkSnapshotForPolicyConflict(PactDslWithProvider builder) { } @Test - @PactTestFor( - pactMethod = "linkSnapshotForPolicySuccess", - providerName = "workspacemanager", - pactVersion = PactSpecVersion.V3) - void testLinkSnapshotForPolicySuccess(MockServer mockServer) { - var wsmDao = buildWsmDao(mockServer); - var snapshotModel = buildSnapshotModel(); - - assertDoesNotThrow(() -> wsmDao.linkSnapshotForPolicy(snapshotModel)); - } - - @Test - @PactTestFor( - pactMethod = "linkSnapshotForPolicyConflict", - providerName = "workspacemanager", - pactVersion = PactSpecVersion.V3) + @PactTestFor(pactMethod = "linkSnapshotForPolicyConflict") void testLinkSnapshotForPolicyConflict(MockServer mockServer) { var wsmDao = buildWsmDao(mockServer); var snapshotModel = buildSnapshotModel(); @@ -139,12 +123,6 @@ private SnapshotModel buildSnapshotModel() { return new SnapshotModel().id(SNAPSHOT_UUID).name(SNAPSHOT_NAME); } - private WorkspaceManagerDao buildWsmDao(MockServer mockServer) { - WorkspaceManagerClientFactory clientFactory = - new HttpWorkspaceManagerClientFactory(mockServer.getUrl()); - return new WorkspaceManagerDao(clientFactory, WORKSPACE_UUID.toString(), new RestClientRetry()); - } - private DslPart createSnapshotReferenceBody(String snapshotName) { // metadata.name is a composite of _ String nameFormatString = String.format("'%s'_yyyyMMddHHmmss", snapshotName); @@ -155,7 +133,7 @@ private DslPart createSnapshotReferenceBody(String snapshotName) { "snapshot", snapshot -> { snapshot.stringValue("instanceName", "terra"); - snapshot.uuid("snapshot"); + snapshot.uuid("snapshot", SNAPSHOT_UUID); }); body.object( "metadata", @@ -177,11 +155,342 @@ private DslPart createSnapshotReferenceBody(String snapshotName) { .build(); } - private Map contentTypeJson() { + @Pact(consumer = "wds", provider = "workspacemanager") + RequestResponsePact enumerateStorageContainersWhenNoneExist(PactDslWithProvider builder) { + return builder + .given("a workspace with the given id exists", Map.of("id", WORKSPACE_UUID.toString())) + .given("no storage container resources exist for the given workspace_id") + .uponReceiving("a request to enumerate resources") + .method("GET") + .matchPath( + enumerateResourcesPath(UUID_REGEX_PATTERN), + enumerateResourcesPath(WORKSPACE_UUID.toString())) + .matchQuery( + "resource", + ResourceType.AZURE_STORAGE_CONTAINER.toString(), + ResourceType.AZURE_STORAGE_CONTAINER.toString()) + .matchQuery("offset", /* regex= */ "[0-9]+", /* example= */ "0") + .matchQuery("limit", /* regex= */ "[0-9]+", /* example= */ "0") + .headers(acceptJson()) + .willRespondWith() + .status(200) + .headers(contentTypeJson()) + .body( + newJsonBody( + body -> { + body.array("resources", emptyArray -> {}); + }) + .build()) + .toPact(); + } + + @Pact(consumer = "wds", provider = "workspacemanager") + RequestResponsePact enumerateStorageContainersWhenOneExists(PactDslWithProvider builder) { + return builder + .given("a workspace with the given id exists", Map.of("id", WORKSPACE_UUID.toString())) + .given( + "a storage container resource exists for the given workspace_id", + Map.of("workspace_id", WORKSPACE_UUID.toString())) + .uponReceiving("a request to enumerate storage containers") + .method("GET") + .matchPath( + enumerateResourcesPath(UUID_REGEX_PATTERN), + enumerateResourcesPath(WORKSPACE_UUID.toString())) + .matchQuery( + "resource", + ResourceType.AZURE_STORAGE_CONTAINER.toString(), + ResourceType.AZURE_STORAGE_CONTAINER.toString()) + .matchQuery("offset", "0", "0") + .matchQuery( + "limit", + String.valueOf(NUM_SNAPSHOTS_REQUESTED), + String.valueOf(NUM_SNAPSHOTS_REQUESTED)) + .headers(acceptJson()) + .willRespondWith() + .status(200) + .headers(contentTypeJson()) + .body( + newJsonBody( + body -> { + body.arrayContaining( + "resources", + resources -> { + // at least one resource should have a name matching the workspaceId + resources.object( + o -> { + o.object( + "metadata", + m -> { + m.uuid("workspaceId", WORKSPACE_UUID); + m.uuid("resourceId"); + m.stringMatcher( + "name", + String.format("sc-%s", UUID_REGEX_PATTERN), + String.format("sc-%s", WORKSPACE_UUID)); + }); + }); + }); + }) + .build()) + .toPact(); + } + + @Pact(consumer = "wds", provider = "workspacemanager") + RequestResponsePact enumerateSnapshotsWhenNoneExist(PactDslWithProvider builder) { + return builder + .given("a workspace with the given id exists", Map.of("id", WORKSPACE_UUID.toString())) + .given( + "no snapshot resources exist for the given workspace_id", + Map.of("workspace_id", WORKSPACE_UUID.toString())) + .uponReceiving("a request to enumerate snapshot resources") + .method("GET") + .matchPath( + enumerateResourcesPath(UUID_REGEX_PATTERN), + enumerateResourcesPath(WORKSPACE_UUID.toString())) + .matchQuery( + "resource", + ResourceType.DATA_REPO_SNAPSHOT.toString(), + ResourceType.DATA_REPO_SNAPSHOT.toString()) + .matchQuery( + "stewardship", + StewardshipType.REFERENCED.toString(), + StewardshipType.REFERENCED.toString()) + .matchQuery("offset", "0", "0") + .matchQuery( + "limit", + String.valueOf(NUM_SNAPSHOTS_REQUESTED), + String.valueOf(NUM_SNAPSHOTS_REQUESTED)) + .headers(acceptJson()) + .willRespondWith() + .status(200) + .headers(contentTypeJson()) + .body( + newJsonBody( + body -> { + body.array("resources", emptyArray -> {}); + }) + .build()) + .toPact(); + } + + @Pact(consumer = "wds", provider = "workspacemanager") + RequestResponsePact enumerateSnapshotsWhenSomeExist(PactDslWithProvider builder) { + return builder + .given("a workspace with the given id exists", Map.of("id", WORKSPACE_UUID.toString())) + .given( + "{num_snapshots} snapshots exist for the given workspace_id", + Map.of( + "workspace_id", + WORKSPACE_UUID.toString(), + "num_snapshots", + NUM_SNAPSHOTS_THAT_EXIST)) + .uponReceiving("a paginated request to enumerate snapshot resources") + .method("GET") + .matchPath( + enumerateResourcesPath(UUID_REGEX_PATTERN), + enumerateResourcesPath(WORKSPACE_UUID.toString())) + .matchQuery( + "resource", + ResourceType.DATA_REPO_SNAPSHOT.toString(), + ResourceType.DATA_REPO_SNAPSHOT.toString()) + .matchQuery( + "stewardship", + StewardshipType.REFERENCED.toString(), + StewardshipType.REFERENCED.toString()) + .matchQuery("offset", "0", "0") + .matchQuery( + "limit", + String.valueOf(NUM_SNAPSHOTS_REQUESTED), + String.valueOf(NUM_SNAPSHOTS_REQUESTED)) + .headers(acceptJson()) + .willRespondWith() + .status(200) + .headers(contentTypeJson()) + .body( + newJsonBody( + body -> { + body.minMaxArrayLike( + "resources", + /* minSize= */ NUM_SNAPSHOTS_THAT_EXIST, + /* maxSize= */ NUM_SNAPSHOTS_THAT_EXIST, + resource -> { + resource.object( + "metadata", + metadata -> { + metadata.uuid("resourceId"); + }); + resource.object( + "resourceAttributes", + attributes -> { + attributes.object( + "gcpDataRepoSnapshot", + tdrSnapshot -> tdrSnapshot.uuid("snapshot")); + }); + }); + }) + .build()) + .toPact(); + } + + @Pact(consumer = "wds", provider = "workspacemanager") + RequestResponsePact createAzureStorageContainerSasTokenSuccess(PactDslWithProvider builder) { + return builder + .given("a workspace with the given id exists", Map.of("id", WORKSPACE_UUID.toString())) + .given( + "a storage container with the given id exists for the given workspace_id", + Map.of("id", RESOURCE_UUID.toString(), "workspace_id", WORKSPACE_UUID.toString())) + .given("permission to create an azure storage container sas token") + .uponReceiving("a request to create an azure storage container sas token") + .method("POST") + .matchPath( + sasTokenPath(UUID_REGEX_PATTERN, UUID_REGEX_PATTERN), + sasTokenPath(WORKSPACE_UUID.toString(), RESOURCE_UUID.toString())) + .headers(contentTypeJson()) + .willRespondWith() + .status(200) // success + .headers(contentTypeJson()) + .body( + newJsonBody( + body -> { + body.matchUrl("url", /* basePath= */ ".*", /* pathFragments= */ ".*"); + }) + .build()) + .toPact(); + } + + @Test + @PactTestFor( + providerName = "workspacemanager", + pactMethods = { + "enumerateStorageContainersWhenOneExists", + "createAzureStorageContainerSasTokenSuccess" + }, + pactVersion = PactSpecVersion.V3) + void testGetBlobStorageUrlSuccess(MockServer mockServer) { + var wsmDao = buildWsmDao(mockServer); + + var actualStorageUrl = + wsmDao.getBlobStorageUrl(WORKSPACE_UUID.toString(), /* authToken= */ null); + + assertNotNull(actualStorageUrl); + } + + @Pact(consumer = "wds", provider = "workspacemanager") + RequestResponsePact createAzureStorageContainerSasTokenForbidden(PactDslWithProvider builder) { + return builder + .given("a workspace with the given id exists", Map.of("id", WORKSPACE_UUID.toString())) + .given( + "a storage container with the given id exists for the given workspace_id", + Map.of("id", RESOURCE_UUID.toString(), "workspace_id", WORKSPACE_UUID.toString())) + .given("no permission to create an azure storage container sas token") + .uponReceiving("a request to create an azure storage container sas token") + .method("POST") + .matchPath( + sasTokenPath(UUID_REGEX_PATTERN, UUID_REGEX_PATTERN), + sasTokenPath(WORKSPACE_UUID.toString(), RESOURCE_UUID.toString())) + .headers(contentTypeJson()) + .willRespondWith() + .status(403) + .toPact(); + } + + @Test + @PactTestFor( + providerName = "workspacemanager", + pactMethods = { + "enumerateStorageContainersWhenOneExists", + "createAzureStorageContainerSasTokenForbidden" + }, + pactVersion = PactSpecVersion.V3) + void testGetBlobStorageUrlNoPermission(MockServer mockServer) { + var wsmDao = buildWsmDao(mockServer); + var thrown = + assertThrows( + WorkspaceManagerException.class, + () -> wsmDao.getBlobStorageUrl(WORKSPACE_UUID.toString(), /* authToken= */ null)); + assertEquals(HttpStatus.FORBIDDEN, thrown.getStatus()); + } + + @Test + @PactTestFor( + providerName = "workspacemanager", + pactMethods = { + "enumerateStorageContainersWhenNoneExist", + }, + pactVersion = PactSpecVersion.V3) + void testGetBlobStorageUrlNoResources(MockServer mockServer) { + var wsmDao = buildWsmDao(mockServer); + var thrown = + assertThrows( + WorkspaceManagerException.class, + () -> wsmDao.getBlobStorageUrl(WORKSPACE_UUID.toString(), /* authToken= */ null)); + assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, thrown.getStatus()); + } + + @Test + @PactTestFor( + providerName = "workspacemanager", + pactMethods = { + "enumerateSnapshotsWhenNoneExist", + }, + pactVersion = PactSpecVersion.V3) + void testExistingPolicySnapshotIdsEmpty(MockServer mockServer) { + var snapshotIds = + tdrSnapshotSupport(mockServer).existingPolicySnapshotIds(NUM_SNAPSHOTS_REQUESTED); + assertTrue(snapshotIds.isEmpty()); + } + + @Test + @PactTestFor( + providerName = "workspacemanager", + pactMethods = { + "enumerateSnapshotsWhenSomeExist", + }, + pactVersion = PactSpecVersion.V3) + void testExistingPolicySnapshotIdsWithSnapshotsPresent(MockServer mockServer) { + var snapshotIds = + tdrSnapshotSupport(mockServer).existingPolicySnapshotIds(NUM_SNAPSHOTS_REQUESTED); + assertEquals(NUM_SNAPSHOTS_THAT_EXIST, snapshotIds.size()); + } + + private static TdrSnapshotSupport tdrSnapshotSupport(MockServer mockServer) { + return new TdrSnapshotSupport(WORKSPACE_UUID, buildWsmDao(mockServer), new RestClientRetry()); + } + + private static WorkspaceManagerDao buildWsmDao(MockServer mockServer) { + WorkspaceManagerClientFactory clientFactory = + new HttpWorkspaceManagerClientFactory(mockServer.getUrl()); + return new WorkspaceManagerDao(clientFactory, WORKSPACE_UUID.toString(), new RestClientRetry()); + } + + // paths + private static String snapshotPath(String workspaceIdPart) { + return String.format( + "/api/workspaces/v1/%s/resources/referenced/datarepo/snapshots", workspaceIdPart); + } + + private static String enumerateResourcesPath(String workspaceIdPart) { + return String.format("/api/workspaces/v1/%s/resources", workspaceIdPart); + } + + private static String sasTokenPath(String workspaceIdPart, String resourceIdPart) { + return String.format( + "/api/workspaces/v1/%s/resources/controlled/azure/storageContainer/%s/getSasToken", + workspaceIdPart, resourceIdPart); + } + + // headers + private static Map contentTypeJson() { Map headers = new HashMap<>(); // pact will automatically assume an expected Content-Type of "application/json; charset=UTF-8" // unless we explicitly tell it otherwise headers.put("Content-Type", "application/json"); return headers; } + + private static Map acceptJson() { + Map headers = new HashMap<>(); + headers.put("Accept", "application/json"); + return headers; + } }