HDDS-438. 'ozone oz' should print usage when command or sub-command is missing. Contributed by Dinesh Chitlangia.

This commit is contained in:
Arpit Agarwal 2018-09-14 07:02:28 -07:00
parent f1a893fdbc
commit a12f12f1af
6 changed files with 82 additions and 11 deletions

View File

@ -67,11 +67,14 @@ public class GenericCli implements Callable<Void>, GenericParentCommand {
} else { } else {
System.err.println(error.getMessage().split("\n")[0]); System.err.println(error.getMessage().split("\n")[0]);
} }
if(error instanceof MissingSubcommandException){
System.err.println(((MissingSubcommandException) error).getUsage());
}
} }
@Override @Override
public Void call() throws Exception { public Void call() throws Exception {
throw new MissingSubcommandException(); throw new MissingSubcommandException(cmd.getUsageMessage());
} }
public OzoneConfiguration createOzoneConfiguration() { public OzoneConfiguration createOzoneConfiguration() {

View File

@ -22,8 +22,14 @@ package org.apache.hadoop.hdds.cli;
*/ */
public class MissingSubcommandException extends RuntimeException { public class MissingSubcommandException extends RuntimeException {
public MissingSubcommandException() { private String usage;
super("Please select a subcommand");
public MissingSubcommandException(String usage) {
super("Incomplete command");
this.usage = usage;
} }
public String getUsage() {
return usage;
}
} }

View File

@ -33,6 +33,7 @@ import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.apache.hadoop.fs.FileUtil; 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.client.ReplicationFactor;
import org.apache.hadoop.hdds.conf.OzoneConfiguration; import org.apache.hadoop.hdds.conf.OzoneConfiguration;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos; import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
@ -236,10 +237,10 @@ public class TestOzoneShell {
assertEquals(userName, volumeInfo.getOwner()); assertEquals(userName, volumeInfo.getOwner());
} }
private void execute(Shell shell, String[] args) { private void execute(Shell ozoneShell, String[] args) {
List<String> arguments = new ArrayList(Arrays.asList(args)); List<String> arguments = new ArrayList(Arrays.asList(args));
LOG.info("Executing shell command with args {}", arguments); LOG.info("Executing shell command with args {}", arguments);
CommandLine cmd = shell.getCmd(); CommandLine cmd = ozoneShell.getCmd();
IExceptionHandler2<List<Object>> exceptionHandler = IExceptionHandler2<List<Object>> exceptionHandler =
new IExceptionHandler2<List<Object>>() { new IExceptionHandler2<List<Object>>() {
@ -309,6 +310,29 @@ public class TestOzoneShell {
executeWithError(shell, args, "VOLUME_NOT_FOUND"); 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=<String=String>]..." +
" [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 @Test
public void testUpdateVolume() throws Exception { public void testUpdateVolume() throws Exception {
LOG.info("Running testUpdateVolume"); LOG.info("Running testUpdateVolume");
@ -352,13 +376,13 @@ public class TestOzoneShell {
* Execute command, assert exeception message and returns true if error * Execute command, assert exeception message and returns true if error
* was thrown. * was thrown.
*/ */
private void executeWithError(Shell shell, String[] args, private void executeWithError(Shell ozoneShell, String[] args,
String expectedError) { String expectedError) {
if (Strings.isNullOrEmpty(expectedError)) { if (Strings.isNullOrEmpty(expectedError)) {
execute(shell, args); execute(ozoneShell, args);
} else { } else {
try { try {
execute(shell, args); execute(ozoneShell, args);
fail("Exception is expected from command execution " + Arrays fail("Exception is expected from command execution " + Arrays
.asList(args)); .asList(args));
} catch (Exception ex) { } 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 @Test
public void testListVolume() throws Exception { public void testListVolume() throws Exception {
LOG.info("Running testListVolume"); LOG.info("Running testListVolume");

View File

@ -49,7 +49,8 @@ public class BucketCommands implements GenericParentCommand, Callable<Void> {
@Override @Override
public Void call() throws Exception { public Void call() throws Exception {
throw new MissingSubcommandException(); throw new MissingSubcommandException(
this.shell.getCmd().getSubcommands().get("bucket").getUsageMessage());
} }
@Override @Override

View File

@ -49,7 +49,8 @@ public class KeyCommands implements GenericParentCommand, Callable<Void> {
@Override @Override
public Void call() throws Exception { public Void call() throws Exception {
throw new MissingSubcommandException(); throw new MissingSubcommandException(
this.shell.getCmd().getSubcommands().get("key").getUsageMessage());
} }
@Override @Override

View File

@ -50,7 +50,8 @@ public class VolumeCommands implements GenericParentCommand, Callable<Void> {
@Override @Override
public Void call() throws Exception { public Void call() throws Exception {
throw new MissingSubcommandException(); throw new MissingSubcommandException(
this.shell.getCmd().getSubcommands().get("volume").getUsageMessage());
} }
@Override @Override