From a12f12f1af22a28bce2d361a506394761cf53aa7 Mon Sep 17 00:00:00 2001 From: Arpit Agarwal Date: Fri, 14 Sep 2018 07:02:28 -0700 Subject: [PATCH] HDDS-438. 'ozone oz' should print usage when command or sub-command is missing. Contributed by Dinesh Chitlangia. --- .../apache/hadoop/hdds/cli/GenericCli.java | 5 +- .../hdds/cli/MissingSubcommandException.java | 10 ++- .../hadoop/ozone/ozShell/TestOzoneShell.java | 69 +++++++++++++++++-- .../web/ozShell/bucket/BucketCommands.java | 3 +- .../ozone/web/ozShell/keys/KeyCommands.java | 3 +- .../web/ozShell/volume/VolumeCommands.java | 3 +- 6 files changed, 82 insertions(+), 11 deletions(-) diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/cli/GenericCli.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/cli/GenericCli.java index 9a0be44355e..e56810cdca4 100644 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/cli/GenericCli.java +++ b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/cli/GenericCli.java @@ -67,11 +67,14 @@ public class GenericCli implements Callable, GenericParentCommand { } else { System.err.println(error.getMessage().split("\n")[0]); } + if(error instanceof MissingSubcommandException){ + System.err.println(((MissingSubcommandException) error).getUsage()); + } } @Override public Void call() throws Exception { - throw new MissingSubcommandException(); + throw new MissingSubcommandException(cmd.getUsageMessage()); } public OzoneConfiguration createOzoneConfiguration() { diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/cli/MissingSubcommandException.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/cli/MissingSubcommandException.java index bf3818f7b97..9f0c4943246 100644 --- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/cli/MissingSubcommandException.java +++ b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/cli/MissingSubcommandException.java @@ -22,8 +22,14 @@ package org.apache.hadoop.hdds.cli; */ public class MissingSubcommandException extends RuntimeException { - public MissingSubcommandException() { - super("Please select a subcommand"); + private String usage; + + public MissingSubcommandException(String usage) { + super("Incomplete command"); + this.usage = usage; } + public String getUsage() { + return usage; + } } 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 f872865e078..c80030eea51 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 @@ -33,6 +33,7 @@ import java.util.UUID; import java.util.stream.Collectors; import org.apache.hadoop.fs.FileUtil; +import org.apache.hadoop.hdds.cli.MissingSubcommandException; import org.apache.hadoop.hdds.client.ReplicationFactor; import org.apache.hadoop.hdds.conf.OzoneConfiguration; import org.apache.hadoop.hdds.protocol.proto.HddsProtos; @@ -236,10 +237,10 @@ public class TestOzoneShell { assertEquals(userName, volumeInfo.getOwner()); } - private void execute(Shell shell, String[] args) { + private void execute(Shell ozoneShell, String[] args) { List arguments = new ArrayList(Arrays.asList(args)); LOG.info("Executing shell command with args {}", arguments); - CommandLine cmd = shell.getCmd(); + CommandLine cmd = ozoneShell.getCmd(); IExceptionHandler2> exceptionHandler = new IExceptionHandler2>() { @@ -309,6 +310,29 @@ public class TestOzoneShell { executeWithError(shell, args, "VOLUME_NOT_FOUND"); } + @Test + public void testShellIncompleteCommand() throws Exception { + LOG.info("Running testShellIncompleteCommand"); + String expectedError = "Incomplete command"; + String[] args = new String[] {}; //executing 'ozone oz' + + executeWithError(shell, args, expectedError, + "Usage: ozone oz [-hV] [--verbose] [-D=]..." + + " [COMMAND]"); + + args = new String[] {"volume"}; //executing 'ozone oz volume' + executeWithError(shell, args, expectedError, + "Usage: ozone oz volume [-hV] [COMMAND]"); + + args = new String[] {"bucket"}; //executing 'ozone oz bucket' + executeWithError(shell, args, expectedError, + "Usage: ozone oz bucket [-hV] [COMMAND]"); + + args = new String[] {"key"}; //executing 'ozone oz key' + executeWithError(shell, args, expectedError, + "Usage: ozone oz key [-hV] [COMMAND]"); + } + @Test public void testUpdateVolume() throws Exception { LOG.info("Running testUpdateVolume"); @@ -352,13 +376,13 @@ public class TestOzoneShell { * Execute command, assert exeception message and returns true if error * was thrown. */ - private void executeWithError(Shell shell, String[] args, + private void executeWithError(Shell ozoneShell, String[] args, String expectedError) { if (Strings.isNullOrEmpty(expectedError)) { - execute(shell, args); + execute(ozoneShell, args); } else { try { - execute(shell, args); + execute(ozoneShell, args); fail("Exception is expected from command execution " + Arrays .asList(args)); } catch (Exception ex) { @@ -378,6 +402,41 @@ public class TestOzoneShell { } } + /** + * Execute command, assert exception message and returns true if error + * was thrown and contains the specified usage string. + */ + private void executeWithError(Shell ozoneShell, String[] args, + String expectedError, String usage) { + if (Strings.isNullOrEmpty(expectedError)) { + execute(ozoneShell, args); + } else { + try { + execute(ozoneShell, args); + fail("Exception is expected from command execution " + Arrays + .asList(args)); + } catch (Exception ex) { + if (!Strings.isNullOrEmpty(expectedError)) { + Throwable exceptionToCheck = ex; + if (exceptionToCheck.getCause() != null) { + exceptionToCheck = exceptionToCheck.getCause(); + } + Assert.assertTrue( + String.format( + "Error of shell code doesn't contain the " + + "exception [%s] in [%s]", + expectedError, exceptionToCheck.getMessage()), + exceptionToCheck.getMessage().contains(expectedError)); + Assert.assertTrue( + exceptionToCheck instanceof MissingSubcommandException); + Assert.assertTrue( + ((MissingSubcommandException)exceptionToCheck) + .getUsage().contains(usage)); + } + } + } + } + @Test public void testListVolume() throws Exception { LOG.info("Running testListVolume"); diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/ozShell/bucket/BucketCommands.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/ozShell/bucket/BucketCommands.java index b2b896633c4..870f4d71986 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/ozShell/bucket/BucketCommands.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/ozShell/bucket/BucketCommands.java @@ -49,7 +49,8 @@ public class BucketCommands implements GenericParentCommand, Callable { @Override public Void call() throws Exception { - throw new MissingSubcommandException(); + throw new MissingSubcommandException( + this.shell.getCmd().getSubcommands().get("bucket").getUsageMessage()); } @Override 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 e9175973260..d0346861e73 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 @@ -49,7 +49,8 @@ public class KeyCommands implements GenericParentCommand, Callable { @Override public Void call() throws Exception { - throw new MissingSubcommandException(); + throw new MissingSubcommandException( + this.shell.getCmd().getSubcommands().get("key").getUsageMessage()); } @Override diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/ozShell/volume/VolumeCommands.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/ozShell/volume/VolumeCommands.java index 111eb78fd48..e3f5d2d38eb 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/ozShell/volume/VolumeCommands.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/web/ozShell/volume/VolumeCommands.java @@ -50,7 +50,8 @@ public class VolumeCommands implements GenericParentCommand, Callable { @Override public Void call() throws Exception { - throw new MissingSubcommandException(); + throw new MissingSubcommandException( + this.shell.getCmd().getSubcommands().get("volume").getUsageMessage()); } @Override