diff --git a/hadoop-hdds/docs/content/KeyCommands.md b/hadoop-hdds/docs/content/KeyCommands.md index 1a777625d88..427ee46dfeb 100644 --- a/hadoop-hdds/docs/content/KeyCommands.md +++ b/hadoop-hdds/docs/content/KeyCommands.md @@ -29,6 +29,7 @@ Ozone shell supports the following key commands. * [delete](#delete) * [info](#info) * [list](#list) + * [rename](#rename) ### Get @@ -119,6 +120,22 @@ ozone sh key list /hive/jan This command will list all keys in the bucket _/hive/jan_. +### Rename + +The `key rename` command changes the name of an existing key in the specified bucket. + +***Params:*** + +| Arguments | Comment | +|--------------------------------|-----------------------------------------| +| Uri | The name of the bucket in **/volume/bucket** format. +| FromKey | The existing key to be renamed +| ToKey | The new desired name of the key + +{{< highlight bash >}} +ozone sh key rename /hive/jan sales.orc new_name.orc +{{< /highlight >}} +The above command will rename `sales.orc` to `new_name.orc` in the bucket `/hive/jan`. diff --git a/hadoop-ozone/dist/src/main/smoketest/basic/ozone-shell.robot b/hadoop-ozone/dist/src/main/smoketest/basic/ozone-shell.robot index 14a576170d7..574c50b7a95 100644 --- a/hadoop-ozone/dist/src/main/smoketest/basic/ozone-shell.robot +++ b/hadoop-ozone/dist/src/main/smoketest/basic/ozone-shell.robot @@ -79,4 +79,7 @@ Test key handling Should contain ${result} createdOn ${result} = Execute ozone sh key list ${protocol}${server}/${volume}/bb1 | grep -Ev 'Removed|WARN|DEBUG|ERROR|INFO|TRACE' | jq -r '.[] | select(.keyName=="key1") | .keyName' Should Be Equal ${result} key1 - Execute ozone sh key delete ${protocol}${server}/${volume}/bb1/key1 + Execute ozone sh key rename ${protocol}${server}/${volume}/bb1 key1 key2 + ${result} = Execute ozone sh key list ${protocol}${server}/${volume}/bb1 | grep -Ev 'Removed|WARN|DEBUG|ERROR|INFO|TRACE' | jq -r '.[].keyName' + Should Be Equal ${result} key2 + Execute ozone sh key delete ${protocol}${server}/${volume}/bb1/key2 diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/ozShell/TestOzoneShell.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/ozShell/TestOzoneShell.java index f00c7561160..4bf7d525ac2 100644 --- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/ozShell/TestOzoneShell.java +++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/ozShell/TestOzoneShell.java @@ -950,13 +950,7 @@ public class TestOzoneShell { execute(shell, args); // verify if key has been deleted in the bucket - try { - bucket.getKey(keyName); - fail("Get key should have thrown."); - } catch (IOException e) { - GenericTestUtils.assertExceptionContains( - "Lookup key failed, error:KEY_NOT_FOUND", e); - } + assertKeyNotExists(bucket, keyName); // test delete key in a non-exist bucket args = new String[] {"key", "delete", @@ -971,6 +965,29 @@ public class TestOzoneShell { executeWithError(shell, args, "Delete key failed, error:KEY_NOT_FOUND"); } + @Test + public void testRenameKey() throws Exception { + LOG.info("Running testRenameKey"); + OzoneBucket bucket = creatBucket(); + OzoneKey oldKey = createTestKey(bucket); + + String oldName = oldKey.getName(); + String newName = oldName + ".new"; + String[] args = new String[]{ + "key", "rename", + String.format("%s/%s/%s", + url, oldKey.getVolumeName(), oldKey.getBucketName()), + oldName, + newName + }; + execute(shell, args); + + OzoneKey newKey = bucket.getKey(newName); + assertEquals(oldKey.getCreationTime(), newKey.getCreationTime()); + assertEquals(oldKey.getDataSize(), newKey.getDataSize()); + assertKeyNotExists(bucket, oldName); + } + @Test public void testInfoKeyDetails() throws Exception { LOG.info("Running testInfoKey"); @@ -1245,6 +1262,18 @@ public class TestOzoneShell { return bucketInfo; } + private OzoneKey createTestKey(OzoneBucket bucket) throws IOException { + String key = "key" + RandomStringUtils.randomNumeric(5); + String value = "value"; + + OzoneOutputStream keyOutputStream = + bucket.createKey(key, value.length()); + keyOutputStream.write(value.getBytes()); + keyOutputStream.close(); + + return bucket.getKey(key); + } + @Test public void testTokenCommands() throws Exception { String omAdd = "--set=" + OZONE_OM_ADDRESS_KEY + "=" + getOmAddress(); @@ -1341,4 +1370,15 @@ public class TestOzoneShell { .map(s -> s.getServiceAddress(ServicePort.Type.RPC)) .orElseThrow(IllegalStateException::new); } + + private static void assertKeyNotExists(OzoneBucket bucket, String keyName) { + try { + bucket.getKey(keyName); + fail(String.format("Key %s should not exist, but it does", keyName)); + } catch (IOException e) { + GenericTestUtils.assertExceptionContains( + "Lookup key failed, error:KEY_NOT_FOUND", e); + } + } + } diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/ozShell/keys/KeyCommands.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/ozShell/keys/KeyCommands.java index aada5568b17..0a76c5483cc 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/ozShell/keys/KeyCommands.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/ozShell/keys/KeyCommands.java @@ -39,6 +39,7 @@ import picocli.CommandLine.ParentCommand; ListKeyHandler.class, GetKeyHandler.class, PutKeyHandler.class, + RenameKeyHandler.class, DeleteKeyHandler.class }, mixinStandardHelpOptions = true, diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/ozShell/keys/RenameKeyHandler.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/ozShell/keys/RenameKeyHandler.java new file mode 100644 index 00000000000..b2ecbdacfbf --- /dev/null +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/ozShell/keys/RenameKeyHandler.java @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.hadoop.ozone.web.ozShell.keys; + +import org.apache.hadoop.ozone.client.OzoneBucket; +import org.apache.hadoop.ozone.client.OzoneClient; +import org.apache.hadoop.ozone.client.OzoneVolume; +import org.apache.hadoop.ozone.web.ozShell.Handler; +import org.apache.hadoop.ozone.web.ozShell.OzoneAddress; +import org.apache.hadoop.ozone.web.ozShell.Shell; + +import picocli.CommandLine.Command; +import picocli.CommandLine.Parameters; + +/** + * Renames an existing key. + */ +@Command(name = "rename", + description = "renames an existing key") +public class RenameKeyHandler extends Handler { + + @Parameters(index = "0", arity = "1..1", + description = Shell.OZONE_BUCKET_URI_DESCRIPTION) + private String uri; + + @Parameters(index = "1", arity = "1..1", + description = "The existing key to be renamed") + private String fromKey; + + @Parameters(index = "2", arity = "1..1", + description = "The new desired name of the key") + private String toKey; + + @Override + public Void call() throws Exception { + OzoneAddress address = new OzoneAddress(uri); + address.ensureBucketAddress(); + OzoneClient client = address.createClient(createOzoneConfiguration()); + + String volumeName = address.getVolumeName(); + String bucketName = address.getBucketName(); + + if (isVerbose()) { + System.out.printf("Volume Name : %s%n", volumeName); + System.out.printf("Bucket Name : %s%n", bucketName); + } + + OzoneVolume vol = client.getObjectStore().getVolume(volumeName); + OzoneBucket bucket = vol.getBucket(bucketName); + bucket.renameKey(fromKey, toKey); + + if (isVerbose()) { + System.out.printf("Renamed Key : %s to %s%n", fromKey, toKey); + } + + return null; + } +}