You are viewing a plain text version of this content. The canonical link for it is here.
Posted to common-commits@hadoop.apache.org by zj...@apache.org on 2015/02/11 20:48:53 UTC

[35/50] [abbrv] hadoop git commit: YARN-2616 [YARN-913] Add CLI client to the registry to list, view and manipulate entries. (Akshay Radia via stevel)

YARN-2616 [YARN-913] Add CLI client to the registry to list, view and manipulate entries. (Akshay Radia via stevel)


Project: http://git-wip-us.apache.org/repos/asf/hadoop/repo
Commit: http://git-wip-us.apache.org/repos/asf/hadoop/commit/362565cf
Tree: http://git-wip-us.apache.org/repos/asf/hadoop/tree/362565cf
Diff: http://git-wip-us.apache.org/repos/asf/hadoop/diff/362565cf

Branch: refs/heads/YARN-2928
Commit: 362565cf5a8cbc1e7e66847649c29666d79f6938
Parents: c541a37
Author: Steve Loughran <st...@apache.org>
Authored: Wed Feb 11 14:18:46 2015 +0000
Committer: Steve Loughran <st...@apache.org>
Committed: Wed Feb 11 14:19:01 2015 +0000

----------------------------------------------------------------------
 hadoop-yarn-project/CHANGES.txt                 |   3 +
 .../apache/hadoop/registry/cli/RegistryCli.java | 425 +++++++++++--------
 .../hadoop/registry/cli/TestRegistryCli.java    | 197 +++++++++
 3 files changed, 439 insertions(+), 186 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hadoop/blob/362565cf/hadoop-yarn-project/CHANGES.txt
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/CHANGES.txt b/hadoop-yarn-project/CHANGES.txt
index 41927d7..14b3462 100644
--- a/hadoop-yarn-project/CHANGES.txt
+++ b/hadoop-yarn-project/CHANGES.txt
@@ -78,6 +78,9 @@ Release 2.7.0 - UNRELEASED
     YARN-2217. [YARN-1492] Shared cache client side changes. 
     (Chris Trezzo via kasha)
 
+     YARN-2616 [YARN-913] Add CLI client to the registry to list, view
+     and manipulate entries. (Akshay Radia via stevel)
+
   IMPROVEMENTS
 
     YARN-3005. [JDK7] Use switch statement for String instead of if-else

http://git-wip-us.apache.org/repos/asf/hadoop/blob/362565cf/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-registry/src/main/java/org/apache/hadoop/registry/cli/RegistryCli.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-registry/src/main/java/org/apache/hadoop/registry/cli/RegistryCli.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-registry/src/main/java/org/apache/hadoop/registry/cli/RegistryCli.java
index bf2b5e5..480ce0e 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-registry/src/main/java/org/apache/hadoop/registry/cli/RegistryCli.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-registry/src/main/java/org/apache/hadoop/registry/cli/RegistryCli.java
@@ -19,6 +19,7 @@ package org.apache.hadoop.registry.cli;
 
 import static org.apache.hadoop.registry.client.binding.RegistryTypeUtils.*;
 
+import java.io.Closeable;
 import java.io.IOException;
 import java.io.PrintStream;
 import java.net.URI;
@@ -34,12 +35,14 @@ import org.apache.commons.cli.Option;
 import org.apache.commons.cli.OptionBuilder;
 import org.apache.commons.cli.Options;
 import org.apache.commons.cli.ParseException;
+import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.conf.Configured;
 import org.apache.hadoop.fs.PathNotFoundException;
 import org.apache.hadoop.security.AccessControlException;
+import org.apache.hadoop.service.ServiceOperations;
+import org.apache.hadoop.util.ExitUtil;
 import org.apache.hadoop.util.Tool;
 import org.apache.hadoop.util.ToolRunner;
-import org.apache.hadoop.yarn.conf.YarnConfiguration;
 import org.apache.hadoop.registry.client.api.BindFlags;
 import org.apache.hadoop.registry.client.api.RegistryOperations;
 import org.apache.hadoop.registry.client.api.RegistryOperationsFactory;
