This is an automated email from the ASF dual-hosted git repository.
siyao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git
The following commit(s) were added to refs/heads/master by this push:
new c5a92a2 HDDS-5824. `ozone sh volume/bucket/key list` should print
valid JSON array (#2713)
c5a92a2 is described below
commit c5a92a20614f22f2c37d599a2ae15ee59c0ecfa9
Author: Siyao Meng <[email protected]>
AuthorDate: Thu Oct 7 11:02:57 2021 -0700
HDDS-5824. `ozone sh volume/bucket/key list` should print valid JSON array
(#2713)
---
hadoop-hdds/docs/content/interface/CSI.md | 4 +-
hadoop-hdds/docs/content/interface/CSI.zh.md | 4 +-
hadoop-hdds/docs/content/interface/Cli.md | 7 +-
.../org/apache/hadoop/hdds/server/JsonUtils.java | 16 ++-
.../dist/src/main/smoketest/basic/links.robot | 8 +-
.../src/main/smoketest/basic/ozone-shell-lib.robot | 10 +-
.../dist/src/main/smoketest/omha/testOMHA.robot | 2 +-
.../dist/src/main/smoketest/ozonefs/ozonefs.robot | 18 ++--
.../hadoop/ozone/shell/TestOzoneShellHA.java | 112 ++++++++++++++++++---
.../org/apache/hadoop/ozone/shell/Handler.java | 17 ++++
.../ozone/shell/bucket/ListBucketHandler.java | 10 +-
.../hadoop/ozone/shell/keys/ListKeyHandler.java | 8 +-
.../ozone/shell/volume/ListVolumeHandler.java | 9 +-
13 files changed, 162 insertions(+), 63 deletions(-)
diff --git a/hadoop-hdds/docs/content/interface/CSI.md
b/hadoop-hdds/docs/content/interface/CSI.md
index f7dbfd3..59b24c9 100644
--- a/hadoop-hdds/docs/content/interface/CSI.md
+++ b/hadoop-hdds/docs/content/interface/CSI.md
@@ -70,7 +70,7 @@ Attach the pod scm-0 and put a key into the /s3v/pvc* bucket.
```bash
kubectl exec -it scm-0 bash
[hadoop@scm-0 ~]$ ozone sh bucket list s3v
-{
+[ {
"metadata" : { },
"volumeName" : "s3v",
"name" : "pvc-861e2d8b-2232-4cd1-b43c-c0c26697ab6b",
@@ -78,7 +78,7 @@ kubectl exec -it scm-0 bash
"versioning" : false,
"creationTime" : "2020-06-11T08:19:47.469Z",
"encryptionKeyName" : null
-}
+} ]
[hadoop@scm-0 ~]$ ozone sh key put
/s3v/pvc-861e2d8b-2232-4cd1-b43c-c0c26697ab6b/A LICENSE.txt
```
diff --git a/hadoop-hdds/docs/content/interface/CSI.zh.md
b/hadoop-hdds/docs/content/interface/CSI.zh.md
index 505c911..b243d1e 100644
--- a/hadoop-hdds/docs/content/interface/CSI.zh.md
+++ b/hadoop-hdds/docs/content/interface/CSI.zh.md
@@ -69,7 +69,7 @@ kubectl create -f /ozone/kubernetes/examples/ozone/pv-test
```bash
kubectl exec -it scm-0 bash
[hadoop@scm-0 ~]$ ozone sh bucket list s3v
-{
+[ {
"metadata" : { },
"volumeName" : "s3v",
"name" : "pvc-861e2d8b-2232-4cd1-b43c-c0c26697ab6b",
@@ -77,7 +77,7 @@ kubectl exec -it scm-0 bash
"versioning" : false,
"creationTime" : "2020-06-11T08:19:47.469Z",
"encryptionKeyName" : null
-}
+} ]
[hadoop@scm-0 ~]$ ozone sh key put
/s3v/pvc-861e2d8b-2232-4cd1-b43c-c0c26697ab6b/A LICENSE.txt
```
diff --git a/hadoop-hdds/docs/content/interface/Cli.md
b/hadoop-hdds/docs/content/interface/Cli.md
index cbdc499..3cbe518 100644
--- a/hadoop-hdds/docs/content/interface/Cli.md
+++ b/hadoop-hdds/docs/content/interface/Cli.md
@@ -116,7 +116,7 @@ $ ozone sh volume info /vol1
```shell
$ ozone sh volume list /
-{
+[ {
"metadata" : { },
"name" : "s3v",
"admin" : "hadoop",
@@ -135,8 +135,9 @@ $ ozone sh volume list /
"aclList" : [ "ALL" ]
} ],
"quota" : 1152921504606846976
-}
-....
+}, {
+ ....
+} ]
```
## Bucket operations
diff --git
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/JsonUtils.java
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/JsonUtils.java
index 1cc7e82..b46e48d 100644
---
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/JsonUtils.java
+++
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/server/JsonUtils.java
@@ -25,6 +25,8 @@ import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.type.CollectionType;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
@@ -37,13 +39,13 @@ public final class JsonUtils {
// ObjectMapper is thread safe as long as we always configure instance
// before use.
private static final ObjectMapper MAPPER;
- private static final ObjectWriter WRITTER;
+ private static final ObjectWriter WRITER;
static {
MAPPER = new ObjectMapper()
.setSerializationInclusion(JsonInclude.Include.NON_NULL)
.registerModule(new JavaTimeModule())
.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
- WRITTER = MAPPER.writerWithDefaultPrettyPrinter();
+ WRITER = MAPPER.writerWithDefaultPrettyPrinter();
}
private JsonUtils() {
@@ -52,13 +54,21 @@ public final class JsonUtils {
public static String toJsonStringWithDefaultPrettyPrinter(Object obj)
throws IOException {
- return WRITTER.writeValueAsString(obj);
+ return WRITER.writeValueAsString(obj);
}
public static String toJsonString(Object obj) throws IOException {
return MAPPER.writeValueAsString(obj);
}
+ public static ArrayNode createArrayNode() {
+ return MAPPER.createArrayNode();
+ }
+
+ public static ObjectNode createObjectNode(Object next) {
+ return MAPPER.valueToTree(next);
+ }
+
/**
* Deserialize a list of elements from a given string,
* each element in the list is in the given type.
diff --git a/hadoop-ozone/dist/src/main/smoketest/basic/links.robot
b/hadoop-ozone/dist/src/main/smoketest/basic/links.robot
index 9b07af1..7c2af60 100644
--- a/hadoop-ozone/dist/src/main/smoketest/basic/links.robot
+++ b/hadoop-ozone/dist/src/main/smoketest/basic/links.robot
@@ -86,15 +86,15 @@ Key read passthrough
Key Should Match Local File ${source}/bucket1/key2
/opt/hadoop/NOTICE.txt
Key list passthrough
- ${target_list} = Execute ozone sh key list
${target}/link1 | jq -r '.name'
- ${source_list} = Execute ozone sh key list
${source}/bucket1 | jq -r '.name'
+ ${target_list} = Execute ozone sh key list
${target}/link1 | jq -r '.[].name'
+ ${source_list} = Execute ozone sh key list
${source}/bucket1 | jq -r '.[].name'
Should Be Equal ${target_list}
${source_list}
Should Contain ${source_list} key1
Should Contain ${source_list} key2
Key delete passthrough
Execute ozone sh key delete
${target}/link1/key2
- ${source_list} = Execute ozone sh key list
${source}/bucket1 | jq -r '.name'
+ ${source_list} = Execute ozone sh key list
${source}/bucket1 | jq -r '.[].name'
Should Not Contain ${source_list} key2
Bucket list contains links
@@ -155,5 +155,5 @@ Source bucket not affected by deleting link
Execute ozone sh bucket delete
${target}/link1
${bucket_list} = Execute ozone sh bucket list
${target}
Should Not Contain ${bucket_list} link1
- ${source_list} = Execute ozone sh key list
${source}/bucket1 | jq -r '.name'
+ ${source_list} = Execute ozone sh key list
${source}/bucket1 | jq -r '.[].name'
Should Contain ${source_list} key1
diff --git a/hadoop-ozone/dist/src/main/smoketest/basic/ozone-shell-lib.robot
b/hadoop-ozone/dist/src/main/smoketest/basic/ozone-shell-lib.robot
index 7671e20..56f100e 100644
--- a/hadoop-ozone/dist/src/main/smoketest/basic/ozone-shell-lib.robot
+++ b/hadoop-ozone/dist/src/main/smoketest/basic/ozone-shell-lib.robot
@@ -34,9 +34,9 @@ Test ozone shell
Should contain ${result} VOLUME_NOT_FOUND
${result} = Execute ozone sh volume create
${protocol}${server}/${volume} --space-quota 100TB --namespace-quota 100
Should not contain ${result} Failed
- ${result} = Execute ozone sh volume list
${protocol}${server}/ | jq -r '. | select(.name=="${volume}")'
+ ${result} = Execute ozone sh volume list
${protocol}${server}/ | jq -r '.[] | select(.name=="${volume}")'
Should contain ${result} creationTime
- ${result} = Execute ozone sh volume list | jq -r '. |
select(.name=="${volume}")'
+ ${result} = Execute ozone sh volume list | jq -r '.[] |
select(.name=="${volume}")'
Should contain ${result} creationTime
# TODO: Disable updating the owner, acls should be used to give access to
other user.
Execute ozone sh volume setquota
${protocol}${server}/${volume} --space-quota 10TB --namespace-quota 100
@@ -56,7 +56,7 @@ Test ozone shell
Should Be Equal ${result} 1099511627776
${result} = Execute ozone sh bucket info
${protocol}${server}/${volume}/bb1 | jq -r '. | select(.name=="bb1") |
.quotaInNamespace'
Should Be Equal ${result} 1000
- ${result} = Execute ozone sh bucket list
${protocol}${server}/${volume}/ | jq -r '. | select(.name=="bb1") | .volumeName'
+ ${result} = Execute ozone sh bucket list
${protocol}${server}/${volume}/ | jq -r '.[] | select(.name=="bb1") |
.volumeName'
Should Be Equal ${result} ${volume}
Run Keyword Test key handling ${protocol}
${server} ${volume}
Execute ozone sh volume clrquota --space-quota
${protocol}${server}/${volume}
@@ -146,10 +146,10 @@ Test key handling
Should Not Contain ${result} NOTICE.txt.1 exists
${result} = Execute ozone sh key info
${protocol}${server}/${volume}/bb1/key1 | jq -r '. | select(.name=="key1")'
Should contain ${result} creationTime
- ${result} = Execute ozone sh key list
${protocol}${server}/${volume}/bb1 | jq -r '. | select(.name=="key1") | .name'
+ ${result} = Execute ozone sh key list
${protocol}${server}/${volume}/bb1 | jq -r '.[] | select(.name=="key1") | .name'
Should Be Equal ${result} key1
Execute ozone sh key rename
${protocol}${server}/${volume}/bb1 key1 key2
- ${result} = Execute ozone sh key list
${protocol}${server}/${volume}/bb1 | jq -r '.name'
+ ${result} = Execute ozone sh key list
${protocol}${server}/${volume}/bb1 | jq -r '.[].name'
Should Be Equal ${result} key2
Execute ozone sh key delete
${protocol}${server}/${volume}/bb1/key2
diff --git a/hadoop-ozone/dist/src/main/smoketest/omha/testOMHA.robot
b/hadoop-ozone/dist/src/main/smoketest/omha/testOMHA.robot
index 0c08bb1..c3d3c7c 100644
--- a/hadoop-ozone/dist/src/main/smoketest/omha/testOMHA.robot
+++ b/hadoop-ozone/dist/src/main/smoketest/omha/testOMHA.robot
@@ -73,7 +73,7 @@ Write Test File
${testFilePath} = Set Variable ${TEMPDIR}/${fileName}
Copy File ${TEST_FILE}
${testFilePath}
Execute ozone fs -copyFromLocal
${testFilePath} o3fs://${BUCKET}.${VOLUME}.${OM_SERVICE_ID}/
- ${result} = Execute ozone sh key list
o3://${OM_SERVICE_ID}/${VOLUME}/${BUCKET} | jq -r '.name'
+ ${result} = Execute ozone sh key list
o3://${OM_SERVICE_ID}/${VOLUME}/${BUCKET} | jq -r '.[].name'
Should contain ${result}
${fileName}
Remove File ${testFilePath}
diff --git a/hadoop-ozone/dist/src/main/smoketest/ozonefs/ozonefs.robot
b/hadoop-ozone/dist/src/main/smoketest/ozonefs/ozonefs.robot
index 8b8220c..f888d22 100644
--- a/hadoop-ozone/dist/src/main/smoketest/ozonefs/ozonefs.robot
+++ b/hadoop-ozone/dist/src/main/smoketest/ozonefs/ozonefs.robot
@@ -38,19 +38,19 @@ List non-existent bucket
Create dir with parents
Execute ozone fs -mkdir -p ${DEEP_URL}
- ${result} = Execute ozone sh key list ${VOLUME}/${BUCKET}
| jq -r '.name'
+ ${result} = Execute ozone sh key list ${VOLUME}/${BUCKET}
| jq -r '.[].name'
Should contain ${result} ${DEEP_DIR}
Copy from local
Execute ozone fs -copyFromLocal NOTICE.txt
${DEEP_URL}/
- ${result} = Execute ozone sh key list ${VOLUME}/${BUCKET}
| jq -r '.name'
+ ${result} = Execute ozone sh key list ${VOLUME}/${BUCKET}
| jq -r '.[].name'
Should contain ${result} NOTICE.txt
${result} = Execute ozone sh key info
${VOLUME}/${BUCKET}/${DEEP_DIR}/NOTICE.txt | jq -r '.replicationFactor'
Should Be Equal ${result} 3
Put
Execute ozone fs -put NOTICE.txt
${DEEP_URL}/PUTFILE.txt
- ${result} = Execute ozone sh key list ${VOLUME}/${BUCKET}
| jq -r '.name'
+ ${result} = Execute ozone sh key list ${VOLUME}/${BUCKET}
| jq -r '.[].name'
Should contain ${result} PUTFILE.txt
List
@@ -60,14 +60,14 @@ List
Move
Execute ozone fs -mv ${DEEP_URL}/NOTICE.txt
${DEEP_URL}/MOVED.TXT
- ${result} = Execute ozone sh key list ${VOLUME}/${BUCKET}
| jq -r '.name'
+ ${result} = Execute ozone sh key list ${VOLUME}/${BUCKET}
| jq -r '.[].name'
Should contain ${result} MOVED.TXT
Should not contain ${result} NOTICE.txt
Copy within FS
[Setup] Execute ozone fs -mkdir -p ${DEEP_URL}/subdir1
Execute ozone fs -cp ${DEEP_URL}/MOVED.TXT
${DEEP_URL}/subdir1/NOTICE.txt
- ${result} = Execute ozone sh key list ${VOLUME}/${BUCKET}
| jq -r '.name'
+ ${result} = Execute ozone sh key list ${VOLUME}/${BUCKET}
| jq -r '.[].name'
Should contain ${result} subdir1/NOTICE.txt
${result} = Execute ozone fs -ls ${DEEP_URL}/subdir1/
@@ -79,17 +79,17 @@ Cat file
Delete file
Execute ozone fs -rm -skipTrash
${DEEP_URL}/subdir1/NOTICE.txt
- ${result} = Execute ozone sh key list ${VOLUME}/${BUCKET}
| jq -r '.name'
+ ${result} = Execute ozone sh key list ${VOLUME}/${BUCKET}
| jq -r '.[].name'
Should not contain ${result} NOTICE.txt
Delete dir
${result} = Execute ozone fs -rmdir ${DEEP_URL}/subdir1/
- ${result} = Execute ozone sh key list ${VOLUME}/${BUCKET}
| jq -r '.name'
+ ${result} = Execute ozone sh key list ${VOLUME}/${BUCKET}
| jq -r '.[].name'
Should not contain ${result} subdir1
Touch file
Execute ozone fs -touch
${DEEP_URL}/TOUCHFILE-${SCHEME}.txt
- ${result} = Execute ozone sh key list ${VOLUME}/${BUCKET}
| jq -r '.name'
+ ${result} = Execute ozone sh key list ${VOLUME}/${BUCKET}
| jq -r '.[].name'
Should contain ${result}
TOUCHFILE-${SCHEME}.txt
Delete file with Trash
@@ -103,7 +103,7 @@ Delete file with Trash
Delete recursively
Execute ozone fs -mkdir -p ${DEEP_URL}/subdir2
Execute ozone fs -rm -skipTrash -r
${DEEP_URL}/subdir2
- ${result} = Execute ozone sh key list ${VOLUME}/${BUCKET}
| jq -r '.name'
+ ${result} = Execute ozone sh key list ${VOLUME}/${BUCKET}
| jq -r '.[].name'
Should not contain ${result} ${DEEP_DIR}/subdir2
List recursively
diff --git
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneShellHA.java
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneShellHA.java
index b32ff32..a8b1980 100644
---
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneShellHA.java
+++
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestOzoneShellHA.java
@@ -22,7 +22,9 @@ import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashSet;
import java.util.List;
import java.util.UUID;
@@ -37,7 +39,6 @@ import org.apache.hadoop.fs.ozone.OzoneFsShell;
import org.apache.hadoop.hdds.conf.OzoneConfiguration;
import org.apache.hadoop.ozone.MiniOzoneCluster;
import org.apache.hadoop.ozone.MiniOzoneOMHAClusterImpl;
-import org.apache.hadoop.ozone.OzoneConsts;
import org.apache.hadoop.ozone.client.ObjectStore;
import org.apache.hadoop.ozone.ha.ConfUtils;
import org.apache.hadoop.ozone.om.OMConfigKeys;
@@ -49,6 +50,8 @@ import org.apache.hadoop.fs.TrashPolicy;
import org.apache.hadoop.ozone.om.TrashPolicyOzone;
import com.google.common.base.Strings;
+import com.google.gson.Gson;
+import com.google.gson.internal.LinkedTreeMap;
import static java.nio.charset.StandardCharsets.UTF_8;
import static
org.apache.hadoop.fs.CommonConfigurationKeysPublic.FS_TRASH_INTERVAL_KEY;
@@ -58,6 +61,7 @@ import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert;
+import static org.apache.hadoop.ozone.OzoneConsts.OZONE_URI_DELIMITER;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import org.junit.Before;
@@ -83,6 +87,8 @@ public class TestOzoneShellHA {
private static final Logger LOG =
LoggerFactory.getLogger(TestOzoneShellHA.class);
+ private static final String DEFAULT_ENCODING = UTF_8.name();
+
/**
* Set the timeout for every test.
*/
@@ -91,6 +97,7 @@ public class TestOzoneShellHA {
private static File baseDir;
private static File testFile;
+ private static String testFilePathString;
private static OzoneConfiguration conf = null;
private static MiniOzoneCluster cluster = null;
private static OzoneShell ozoneShell = null;
@@ -121,7 +128,8 @@ public class TestOzoneShellHA {
baseDir = new File(path);
baseDir.mkdirs();
- testFile = new File(path + OzoneConsts.OZONE_URI_DELIMITER + "testFile");
+ testFilePathString = path + OZONE_URI_DELIMITER + "testFile";
+ testFile = new File(testFilePathString);
testFile.getParentFile().mkdirs();
testFile.createNewFile();
@@ -158,8 +166,8 @@ public class TestOzoneShellHA {
@Before
public void setup() throws UnsupportedEncodingException {
- System.setOut(new PrintStream(out, false, UTF_8.name()));
- System.setErr(new PrintStream(err, false, UTF_8.name()));
+ System.setOut(new PrintStream(out, false, DEFAULT_ENCODING));
+ System.setErr(new PrintStream(err, false, DEFAULT_ENCODING));
}
@After
@@ -311,8 +319,7 @@ public class TestOzoneShellHA {
"bucket", "create", "o3://" + omServiceId + volumeName + bucketName};
execute(ozoneShell, args);
- String keyName = volumeName + bucketName +
- OzoneConsts.OZONE_URI_DELIMITER + "key";
+ String keyName = volumeName + bucketName + OZONE_URI_DELIMITER + "key";
for (int i = 0; i < 100; i++) {
args = new String[] {
"key", "put", "o3://" + omServiceId + keyName + i,
@@ -325,7 +332,7 @@ public class TestOzoneShellHA {
* Helper function to get nums of keys from info of listing command.
*/
private int getNumOfKeys() throws UnsupportedEncodingException {
- return out.toString(UTF_8.name()).split("key").length - 1;
+ return out.toString(DEFAULT_ENCODING).split("key").length - 1;
}
/**
@@ -337,7 +344,7 @@ public class TestOzoneShellHA {
execute(ozoneShell, args);
String bucketName =
- volumeName + OzoneConsts.OZONE_URI_DELIMITER + "testbucket";
+ volumeName + OZONE_URI_DELIMITER + "testbucket";
for (int i = 0; i < numOfBuckets; i++) {
args = new String[] {
"bucket", "create", "o3://" + omServiceId + bucketName + i};
@@ -350,10 +357,17 @@ public class TestOzoneShellHA {
*/
private int getNumOfBuckets(String bucketPrefix)
throws UnsupportedEncodingException {
- return out.toString(UTF_8.name())
- .split(bucketPrefix).length - 1;
+ return out.toString(DEFAULT_ENCODING).split(bucketPrefix).length - 1;
}
+ /**
+ * Parse output into ArrayList with Gson.
+ * @return ArrayList
+ */
+ private ArrayList<LinkedTreeMap<String, String>> parseOutputIntoArrayList()
+ throws UnsupportedEncodingException {
+ return new Gson().fromJson(out.toString(DEFAULT_ENCODING),
ArrayList.class);
+ }
/**
* Tests ozone sh command URI parsing with volume and bucket create commands.
@@ -434,7 +448,8 @@ public class TestOzoneShellHA {
args = new String[] {"key", "list", startKey, destinationBucket};
out.reset();
execute(ozoneShell, args);
- Assert.assertEquals(0, out.size());
+ // Expect empty JSON array
+ Assert.assertEquals(0, parseOutputIntoArrayList().size());
Assert.assertEquals(0, getNumOfKeys());
// Part of listing buckets test.
@@ -456,7 +471,8 @@ public class TestOzoneShellHA {
out.reset();
args = new String[] {"bucket", "list", startBucket, destinationVolume};
execute(ozoneShell, args);
- Assert.assertEquals(0, out.size());
+ // Expect empty JSON array
+ Assert.assertEquals(0, parseOutputIntoArrayList().size());
Assert.assertEquals(0, getNumOfBuckets("testbucket"));
}
@@ -855,4 +871,76 @@ public class TestOzoneShellHA {
objectStore.getVolume("vol4").deleteBucket("buck4");
objectStore.deleteVolume("vol4");
}
+
+ @Test
+ public void testListVolumeBucketKeyShouldPrintValidJsonArray()
+ throws UnsupportedEncodingException {
+
+ final List<String> testVolumes =
+ Arrays.asList("jsontest-vol1", "jsontest-vol2", "jsontest-vol3");
+ final List<String> testBuckets =
+ Arrays.asList("v1-bucket1", "v1-bucket2", "v1-bucket3");
+ final List<String> testKeys = Arrays.asList("key1", "key2", "key3");
+
+ final String firstVolumePrefix = testVolumes.get(0) + OZONE_URI_DELIMITER;
+ final String keyPathPrefix = firstVolumePrefix +
+ testBuckets.get(0) + OZONE_URI_DELIMITER;
+
+ // Create test volumes, buckets and keys
+ testVolumes.forEach(vol -> execute(ozoneShell, new String[] {
+ "volume", "create", vol}));
+ testBuckets.forEach(bucket -> execute(ozoneShell, new String[] {
+ "bucket", "create", firstVolumePrefix + bucket}));
+ testKeys.forEach(key -> execute(ozoneShell, new String[] {
+ "key", "put", keyPathPrefix + key, testFilePathString}));
+
+ // ozone sh volume list
+ out.reset();
+ execute(ozoneShell, new String[] {"volume", "list"});
+
+ // Expect valid JSON array
+ final ArrayList<LinkedTreeMap<String, String>> volumeListOut =
+ parseOutputIntoArrayList();
+ // Can include s3v and volumes from other test cases that aren't cleaned
up,
+ // hence >= instead of equals.
+ Assert.assertTrue(volumeListOut.size() >= testVolumes.size());
+ final HashSet<String> volumeSet = new HashSet<>(testVolumes);
+ volumeListOut.forEach(map -> volumeSet.remove(map.get("name")));
+ // Should have found all the volumes created for this test
+ Assert.assertEquals(0, volumeSet.size());
+
+ // ozone sh bucket list jsontest-vol1
+ out.reset();
+ execute(ozoneShell, new String[] {"bucket", "list", firstVolumePrefix});
+
+ // Expect valid JSON array as well
+ final ArrayList<LinkedTreeMap<String, String>> bucketListOut =
+ parseOutputIntoArrayList();
+ Assert.assertEquals(testBuckets.size(), bucketListOut.size());
+ final HashSet<String> bucketSet = new HashSet<>(testBuckets);
+ bucketListOut.forEach(map -> bucketSet.remove(map.get("name")));
+ // Should have found all the buckets created for this test
+ Assert.assertEquals(0, bucketSet.size());
+
+ // ozone sh key list jsontest-vol1/v1-bucket1
+ out.reset();
+ execute(ozoneShell, new String[] {"key", "list", keyPathPrefix});
+
+ // Expect valid JSON array as well
+ final ArrayList<LinkedTreeMap<String, String>> keyListOut =
+ parseOutputIntoArrayList();
+ Assert.assertEquals(testKeys.size(), keyListOut.size());
+ final HashSet<String> keySet = new HashSet<>(testKeys);
+ keyListOut.forEach(map -> keySet.remove(map.get("name")));
+ // Should have found all the keys put for this test
+ Assert.assertEquals(0, keySet.size());
+
+ // Clean up
+ testKeys.forEach(key -> execute(ozoneShell, new String[] {
+ "key", "delete", keyPathPrefix + key}));
+ testBuckets.forEach(bucket -> execute(ozoneShell, new String[] {
+ "bucket", "delete", firstVolumePrefix + bucket}));
+ testVolumes.forEach(vol -> execute(ozoneShell, new String[] {
+ "volume", "delete", vol}));
+ }
}
diff --git
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/Handler.java
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/Handler.java
index d8f49b9..ae5edf5 100644
---
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/Handler.java
+++
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/Handler.java
@@ -20,8 +20,10 @@ package org.apache.hadoop.ozone.shell;
import java.io.IOException;
import java.io.PrintStream;
+import java.util.Iterator;
import java.util.concurrent.Callable;
+import com.fasterxml.jackson.databind.node.ArrayNode;
import org.apache.hadoop.hdds.cli.GenericParentCommand;
import org.apache.hadoop.hdds.cli.HddsVersionProvider;
import org.apache.hadoop.hdds.conf.OzoneConfiguration;
@@ -118,6 +120,21 @@ public abstract class Handler implements Callable<Void> {
out().println(JsonUtils.toJsonStringWithDefaultPrettyPrinter(o));
}
+ /**
+ * Pretty print the result as a valid JSON array to out().
+ * @return Number of entries actually printed.
+ */
+ protected int printAsJsonArray(Iterator<?> iterator, int limit) {
+ int counter = 0;
+ final ArrayNode arrayNode = JsonUtils.createArrayNode();
+ while (limit > counter && iterator.hasNext()) {
+ arrayNode.add(JsonUtils.createObjectNode(iterator.next()));
+ counter++;
+ }
+ out().println(arrayNode.toPrettyString());
+ return counter;
+ }
+
protected void printMsg(String msg) {
out().println(msg);
}
diff --git
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/bucket/ListBucketHandler.java
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/bucket/ListBucketHandler.java
index 6c01af3..c3178fb 100644
---
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/bucket/ListBucketHandler.java
+++
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/bucket/ListBucketHandler.java
@@ -51,16 +51,10 @@ public class ListBucketHandler extends VolumeHandler {
Iterator<? extends OzoneBucket> bucketIterator =
vol.listBuckets(listOptions.getPrefix(), listOptions.getStartItem());
- int counter = 0;
- while (listOptions.getLimit() > counter && bucketIterator.hasNext()) {
- printObjectAsJson(bucketIterator.next());
-
- counter++;
- }
+ int counter = printAsJsonArray(bucketIterator, listOptions.getLimit());
if (isVerbose()) {
- out().printf("Found : %d buckets for volume : %s ",
- counter, volumeName);
+ out().printf("Found : %d buckets for volume : %s ", counter, volumeName);
}
}
diff --git
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/keys/ListKeyHandler.java
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/keys/ListKeyHandler.java
index 00d04fb..741619b 100644
---
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/keys/ListKeyHandler.java
+++
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/keys/ListKeyHandler.java
@@ -57,13 +57,7 @@ public class ListKeyHandler extends BucketHandler {
listOptions.getPrefix(), listOptions.getStartItem());
int maxKeyLimit = listOptions.getLimit();
-
- int counter = 0;
- while (maxKeyLimit > counter && keyIterator.hasNext()) {
- OzoneKey ozoneKey = keyIterator.next();
- printObjectAsJson(ozoneKey);
- counter++;
- }
+ int counter = printAsJsonArray(keyIterator, maxKeyLimit);
// More keys were returned notify about max length
if (keyIterator.hasNext()) {
diff --git
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/volume/ListVolumeHandler.java
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/volume/ListVolumeHandler.java
index fb0760e..70ccb8d 100644
---
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/volume/ListVolumeHandler.java
+++
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/shell/volume/ListVolumeHandler.java
@@ -84,15 +84,10 @@ public class ListVolumeHandler extends Handler {
listOptions.getPrefix(), listOptions.getStartItem());
}
- int counter = 0;
- while (listOptions.getLimit() > counter && volumeIterator.hasNext()) {
- printObjectAsJson(volumeIterator.next());
- counter++;
- }
+ int counter = printAsJsonArray(volumeIterator, listOptions.getLimit());
if (isVerbose()) {
- out().printf("Found : %d volumes for user : %s ", counter,
- userName);
+ out().printf("Found : %d volumes for user : %s ", counter, userName);
}
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]