Skip to content

Commit 0982ff2

Browse files
authored
Merge branch 'develop' into 11710-find-dataverses-for-linking
2 parents 296b50c + 56bf628 commit 0982ff2

File tree

10 files changed

+139
-9
lines changed

10 files changed

+139
-9
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
## Get Dataset/Dataverse Storage Driver API
2+
3+
### Changed Json response - breaking change!
4+
5+
The API for getting the Storage Driver info has been changed/extended.
6+
/api/datasets/{identifier}/storageDriver
7+
/api/admin/dataverse/{dataverse-alias}/storageDriver
8+
changed "message" to "name" and added "type" and "label"
9+
10+
Also added query param for /api/admin/dataverse/{dataverse-alias}/storageDriver?getEffective=true to recurse the chain of parents to find the effective storageDriver
11+
12+
See also [the guides](https://dataverse-guide--11664.org.readthedocs.build/en/11664/api/native-api.html#configure-a-dataset-to-store-all-new-files-in-a-specific-file-store), #11695, and #11664.

doc/sphinx-guides/source/admin/dataverses-datasets.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ The current driver can be seen using::
6060

6161
curl -H "X-Dataverse-key: $API_TOKEN" http://$SERVER/api/admin/dataverse/$dataverse-alias/storageDriver
6262

63+
Or to recurse the chain of parents to find the effective storageDriver::
64+
65+
curl -H "X-Dataverse-key: $API_TOKEN" http://$SERVER/api/admin/dataverse/$dataverse-alias/storageDriver?getEffective=true
66+
6367
(Note that for ``dataverse.files.store1.label=MyLabel``, ``store1`` will be returned.)
6468

6569
and can be reset to the default store with::

doc/sphinx-guides/source/api/changelog.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ v6.8
1313
- For POST /api/files/{id}/metadata passing an empty string ("description":"") or array ("categories":[]) will no longer be ignored. Empty fields will now clear out the values in the file's metadata. To ignore the fields simply do not include them in the JSON string.
1414
- For PUT /api/datasets/{id}/editMetadata the query parameter "sourceInternalVersionNumber" has been removed and replaced with "sourceLastUpdateTime" to verify that the data being edited hasn't been modified and isn't stale.
1515
- For GET /api/dataverses/$dataverse-alias/links the Json response has changed breaking the backward compatibility of the API.
16+
- For GET /api/admin/dataverse/{dataverse-alias}/storageDriver and /api/datasets/{identifier}/storageDriver the driver name is no longer returned in data.message. This value is now returned in data.name.
1617
- For PUT /api/dataverses/$dataverse-alias/inputLevels custom input levels that had been previously set will no longer be deleted. To delete input levels send an empty list (deletes all), then send the new/modified list.
1718
- For GET /api/externalTools and /api/externalTools/{id} the responses are now formatted as JSON (previously the toolParameters and allowedApiCalls were a JSON object and array (respectively) that were serialized as JSON strings) and any configured "requirements" are included.
1819

src/main/java/edu/harvard/iq/dataverse/api/Admin.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import edu.harvard.iq.dataverse.settings.JvmSettings;
2121
import edu.harvard.iq.dataverse.util.StringUtil;
2222
import edu.harvard.iq.dataverse.util.cache.CacheFactoryBean;
23+
import edu.harvard.iq.dataverse.util.json.JsonPrinter;
2324
import edu.harvard.iq.dataverse.util.json.NullSafeJsonBuilder;
2425
import edu.harvard.iq.dataverse.validation.EMailValidator;
2526
import edu.harvard.iq.dataverse.EjbDataverseEngine;
@@ -2180,7 +2181,8 @@ public Response addRoleAssignementsToChildren(@Context ContainerRequestContext c
21802181
@GET
21812182
@AuthRequired
21822183
@Path("/dataverse/{alias}/storageDriver")
2183-
public Response getStorageDriver(@Context ContainerRequestContext crc, @PathParam("alias") String alias) throws WrappedResponse {
2184+
public Response getStorageDriver(@Context ContainerRequestContext crc, @PathParam("alias") String alias,
2185+
@QueryParam("getEffective") Boolean getEffective) throws WrappedResponse {
21842186
Dataverse dataverse = dataverseSvc.findByAlias(alias);
21852187
if (dataverse == null) {
21862188
return error(Response.Status.NOT_FOUND, "Could not find dataverse based on alias supplied: " + alias + ".");
@@ -2193,8 +2195,12 @@ public Response getStorageDriver(@Context ContainerRequestContext crc, @PathPara
21932195
} catch (WrappedResponse wr) {
21942196
return wr.getResponse();
21952197
}
2196-
//Note that this returns what's set directly on this dataverse. If null/DataAccess.UNDEFINED_STORAGE_DRIVER_IDENTIFIER, the user would have to recurse the chain of parents to find the effective storageDriver
2197-
return ok(dataverse.getStorageDriverId());
2198+
2199+
if (getEffective != null && getEffective) {
2200+
return ok(JsonPrinter.jsonStorageDriver(dataverse.getEffectiveStorageDriverId(), null));
2201+
} else {
2202+
return ok(JsonPrinter.jsonStorageDriver(dataverse.getStorageDriverId(), null));
2203+
}
21982204
}
21992205

22002206
@PUT

src/main/java/edu/harvard/iq/dataverse/api/Datasets.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3690,7 +3690,7 @@ public Response getFileStore(@Context ContainerRequestContext crc, @PathParam("i
36903690
return error(Response.Status.NOT_FOUND, "No such dataset");
36913691
}
36923692

3693-
return response(req -> ok(dataset.getEffectiveStorageDriverId()), getRequestUser(crc));
3693+
return ok(JsonPrinter.jsonStorageDriver(dataset.getEffectiveStorageDriverId(), dataset));
36943694
}
36953695

36963696
@PUT

src/main/java/edu/harvard/iq/dataverse/util/json/JsonPrinter.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import edu.harvard.iq.dataverse.workflow.Workflow;
4141
import edu.harvard.iq.dataverse.workflow.step.WorkflowStepData;
4242

43+
import java.io.IOException;
4344
import java.util.*;
4445
import jakarta.json.Json;
4546
import jakarta.json.JsonArrayBuilder;
@@ -1665,6 +1666,23 @@ public static JsonArrayBuilder jsonTemplateInstructions(Map<String, String> temp
16651666
return jsonArrayBuilder;
16661667
}
16671668

1669+
public static JsonObjectBuilder jsonStorageDriver(String storageDriverId, Dataset dataset) {
1670+
JsonObjectBuilder jsonObjectBuilder = new NullSafeJsonBuilder();
1671+
jsonObjectBuilder.add("name", storageDriverId);
1672+
jsonObjectBuilder.add("type", DataAccess.getDriverType(storageDriverId));
1673+
jsonObjectBuilder.add("label", DataAccess.getStorageDriverLabelFor(storageDriverId));
1674+
if (dataset != null) {
1675+
jsonObjectBuilder.add("directUpload", DataAccess.uploadToDatasetAllowed(dataset, storageDriverId));
1676+
try {
1677+
jsonObjectBuilder.add("directDownload", DataAccess.getStorageIO(dataset).downloadRedirectEnabled());
1678+
} catch (IOException ex) {
1679+
logger.fine("Failed to get Storage IO for dataset " + ex.getMessage());
1680+
}
1681+
}
1682+
1683+
return jsonObjectBuilder;
1684+
}
1685+
16681686
public static JsonArrayBuilder json(List<UserNotification> notifications, AuthenticatedUser authenticatedUser, boolean inAppNotificationFormat) {
16691687
JsonArrayBuilder notificationsArray = Json.createArrayBuilder();
16701688

src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6118,6 +6118,60 @@ public void testGetGlobusUploadParameters() {
61186118
GlobusOverlayAccessIOTest.tearDown();
61196119
}
61206120

6121+
@Test
6122+
public void testSetGetDatasetStorageDriver() {
6123+
Response createUser = UtilIT.createRandomUser();
6124+
createUser.then().assertThat().statusCode(OK.getStatusCode());
6125+
String apiToken = UtilIT.getApiTokenFromResponse(createUser);
6126+
String username = UtilIT.getUsernameFromResponse(createUser);
6127+
Response makeSuperUser = UtilIT.makeSuperUser(username);
6128+
assertEquals(200, makeSuperUser.getStatusCode());
6129+
Response createDataverse = UtilIT.createRandomDataverse(apiToken);
6130+
String dataverseAlias = UtilIT.getAliasFromResponse(createDataverse);
6131+
Response createDataset = UtilIT.createRandomDatasetViaNativeApi(dataverseAlias, apiToken);
6132+
Integer datasetId = UtilIT.getDatasetIdFromResponse(createDataset);
6133+
6134+
Response storageDrivers = UtilIT.listStorageDrivers(apiToken);
6135+
storageDrivers.prettyPrint();
6136+
JsonObject data = JsonUtil.getJsonObject(storageDrivers.getBody().asString());
6137+
String first = data.getJsonObject("data").keySet().iterator().next();
6138+
String name = data.getJsonObject("data").getString(first);
6139+
6140+
Response setDriver = UtilIT.setDatasetStorageDriver(datasetId, first, apiToken);
6141+
setDriver.prettyPrint();
6142+
assertEquals(200, setDriver.getStatusCode());
6143+
Response getDriver = UtilIT.getDatasetStorageDriver(datasetId, apiToken);
6144+
getDriver.prettyPrint();
6145+
assertEquals(200, getDriver.getStatusCode());
6146+
getDriver.then().assertThat()
6147+
.body("data.name", CoreMatchers.equalTo(name))
6148+
.body("data.type", CoreMatchers.notNullValue())
6149+
.body("data.label", CoreMatchers.notNullValue())
6150+
.body("data.directUpload", CoreMatchers.notNullValue())
6151+
.body("data.directDownload", CoreMatchers.notNullValue())
6152+
.statusCode(OK.getStatusCode());
6153+
6154+
// Test dataset under root with default storage driver
6155+
Response getStorageDriverResponse = UtilIT.getStorageDriver("root", apiToken, Boolean.TRUE);
6156+
getStorageDriverResponse.prettyPrint();
6157+
data = JsonUtil.getJsonObject(getStorageDriverResponse.getBody().asString());
6158+
name = data.getJsonObject("data").getString("name");
6159+
String type = data.getJsonObject("data").getString("type");
6160+
String label = data.getJsonObject("data").getString("label");
6161+
createDataset = UtilIT.createRandomDatasetViaNativeApi("root", apiToken);
6162+
datasetId = UtilIT.getDatasetIdFromResponse(createDataset);
6163+
getDriver = UtilIT.getDatasetStorageDriver(datasetId, apiToken);
6164+
getDriver.prettyPrint();
6165+
assertEquals(200, getDriver.getStatusCode());
6166+
getDriver.then().assertThat()
6167+
.body("data.name", CoreMatchers.equalTo(name))
6168+
.body("data.type", CoreMatchers.equalTo(type))
6169+
.body("data.label", CoreMatchers.equalTo(label))
6170+
.body("data.directUpload", CoreMatchers.notNullValue())
6171+
.body("data.directDownload", CoreMatchers.notNullValue())
6172+
.statusCode(OK.getStatusCode());
6173+
}
6174+
61216175
@Test
61226176
public void testGetCanDownloadAtLeastOneFile() {
61236177
Response createUserResponse = UtilIT.createRandomUser();

src/test/java/edu/harvard/iq/dataverse/api/DataversesIT.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package edu.harvard.iq.dataverse.api;
22

3+
import edu.harvard.iq.dataverse.dataaccess.DataAccess;
34
import edu.harvard.iq.dataverse.util.json.JsonParseException;
45
import edu.harvard.iq.dataverse.util.json.JsonParser;
56
import edu.harvard.iq.dataverse.util.json.JsonUtil;
@@ -2703,6 +2704,26 @@ public void testCreateAndGetTemplates() throws JsonParseException {
27032704
getTemplateResponse.then().assertThat().statusCode(UNAUTHORIZED.getStatusCode());
27042705
}
27052706

2707+
@Test
2708+
public void testGetStorageDriver() {
2709+
Response updatedStorageDriver = UtilIT.getStorageDriver("root", getSuperuserToken(), Boolean.TRUE);
2710+
updatedStorageDriver.prettyPrint();
2711+
updatedStorageDriver.then().assertThat()
2712+
.body("data.name", CoreMatchers.notNullValue())
2713+
.body("data.type", CoreMatchers.notNullValue())
2714+
.body("data.label", CoreMatchers.notNullValue())
2715+
.body("data.directUpload", CoreMatchers.nullValue())
2716+
.body("data.directDownload", CoreMatchers.nullValue())
2717+
.statusCode(200);
2718+
2719+
// Root without default is undefined
2720+
updatedStorageDriver = UtilIT.getStorageDriver("root", getSuperuserToken(), null);
2721+
updatedStorageDriver.prettyPrint();
2722+
updatedStorageDriver.then().assertThat()
2723+
.body("data.name", CoreMatchers.equalTo(DataAccess.UNDEFINED_STORAGE_DRIVER_IDENTIFIER))
2724+
.statusCode(200);
2725+
}
2726+
27062727
private String getSuperuserToken() {
27072728
Response createResponse = UtilIT.createRandomUser();
27082729
String adminApiToken = UtilIT.getApiTokenFromResponse(createResponse);

src/test/java/edu/harvard/iq/dataverse/api/S3AccessIT.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package edu.harvard.iq.dataverse.api;
22

3+
import org.hamcrest.CoreMatchers;
34
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
45
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
56
import software.amazon.awssdk.core.ResponseInputStream;
@@ -142,7 +143,7 @@ public void testNonDirectUpload() {
142143
Response originalStorageDriver = UtilIT.getStorageDriver(dataverseAlias, superuserApiToken);
143144
originalStorageDriver.prettyPrint();
144145
originalStorageDriver.then().assertThat()
145-
.body("data.message", equalTo("undefined"))
146+
.body("data.name", equalTo("undefined"))
146147
.statusCode(200);
147148

148149
Response setStorageDriverToS3 = UtilIT.setStorageDriver(dataverseAlias, driverLabel, superuserApiToken);
@@ -153,6 +154,9 @@ public void testNonDirectUpload() {
153154
Response updatedStorageDriver = UtilIT.getStorageDriver(dataverseAlias, superuserApiToken);
154155
updatedStorageDriver.prettyPrint();
155156
updatedStorageDriver.then().assertThat()
157+
.body("data.type", CoreMatchers.notNullValue())
158+
.body("data.label", CoreMatchers.notNullValue())
159+
.body("data.directUpload", CoreMatchers.nullValue())
156160
.statusCode(200);
157161

158162
Response createDatasetResponse = UtilIT.createRandomDatasetViaNativeApi(dataverseAlias, apiToken);
@@ -273,7 +277,7 @@ public void testDirectUpload() {
273277
Response originalStorageDriver = UtilIT.getStorageDriver(dataverseAlias, superuserApiToken);
274278
originalStorageDriver.prettyPrint();
275279
originalStorageDriver.then().assertThat()
276-
.body("data.message", equalTo("undefined"))
280+
.body("data.name", equalTo("undefined"))
277281
.statusCode(200);
278282

279283
Response setStorageDriverToS3 = UtilIT.setStorageDriver(dataverseAlias, driverLabel, superuserApiToken);
@@ -491,7 +495,7 @@ public void testDirectUploadDetectStataFile() {
491495
Response originalStorageDriver = UtilIT.getStorageDriver(dataverseAlias, superuserApiToken);
492496
originalStorageDriver.prettyPrint();
493497
originalStorageDriver.then().assertThat()
494-
.body("data.message", equalTo("undefined"))
498+
.body("data.name", equalTo("undefined"))
495499
.statusCode(200);
496500

497501
Response setStorageDriverToS3 = UtilIT.setStorageDriver(dataverseAlias, driverLabel, superuserApiToken);
@@ -689,7 +693,7 @@ public void testDirectUploadWithFileCountLimit() throws JsonParseException {
689693
Response originalStorageDriver = UtilIT.getStorageDriver(dataverseAlias, superuserApiToken);
690694
originalStorageDriver.prettyPrint();
691695
originalStorageDriver.then().assertThat()
692-
.body("data.message", equalTo("undefined"))
696+
.body("data.name", equalTo("undefined"))
693697
.statusCode(200);
694698

695699
Response setStorageDriverToS3 = UtilIT.setStorageDriver(dataverseAlias, driverLabel, superuserApiToken);

src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2850,9 +2850,13 @@ static Response listStorageDrivers(String apiToken) {
28502850
}
28512851

28522852
static Response getStorageDriver(String dvAlias, String apiToken) {
2853+
return getStorageDriver(dvAlias, apiToken, null);
2854+
}
2855+
static Response getStorageDriver(String dvAlias, String apiToken, Boolean getEffective) {
2856+
String params = getEffective != null ? "?getEffective=" + getEffective : "";
28532857
return given()
28542858
.header(API_TOKEN_HTTP_HEADER, apiToken)
2855-
.get("/api/admin/dataverse/" + dvAlias + "/storageDriver");
2859+
.get("/api/admin/dataverse/" + dvAlias + "/storageDriver" + params);
28562860
}
28572861

28582862
static Response setStorageDriver(String dvAlias, String label, String apiToken) {
@@ -4460,6 +4464,12 @@ static Response setDatasetStorageDriver(Integer datasetId, String driverLabel, S
44604464
.put("/api/datasets/" + datasetId + "/storageDriver");
44614465
}
44624466

4467+
static Response getDatasetStorageDriver(Integer datasetId, String apiToken) {
4468+
return given()
4469+
.header(API_TOKEN_HTTP_HEADER, apiToken)
4470+
.get("/api/datasets/" + datasetId + "/storageDriver");
4471+
}
4472+
44634473
/** GET on /api/admin/savedsearches/list */
44644474
static Response getSavedSearchList() {
44654475
return given().get("/api/admin/savedsearches/list");

0 commit comments

Comments
 (0)