@@ -54,41 +57,76 @@ import org.apache.hadoop.registry.client.types.ServiceRecord;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class RegistryCli extends Configured implements Tool {
+/**
+ * Command line for registry operations.
+ */
+public class RegistryCli extends Configured implements Tool, Closeable {
   private static final Logger LOG =
       LoggerFactory.getLogger(RegistryCli.class);
-	protected final PrintStream sysout;
-	protected final PrintStream syserr;
+  protected final PrintStream sysout;
+  protected final PrintStream syserr;
 
 
-	private RegistryOperations registry;
+  private RegistryOperations registry;
 
-  static final String LS_USAGE = "ls pathName";
-  static final String RESOLVE_USAGE = "resolve pathName";
-  static final String BIND_USAGE =
+  private static final String LS_USAGE = "ls pathName";
+  private static final String RESOLVE_USAGE = "resolve pathName";
+  private static final String BIND_USAGE =
       "bind -inet  -api apiName -p portNumber -h hostName  pathName" + "\n"
       + "bind -webui uriString -api apiName  pathName" + "\n"
       + "bind -rest uriString -api apiName  pathName";
-  static final String MKNODE_USAGE = "mknode directoryName";
-  static final String RM_USAGE = "rm pathName";
-  static final String USAGE =
+  private static final String MKNODE_USAGE = "mknode directoryName";
+  private static final String RM_USAGE = "rm pathName";
+  private static final String USAGE =
       "\n" + LS_USAGE + "\n" + RESOLVE_USAGE + "\n" + BIND_USAGE + "\n" +
       MKNODE_USAGE + "\n" + RM_USAGE;
 
 
-
-	public RegistryCli(PrintStream sysout, PrintStream syserr) {
-	    super(new YarnConfiguration());
+  public RegistryCli(PrintStream sysout, PrintStream syserr) {
+    Configuration conf = new Configuration();
+    super.setConf(conf);
+    registry = RegistryOperationsFactory.createInstance(conf);
+    registry.start();
     this.sysout = sysout;
     this.syserr = syserr;
-	}
+  }
 
+  public RegistryCli(RegistryOperations reg,
+      Configuration conf,
+      PrintStream sysout,
+      PrintStream syserr) {
+    super(conf);
+    Preconditions.checkArgument(reg != null, "Null registry");
+    registry = reg;
+    this.sysout = sysout;
+    this.syserr = syserr;
+  }
 
   @SuppressWarnings("UseOfSystemOutOrSystemErr")
   public static void main(String[] args) throws Exception {
-    RegistryCli cli = new RegistryCli(System.out, System.err);
-    int res = ToolRunner.run(cli, args);
-    System.exit(res);
+    int res = -1;
+    try (RegistryCli cli = new RegistryCli(System.out, System.err)) {
+      res = ToolRunner.run(cli, args);
+    } catch (Exception e) {
+      ExitUtil.terminate(res, e);
+    }
+    ExitUtil.terminate(res);
+  }
+
+  /**
+   * Close the object by stopping the registry.
+   * <p>
+   * <i>Important:</i>
+   * <p>
+   *   After this call is made, no operations may be made of this
+   *   object, <i>or of a YARN registry instance used when constructing
+   *   this object. </i>
+   * @throws IOException
+   */
+  @Override
+  public void close() throws IOException {
+    ServiceOperations.stopQuietly(registry);
+    registry = null;
   }
 
   private int usageError(String err, String usage) {
@@ -104,146 +142,151 @@ public class RegistryCli extends Configured implements Tool {
     }
     return true;
   }
+
   @Override
   public int run(String[] args) throws Exception {
     Preconditions.checkArgument(getConf() != null, "null configuration");
-    registry = RegistryOperationsFactory.createInstance(
-        new YarnConfiguration(getConf()));
-    registry.start();
     if (args.length > 0) {
-      if (args[0].equals("ls")) {
-        return ls(args);
-      } else if (args[0].equals("resolve")) {
-        return resolve(args);
-      } else if (args[0].equals("bind")) {
-        return bind(args);
-      } else if (args[0].equals("mknode")) {
-        return mknode(args);
-      } else if (args[0].equals("rm")) {
-        return rm(args);
+      switch (args[0]) {
+        case "ls":
+          return ls(args);
+        case "resolve":
+          return resolve(args);
+        case "bind":
+          return bind(args);
+        case "mknode":
+          return mknode(args);
+        case "rm":
+          return rm(args);
+        default:
+          return usageError("Invalid command: " + args[0], USAGE);
       }
     }
-    return usageError("Invalid command: " + args[0], USAGE);
+    return usageError("No command arg passed.", USAGE);
   }
 
   @SuppressWarnings("unchecked")
-	public int ls(String [] args) {
-
-		Options lsOption = new Options();
-		CommandLineParser parser = new GnuParser();
-		try {
-			CommandLine line = parser.parse(lsOption, args);
-
-			List<String> argsList = line.getArgList();
-			if (argsList.size() != 2) {
-				return usageError("ls requires exactly one path argument", LS_USAGE);
-		    }
-			if (!validatePath(argsList.get(1)))
-				return -1;
-
-			try {
-				List<String> children = registry.list(argsList.get(1));
+  public int ls(String[] args) {
+
+    Options lsOption = new Options();
+    CommandLineParser parser = new GnuParser();
+    try {
+      CommandLine line = parser.parse(lsOption, args);
+
+      List<String> argsList = line.getArgList();
+      if (argsList.size() != 2) {
+        return usageError("ls requires exactly one path argument", LS_USAGE);
+      }
+      if (!validatePath(argsList.get(1))) {
+        return -1;
+      }
+
+      try {
+        List<String> children = registry.list(argsList.get(1));
         for (String child : children) {
           sysout.println(child);
         }
-				return 0;
+        return 0;
 
       } catch (Exception e) {
         syserr.println(analyzeException("ls", e, argsList));
       }
-			return -1;
-		} catch (ParseException exp) {
-			return usageError("Invalid syntax " + exp, LS_USAGE);
-		}
-	}
+      return -1;
+    } catch (ParseException exp) {
+      return usageError("Invalid syntax " + exp, LS_USAGE);
+    }
+  }
 
   @SuppressWarnings("unchecked")
-  public int resolve(String [] args) {
-		Options resolveOption = new Options();
-		CommandLineParser parser = new GnuParser();
-		try {
-			CommandLine line = parser.parse(resolveOption, args);
-
-			List<String> argsList = line.getArgList();
-			if (argsList.size() != 2) {
-				return usageError("resolve requires exactly one path argument", RESOLVE_USAGE);
-		    }
-			if (!validatePath(argsList.get(1)))
-				return -1;
-
-			try {
-				ServiceRecord record = registry.resolve(argsList.get(1));
-
-				for (Endpoint endpoint : record.external) {
-						sysout.println(" Endpoint(ProtocolType="
-								+ endpoint.protocolType + ", Api="
-								+ endpoint.api + ");"
-								+ " Addresses(AddressType="
-								+ endpoint.addressType + ") are: ");
+  public int resolve(String[] args) {
+    Options resolveOption = new Options();
+    CommandLineParser parser = new GnuParser();
+    try {
+      CommandLine line = parser.parse(resolveOption, args);
+
+      List<String> argsList = line.getArgList();
+      if (argsList.size() != 2) {
+        return usageError("resolve requires exactly one path argument",
+            RESOLVE_USAGE);
+      }
+      if (!validatePath(argsList.get(1))) {
+        return -1;
+      }
+
+      try {
+        ServiceRecord record = registry.resolve(argsList.get(1));
+
+        for (Endpoint endpoint : record.external) {
+          sysout.println(" Endpoint(ProtocolType="
+                         + endpoint.protocolType + ", Api="
+                         + endpoint.api + ");"
+                         + " Addresses(AddressType="
+                         + endpoint.addressType + ") are: ");
 
           for (Map<String, String> address : endpoint.addresses) {
-            sysout.println("  [ ");
+            sysout.println("[ ");
             for (Map.Entry<String, String> entry : address.entrySet()) {
-              sysout.println("    " + entry.getKey()
-                             + ": \"" + entry.getValue() + "\"");
+              sysout.print("\t" + entry.getKey()
+                             + ":" + entry.getValue());
             }
-            sysout.println("  ]");
+
+            sysout.println("\n]");
           }
           sysout.println();
         }
-				return 0;
+        return 0;
       } catch (Exception e) {
         syserr.println(analyzeException("resolve", e, argsList));
       }
-			return -1;
-		} catch (org.apache.commons.cli.ParseException exp) {
-			return usageError("Invalid syntax " + exp, RESOLVE_USAGE);
-		}
-
-	}
-
-	public int bind(String [] args) {
-		Option rest = OptionBuilder.withArgName("rest")
-				.hasArg()
-				.withDescription("rest Option")
-				.create("rest");
-		Option webui = OptionBuilder.withArgName("webui")
-				.hasArg()
-				.withDescription("webui Option")
-				.create("webui");
-		Option inet = OptionBuilder.withArgName("inet")
-				.withDescription("inet Option")
-				.create("inet");
-		Option port = OptionBuilder.withArgName("port")
-				.hasArg()
-				.withDescription("port to listen on [9999]")
-				.create("p");
-		Option host = OptionBuilder.withArgName("host")
-				.hasArg()
-				.withDescription("host name")
-				.create("h");
-		Option apiOpt = OptionBuilder.withArgName("api")
-				.hasArg()
-				.withDescription("api")
-				.create("api");
-		Options inetOption = new Options();
-		inetOption.addOption(inet);
-		inetOption.addOption(port);
-		inetOption.addOption(host);
-		inetOption.addOption(apiOpt);
-
-		Options webuiOpt = new Options();
-		webuiOpt.addOption(webui);
-		webuiOpt.addOption(apiOpt);
-
-		Options restOpt = new Options();
-		restOpt.addOption(rest);
-		restOpt.addOption(apiOpt);
+      return -1;
+    } catch (ParseException exp) {
+      return usageError("Invalid syntax " + exp, RESOLVE_USAGE);
+    }
+
+  }
+
+  public int bind(String[] args) {
+    Option rest = OptionBuilder.withArgName("rest")
+                               .hasArg()
+                               .withDescription("rest Option")
+                               .create("rest");
+    Option webui = OptionBuilder.withArgName("webui")
+                                .hasArg()
+                                .withDescription("webui Option")
+                                .create("webui");
+    Option inet = OptionBuilder.withArgName("inet")
+                               .withDescription("inet Option")
+                               .create("inet");
+    Option port = OptionBuilder.withArgName("port")
+                               .hasArg()
+                               .withDescription("port to listen on [9999]")
+                               .create("p");
+    Option host = OptionBuilder.withArgName("host")
+                               .hasArg()
+                               .withDescription("host name")
+                               .create("h");
+    Option apiOpt = OptionBuilder.withArgName("api")
+                                 .hasArg()
+                                 .withDescription("api")
+                                 .create("api");
+    Options inetOption = new Options();
+    inetOption.addOption(inet);
+    inetOption.addOption(port);
+    inetOption.addOption(host);
+    inetOption.addOption(apiOpt);
+
+    Options webuiOpt = new Options();
+    webuiOpt.addOption(webui);
+    webuiOpt.addOption(apiOpt);
+
+    Options restOpt = new Options();
+    restOpt.addOption(rest);
+    restOpt.addOption(apiOpt);
 
 
     CommandLineParser parser = new GnuParser();
     ServiceRecord sr = new ServiceRecord();
-    CommandLine line = null;
+    CommandLine line;
     if (args.length <= 1) {
       return usageError("Invalid syntax ", BIND_USAGE);
     }
@@ -259,7 +302,12 @@ public class RegistryCli extends Configured implements Tool {
       }
       if (line.hasOption("inet") && line.hasOption("p") &&
           line.hasOption("h") && line.hasOption("api")) {
-        portNum = Integer.parseInt(line.getOptionValue("p"));
+        try {
+          portNum = Integer.parseInt(line.getOptionValue("p"));
+        } catch (NumberFormatException exp) {
+          return usageError("Invalid Port - int required" + exp.getMessage(),
+              BIND_USAGE);
+        }
         hostName = line.getOptionValue("h");
         api = line.getOptionValue("api");
         sr.addExternalEndpoint(
@@ -278,7 +326,7 @@ public class RegistryCli extends Configured implements Tool {
         return usageError("Invalid syntax " + exp.getMessage(), BIND_USAGE);
       }
       if (line.hasOption("webui") && line.hasOption("api")) {
-        URI theUri = null;
+        URI theUri;
         try {
           theUri = new URI(line.getOptionValue("webui"));
         } catch (URISyntaxException e) {
@@ -315,86 +363,91 @@ public class RegistryCli extends Configured implements Tool {
       return usageError("Invalid syntax", BIND_USAGE);
     }
     @SuppressWarnings("unchecked")
-		List<String> argsList = line.getArgList();
-		if (argsList.size() != 2) {
-			return usageError("bind requires exactly one path argument", BIND_USAGE);
-	    }
-		if (!validatePath(argsList.get(1)))
-			return -1;
-
-		try {
-			registry.bind(argsList.get(1), sr, BindFlags.OVERWRITE);
-			return 0;
+    List<String> argsList = line.getArgList();
+    if (argsList.size() != 2) {
+      return usageError("bind requires exactly one path argument", BIND_USAGE);
+    }
+    if (!validatePath(argsList.get(1))) {
+      return -1;
+    }
+
+    try {
+      registry.bind(argsList.get(1), sr, BindFlags.OVERWRITE);
+      return 0;
     } catch (Exception e) {
       syserr.println(analyzeException("bind", e, argsList));
     }
 
     return -1;
-	}
+  }
 
   @SuppressWarnings("unchecked")
-	public int mknode(String [] args) {
-		Options mknodeOption = new Options();
-		CommandLineParser parser = new GnuParser();
-		try {
-			CommandLine line = parser.parse(mknodeOption, args);
-
-			List<String> argsList = line.getArgList();
-			if (argsList.size() != 2) {
-				return usageError("mknode requires exactly one path argument", MKNODE_USAGE);
-		    }
-			if (!validatePath(argsList.get(1)))
-				return -1;
-
-			try {
-				registry.mknode(args[1], false);
-				return 0;
-			} catch (Exception e) {
+  public int mknode(String[] args) {
+    Options mknodeOption = new Options();
+    CommandLineParser parser = new GnuParser();
+    try {
+      CommandLine line = parser.parse(mknodeOption, args);
+
+      List<String> argsList = line.getArgList();
+      if (argsList.size() != 2) {
+        return usageError("mknode requires exactly one path argument",
+            MKNODE_USAGE);
+      }
+      if (!validatePath(argsList.get(1))) {
+        return -1;
+      }
+
+      try {
+        registry.mknode(args[1], false);
+        return 0;
+      } catch (Exception e) {
         syserr.println(analyzeException("mknode", e, argsList));
-			}
-			return -1;
-		} catch (ParseException exp) {
-			return usageError("Invalid syntax " + exp.toString(), MKNODE_USAGE);
-		}
-	}
+      }
+      return -1;
+    } catch (ParseException exp) {
+      return usageError("Invalid syntax " + exp.toString(), MKNODE_USAGE);
+    }
+  }
 
 
   @SuppressWarnings("unchecked")
   public int rm(String[] args) {
-		Option recursive = OptionBuilder.withArgName("recursive")
-				.withDescription("delete recursively").create("r");
+    Option recursive = OptionBuilder.withArgName("recursive")
+                                    .withDescription("delete recursively")
+                                    .create("r");
 
-		Options rmOption = new Options();
-		rmOption.addOption(recursive);
+    Options rmOption = new Options();
+    rmOption.addOption(recursive);
 
-		boolean recursiveOpt = false;
+    boolean recursiveOpt = false;
 
-		CommandLineParser parser = new GnuParser();
-		try {
-			CommandLine line = parser.parse(rmOption, args);
+    CommandLineParser parser = new GnuParser();
+    try {
+      CommandLine line = parser.parse(rmOption, args);
 
-			List<String> argsList = line.getArgList();
-			if (argsList.size() != 2) {
-				return usageError("RM requires exactly one path argument", RM_USAGE);
-		    }
-			if (!validatePath(argsList.get(1)))
-				return -1;
+      List<String> argsList = line.getArgList();
+      if (argsList.size() != 2) {
+        return usageError("RM requires exactly one path argument", RM_USAGE);
+      }
+      if (!validatePath(argsList.get(1))) {
+        return -1;
+      }
 
-			try {
-				if (line.hasOption("r")) {
-					recursiveOpt = true;
-				}
+      try {
+        if (line.hasOption("r")) {
+          recursiveOpt = true;
+        }
 
-				registry.delete(argsList.get(1), recursiveOpt);
-				return 0;
+        registry.delete(argsList.get(1), recursiveOpt);
+        return 0;
       } catch (Exception e) {
         syserr.println(analyzeException("rm", e, argsList));
       }
       return -1;
-		} catch (ParseException exp) {
-			return usageError("Invalid syntax " + exp.toString(), RM_USAGE);
-		}
-	}
+    } catch (ParseException exp) {
+      return usageError("Invalid syntax " + exp.toString(), RM_USAGE);
+    }
+  }
 
   /**
    * Given an exception and a possibly empty argument list, generate

http://git-wip-us.apache.org/repos/asf/hadoop/blob/362565cf/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-registry/src/test/java/org/apache/hadoop/registry/cli/TestRegistryCli.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-registry/src/test/java/org/apache/hadoop/registry/cli/TestRegistryCli.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-registry/src/test/java/org/apache/hadoop/registry/cli/TestRegistryCli.java
new file mode 100644
index 0000000..bd8a38d
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-registry/src/test/java/org/apache/hadoop/registry/cli/TestRegistryCli.java
@@ -0,0 +1,197 @@
+/*
+ * 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.registry.cli;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+
+import org.apache.hadoop.registry.AbstractRegistryTest;
+import org.apache.hadoop.registry.operations.TestRegistryOperations;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TestRegistryCli extends AbstractRegistryTest {
+  protected static final Logger LOG =
+      LoggerFactory.getLogger(TestRegistryOperations.class);
+
+  private ByteArrayOutputStream sysOutStream;
+  private PrintStream sysOut;
+  private ByteArrayOutputStream sysErrStream;
+  private PrintStream sysErr;
+  private RegistryCli cli;
+
+  @Before
+  public void setUp() throws Exception {
+    sysOutStream = new ByteArrayOutputStream();
+    sysOut = new PrintStream(sysOutStream);
+    sysErrStream = new ByteArrayOutputStream();
+    sysErr = new PrintStream(sysErrStream);
+    System.setOut(sysOut);
+    cli = new RegistryCli(operations, createRegistryConfiguration(), sysOut, sysErr);
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    cli.close();
+  }
+
+  private void assertResult(RegistryCli cli, int code, String...args) throws Exception {
+    int result = cli.run(args);
+    assertEquals(code, result);
+  }
+
+  @Test
+  public void testBadCommands() throws Exception {
+    assertResult(cli, -1, new String[] { });
+    assertResult(cli, -1, "foo");
+  }
+
+  @Test
+  public void testInvalidNumArgs() throws Exception {
+    assertResult(cli, -1, "ls");
+    assertResult(cli, -1, "ls", "/path", "/extraPath");
+    assertResult(cli, -1, "resolve");
+    assertResult(cli, -1, "resolve", "/path", "/extraPath");
+    assertResult(cli, -1, "mknode");
+    assertResult(cli, -1, "mknode", "/path", "/extraPath");
+    assertResult(cli, -1, "rm");
+    assertResult(cli, -1, "rm", "/path", "/extraPath");
+    assertResult(cli, -1, "bind");
+    assertResult(cli, -1, "bind", "foo");
+    assertResult(cli, -1, "bind", "-inet", "foo");
+    assertResult(cli, -1, "bind", "-inet", "-api", "-p", "378", "-h", "host", "/foo");
+    assertResult(cli, -1, "bind", "-inet", "-api", "Api", "-p", "-h", "host", "/foo");
+    assertResult(cli, -1, "bind", "-inet", "-api", "Api", "-p", "378", "-h", "/foo");
+    assertResult(cli, -1, "bind", "-inet", "-api", "Api", "-p", "378", "-h", "host");
+    assertResult(cli, -1, "bind", "-api", "Api", "-p", "378", "-h", "host", "/foo");
+    assertResult(cli, -1, "bind", "-webui", "foo");
+    assertResult(cli, -1, "bind", "-webui", "-api", "Api", "/foo");
+    assertResult(cli, -1, "bind", "-webui", "uriString", "-api", "/foo");
+    assertResult(cli, -1, "bind", "-webui", "uriString", "-api", "Api");
+    assertResult(cli, -1, "bind", "-rest", "foo");
+    assertResult(cli, -1, "bind", "-rest", "uriString", "-api", "Api");
+    assertResult(cli, -1, "bind", "-rest", "-api", "Api", "/foo");
+    assertResult(cli, -1, "bind", "-rest", "uriString", "-api", "/foo");
+    assertResult(cli, -1, "bind", "uriString", "-api", "Api", "/foo");
+  }
+
+  @Test
+  public void testBadArgType() throws Exception {
+    assertResult(cli, -1, "bind", "-inet", "-api", "Api", "-p", "fooPort", "-h",
+        "host", "/dir");
+  }
+
+  @Test
+  public void testBadPath() throws Exception {
+    assertResult(cli, -1, "ls", "NonSlashPath");
+    assertResult(cli, -1, "ls", "//");
+    assertResult(cli, -1, "resolve", "NonSlashPath");
+    assertResult(cli, -1, "resolve", "//");
+    assertResult(cli, -1, "mknode", "NonSlashPath");
+    assertResult(cli, -1, "mknode", "//");
+    assertResult(cli, -1, "rm", "NonSlashPath");
+    assertResult(cli, -1, "rm", "//");
+    assertResult(cli, -1, "bind", "-inet", "-api", "Api", "-p", "378", "-h", "host", "NonSlashPath");
+    assertResult(cli, -1, "bind", "-inet", "-api", "Api", "-p", "378", "-h", "host", "//");
+    assertResult(cli, -1, "bind", "-webui", "uriString", "-api", "Api", "NonSlashPath");
+    assertResult(cli, -1, "bind", "-webui", "uriString", "-api", "Api", "//");
+    assertResult(cli, -1, "bind", "-rest", "uriString", "-api", "Api", "NonSlashPath");
+    assertResult(cli, -1, "bind", "-rest", "uriString", "-api", "Api", "//");
+  }
+
+  @Test
+  public void testNotExistingPaths() throws Exception {
+    assertResult(cli, -1, "ls", "/nonexisting_path");
+    assertResult(cli, -1, "ls", "/NonExistingDir/nonexisting_path");
+    assertResult(cli, -1, "resolve", "/nonexisting_path");
+    assertResult(cli, -1, "resolve", "/NonExistingDir/nonexisting_path");
+    assertResult(cli, -1, "bind", "-inet", "-api", "Api", "-p", "378", "-h", "host", "/NonExistingDir/nonexisting_path");
+    assertResult(cli, -1, "bind", "-webui", "uriString", "-api", "Api", "/NonExistingDir/nonexisting_path");
+    assertResult(cli, -1, "bind", "-rest", "uriString", "-api", "Api", "/NonExistingDir/nonexisting_path");
+  }
+
+  @Test
+  public void testValidCommands() throws Exception {
+    assertResult(cli, 0, "bind", "-inet", "-api", "Api", "-p", "378", "-h", "host", "/foo");
+    assertResult(cli, 0, "resolve", "/foo");
+    assertResult(cli, 0, "rm", "/foo");
+    assertResult(cli, -1, "resolve", "/foo");
+
+    assertResult(cli, 0, "bind", "-webui", "uriString", "-api", "Api", "/foo");
+    assertResult(cli, 0, "resolve", "/foo");
+    assertResult(cli, 0, "rm", "/foo");
+    assertResult(cli, -1, "resolve", "/foo");
+
+    assertResult(cli, 0, "bind", "-rest", "uriString", "-api", "Api", "/foo");
+    assertResult(cli, 0, "resolve", "/foo");
+    assertResult(cli, 0, "rm", "/foo");
+    assertResult(cli, -1, "resolve", "/foo");
+
+    //Test Sub Directories Binds
+    assertResult(cli, 0, "mknode", "/subdir");
+    assertResult(cli, -1, "resolve", "/subdir");
+
+    assertResult(cli, 0, "bind", "-inet", "-api", "Api", "-p", "378", "-h", "host", "/subdir/foo");
+    assertResult(cli, 0, "resolve", "/subdir/foo");
+    assertResult(cli, 0, "rm", "/subdir/foo");
+    assertResult(cli, -1, "resolve", "/subdir/foo");
+
+    assertResult(cli, 0, "bind", "-webui", "uriString", "-api", "Api", "/subdir/foo");
+    assertResult(cli, 0, "resolve", "/subdir/foo");
+    assertResult(cli, 0, "rm", "/subdir/foo");
+    assertResult(cli, -1, "resolve", "/subdir/foo");
+
+    assertResult(cli, 0, "bind", "-rest", "uriString", "-api", "Api", "/subdir/foo");
+    assertResult(cli, 0, "resolve", "/subdir/foo");
+    assertResult(cli, 0, "rm", "/subdir/foo");
+    assertResult(cli, -1, "resolve", "/subdir/foo");
+
+    assertResult(cli, 0, "rm", "/subdir");
+    assertResult(cli, -1, "resolve", "/subdir");
+
+    //Test Bind that the dir itself
+    assertResult(cli, 0, "mknode", "/dir");
+    assertResult(cli, -1, "resolve", "/dir");
+
+    assertResult(cli, 0, "bind", "-inet", "-api", "Api", "-p", "378", "-h", "host", "/dir");
+    assertResult(cli, 0, "resolve", "/dir");
+    assertResult(cli, 0, "rm", "/dir");
+    assertResult(cli, -1, "resolve", "/dir");
+
+    assertResult(cli, 0, "mknode", "/dir");
+    assertResult(cli, -1, "resolve", "/dir");
+
+    assertResult(cli, 0, "bind", "-webui", "uriString", "-api", "Api", "/dir");
+    assertResult(cli, 0, "resolve", "/dir");
+    assertResult(cli, 0, "rm", "/dir");
+    assertResult(cli, -1, "resolve", "/dir");
+
+    assertResult(cli, 0, "mknode", "/dir");
+    assertResult(cli, -1, "resolve", "/dir");
+
+    assertResult(cli, 0, "bind", "-rest", "uriString", "-api", "Api", "/dir");
+    assertResult(cli, 0, "resolve", "/dir");
+    assertResult(cli, 0, "rm", "/dir");
+    assertResult(cli, -1, "resolve", "/dir");
+
+    assertResult(cli, 0, "rm", "/Nonexitent");
+  }
+}