Repository: incubator-slider Updated Branches: refs/heads/develop 51a450999 -> f6e2972a7
SLIDER-458 Slider CLI help is very verbose (Thomas Liu via gourksaha) Project: http://git-wip-us.apache.org/repos/asf/incubator-slider/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-slider/commit/f6e2972a Tree: http://git-wip-us.apache.org/repos/asf/incubator-slider/tree/f6e2972a Diff: http://git-wip-us.apache.org/repos/asf/incubator-slider/diff/f6e2972a Branch: refs/heads/develop Commit: f6e2972a741bcd9a2ca716d400bf5ed4f23da1d7 Parents: 51a4509 Author: Gour Saha <[email protected]> Authored: Fri Oct 17 13:25:23 2014 -0700 Committer: Gour Saha <[email protected]> Committed: Fri Oct 17 13:27:12 2014 -0700 ---------------------------------------------------------------------- slider-assembly/src/main/scripts/slider | 4 +- .../org/apache/slider/client/SliderClient.java | 490 ++++++++++--------- .../common/params/ActionDiagnosticArgs.java | 13 +- .../slider/common/params/ActionHelpArgs.java | 2 +- .../common/params/ActionRegistryArgs.java | 5 +- .../apache/slider/common/params/ClientArgs.java | 8 +- .../apache/slider/common/params/CommonArgs.java | 64 ++- .../slider/common/params/SliderActions.java | 1 - .../slider/client/TestClientBadArgs.groovy | 12 +- .../slider/client/TestClientBasicArgs.groovy | 8 +- .../funtest/commands/SimpleCommandsIT.groovy | 2 +- 11 files changed, 328 insertions(+), 281 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/f6e2972a/slider-assembly/src/main/scripts/slider ---------------------------------------------------------------------- diff --git a/slider-assembly/src/main/scripts/slider b/slider-assembly/src/main/scripts/slider index 0b666e8..24ae64e 100755 --- a/slider-assembly/src/main/scripts/slider +++ b/slider-assembly/src/main/scripts/slider @@ -72,7 +72,9 @@ export CLASSPATH="${slider_classpath}" #echo "slider_jvm_opts = \"${slider_jvm_opts}\"" #echo "classpath = \"${slider_classpath}\"" #echo "" -# echo "command is java ${slider_jvm_opts} -classpath \"${slider_classpath}\" ${launcher} $@" + +#echo "command is java ${slider_jvm_opts} -classpath \"${slider_classpath}\" ${launcher} $@" + #echo "" #echo "" http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/f6e2972a/slider-core/src/main/java/org/apache/slider/client/SliderClient.java ---------------------------------------------------------------------- diff --git a/slider-core/src/main/java/org/apache/slider/client/SliderClient.java b/slider-core/src/main/java/org/apache/slider/client/SliderClient.java index da3b913..48fa6c8 100644 --- a/slider-core/src/main/java/org/apache/slider/client/SliderClient.java +++ b/slider-core/src/main/java/org/apache/slider/client/SliderClient.java @@ -20,6 +20,7 @@ package org.apache.slider.client; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; + import org.apache.commons.lang.StringUtils; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.Path; @@ -46,6 +47,7 @@ import org.apache.hadoop.yarn.conf.YarnConfiguration; import org.apache.hadoop.yarn.exceptions.YarnException; import org.apache.hadoop.registry.client.api.RegistryConstants; import org.apache.hadoop.registry.client.api.RegistryOperations; + import static org.apache.hadoop.registry.client.binding.RegistryUtils.*; import org.apache.hadoop.registry.client.binding.RegistryUtils; @@ -80,6 +82,7 @@ import org.apache.slider.common.params.ActionStatusArgs; import org.apache.slider.common.params.ActionThawArgs; import org.apache.slider.common.params.Arguments; import org.apache.slider.common.params.ClientArgs; +import org.apache.slider.common.params.CommonArgs; import org.apache.slider.common.params.LaunchArgsAccessor; import org.apache.slider.common.tools.ConfigHelper; import org.apache.slider.common.tools.Duration; @@ -351,8 +354,7 @@ public class SliderClient extends AbstractSliderLaunchedService implements RunSe serviceArgs.getActionExistsArgs().live); } else if (ACTION_FLEX.equals(action)) { exitCode = actionFlex(clusterName, serviceArgs.getActionFlexArgs()); - } else if (ACTION_HELP.equals(action) || - ACTION_USAGE.equals(action)) { + } else if (ACTION_HELP.equals(action)) { log.info(serviceArgs.usage()); } else if (ACTION_KILL_CONTAINER.equals(action)) { exitCode = actionKillContainer(clusterName, @@ -373,6 +375,9 @@ public class SliderClient extends AbstractSliderLaunchedService implements RunSe exitCode = actionUpdate(clusterName, serviceArgs.getActionUpdateArgs()); } else if (ACTION_VERSION.equals(action)) { exitCode = actionVersion(); + } else if (SliderUtils.isUnset(action)) { + throw new SliderException(EXIT_USAGE, + serviceArgs.usage()); } else { throw new SliderException(EXIT_UNIMPLEMENTED, "Unimplemented: " + action); @@ -2349,7 +2354,7 @@ public class SliderClient extends AbstractSliderLaunchedService implements RunSe outputExport(publishedExports, registryArgs); } else { // it's an unknown command - log.info(ActionRegistryArgs.USAGE); + log.info(CommonArgs.usage(serviceArgs, ACTION_DIAGNOSTIC)); return EXIT_USAGE; } // JDK7 @@ -2410,237 +2415,245 @@ public class SliderClient extends AbstractSliderLaunchedService implements RunSe return serviceRecords; } - @Override + @Override public int actionDiagnostic(ActionDiagnosticArgs diagnosticArgs) { - try { - if (diagnosticArgs.client) { - actionDiagnosticClient(diagnosticArgs); - } else if (SliderUtils.isSet(diagnosticArgs.application)) { - actionDiagnosticApplication(diagnosticArgs); - } else if (SliderUtils.isSet(diagnosticArgs.slider)) { - actionDiagnosticSlider(diagnosticArgs); - } else if (diagnosticArgs.yarn) { - actionDiagnosticYarn(diagnosticArgs); - } else if (diagnosticArgs.credentials) { - actionDiagnosticCredentials(); - } else if (SliderUtils.isSet(diagnosticArgs.all)) { - actionDiagnosticAll(diagnosticArgs); - } else if (SliderUtils.isSet(diagnosticArgs.level)) { - actionDiagnosticIntelligent(diagnosticArgs); - } else { - // it's an unknown command - log.info(ActionDiagnosticArgs.USAGE); - return EXIT_USAGE; - } - } catch (Exception e) { - log.error(e.toString()); - return EXIT_FALSE; - } - return EXIT_SUCCESS; - } - - private void actionDiagnosticIntelligent(ActionDiagnosticArgs diagnosticArgs) - throws YarnException, IOException, URISyntaxException { - // not using member variable clustername because we want to place - // application name after --application option and member variable - // cluster name has to be put behind action - String clusterName = diagnosticArgs.level; - - try { - SliderUtils.validateClientConfigFile(); - log.info("Slider-client.xml is accessible"); - } catch (IOException e) { - // we are catching exceptions here because those are indication of - // validation result, and we need to print them here - log.error("validation of slider-client.xml fails because: " - + e.toString(), e); - return; - } - SliderClusterOperations clusterOperations = createClusterOperations(clusterName); - // cluster not found exceptions will be thrown upstream - ClusterDescription clusterDescription = clusterOperations - .getClusterDescription(); - log.info("Slider AppMaster is accessible"); - - if (clusterDescription.state == ClusterDescription.STATE_LIVE) { - AggregateConf instanceDefinition = clusterOperations - .getInstanceDefinition(); - String imagePath = instanceDefinition.getInternalOperations().get( - InternalKeys.INTERNAL_APPLICATION_IMAGE_PATH); - //if null, that means slider uploaded the agent tarball for the user - //and we need to use where slider has put - if(imagePath == null){ - ApplicationReport appReport = findInstance(clusterName); - Path path1 = sliderFileSystem.getTempPathForCluster(clusterName); - Path subPath = new Path(path1, appReport.getApplicationId().toString() + "/am"); - imagePath = subPath.toString(); - } - try { - SliderUtils.validateHDFSFile(sliderFileSystem, imagePath); - log.info("Slider agent package is properly installed"); - } catch (FileNotFoundException e) { - log.error("can not find agent package: {}", e); - return; - } catch (IOException e) { - log.error("can not open agent package: {}", e, e); - return; - } - String pkgTarballPath = instanceDefinition.getAppConfOperations() - .getGlobalOptions().getMandatoryOption(AgentKeys.APP_DEF); - try { - SliderUtils.validateHDFSFile(sliderFileSystem, pkgTarballPath); - log.info("Application package is properly installed"); + try { + if (diagnosticArgs.client) { + actionDiagnosticClient(diagnosticArgs); + } else if (SliderUtils.isSet(diagnosticArgs.application)) { + actionDiagnosticApplication(diagnosticArgs); + } else if (SliderUtils.isSet(diagnosticArgs.slider)) { + actionDiagnosticSlider(diagnosticArgs); + } else if (diagnosticArgs.yarn) { + actionDiagnosticYarn(diagnosticArgs); + } else if (diagnosticArgs.credentials) { + actionDiagnosticCredentials(); + } else if (SliderUtils.isSet(diagnosticArgs.all)) { + actionDiagnosticAll(diagnosticArgs); + } else if (SliderUtils.isSet(diagnosticArgs.level)) { + actionDiagnosticIntelligent(diagnosticArgs); + } else { + // it's an unknown option + log.info(CommonArgs.usage(serviceArgs, ACTION_DIAGNOSTIC)); + return EXIT_USAGE; + } + } catch (Exception e) { + log.error(e.toString()); + return EXIT_FALSE; + } + return EXIT_SUCCESS; + } + + private void actionDiagnosticIntelligent(ActionDiagnosticArgs diagnosticArgs) + throws YarnException, IOException, URISyntaxException { + // not using member variable clustername because we want to place + // application name after --application option and member variable + // cluster name has to be put behind action + String clusterName = diagnosticArgs.level; + + try { + SliderUtils.validateClientConfigFile(); + log.info("Slider-client.xml is accessible"); + } catch (IOException e) { + // we are catching exceptions here because those are indication of + // validation result, and we need to print them here + log.error( + "validation of slider-client.xml fails because: " + e.toString(), e); + return; + } + SliderClusterOperations clusterOperations = createClusterOperations(clusterName); + // cluster not found exceptions will be thrown upstream + ClusterDescription clusterDescription = clusterOperations + .getClusterDescription(); + log.info("Slider AppMaster is accessible"); + + if (clusterDescription.state == ClusterDescription.STATE_LIVE) { + AggregateConf instanceDefinition = clusterOperations + .getInstanceDefinition(); + String imagePath = instanceDefinition.getInternalOperations().get( + InternalKeys.INTERNAL_APPLICATION_IMAGE_PATH); + // if null, that means slider uploaded the agent tarball for the user + // and we need to use where slider has put + if (imagePath == null) { + ApplicationReport appReport = findInstance(clusterName); + Path path1 = sliderFileSystem.getTempPathForCluster(clusterName); + Path subPath = new Path(path1, appReport.getApplicationId().toString() + + "/am"); + imagePath = subPath.toString(); + } + try { + SliderUtils.validateHDFSFile(sliderFileSystem, imagePath); + log.info("Slider agent package is properly installed"); + } catch (FileNotFoundException e) { + log.error("can not find agent package: {}", e); + return; + } catch (IOException e) { + log.error("can not open agent package: {}", e, e); + return; + } + String pkgTarballPath = instanceDefinition.getAppConfOperations() + .getGlobalOptions().getMandatoryOption(AgentKeys.APP_DEF); + try { + SliderUtils.validateHDFSFile(sliderFileSystem, pkgTarballPath); + log.info("Application package is properly installed"); } catch (FileNotFoundException e) { log.error("can not find application package: {}", e); return; - } catch (IOException e) { - log.error("can not open application package: {} ", e); - return; - } - } - } - - private void actionDiagnosticAll(ActionDiagnosticArgs diagnosticArgs) - throws IOException, YarnException { - //assign application name from param to each sub diagnostic function - diagnosticArgs.application = diagnosticArgs.all; - diagnosticArgs.slider = diagnosticArgs.all; - actionDiagnosticClient(diagnosticArgs); - actionDiagnosticApplication(diagnosticArgs); - actionDiagnosticSlider(diagnosticArgs); - actionDiagnosticYarn(diagnosticArgs); - actionDiagnosticCredentials(); - } - - private void actionDiagnosticCredentials() throws BadConfigException, IOException - { - if (SliderUtils.isHadoopClusterSecure(SliderUtils - .loadClientConfigurationResource())) { - String credentialCacheFileDescription = null; - try { - credentialCacheFileDescription = SliderUtils - .checkCredentialCacheFile(); - } catch (BadConfigException e) { - log.error("The credential config is not valid: " + e.toString()); - throw e; - } catch (IOException e) { - log.error("Unable to read the credential file: " + e.toString()); - throw e; - } - log.info("Credential cache file for the current user: " - + credentialCacheFileDescription); - } else { - log.info("the cluster is not in secure mode"); - } - } - - private void actionDiagnosticYarn(ActionDiagnosticArgs diagnosticArgs) throws IOException, YarnException { - JSONObject converter = null; - log.info("the node in the YARN cluster has below state: "); - List<NodeReport> yarnClusterInfo; - try { - yarnClusterInfo = yarnClient.getNodeReports(NodeState.RUNNING); - } catch (YarnException e1) { - log.error("Exception happened when fetching node report from the YARN cluster: " + e1.toString()); - throw e1; - } catch (IOException e1) { - log.error("Network problem happened when fetching node report YARN cluster: " + e1.toString()); - throw e1; - } - for(NodeReport nodeReport : yarnClusterInfo){ - log.info(nodeReport.toString()); - } - - if (diagnosticArgs.verbose) { - Writer configWriter = new StringWriter(); - try { - Configuration.dumpConfiguration(yarnClient.getConfig(), configWriter); - } catch (IOException e1) { - log.error("Network problem happened when retrieving YARN config from YARN: " + e1.toString()); - throw e1; - } - try { - converter = new JSONObject(configWriter.toString()); - log.info("the configuration of the YARN cluster is: " - + converter.toString(2)); - - } catch (JSONException e) { - log.error("JSONException happened during parsing response from YARN: " + e.toString()); - } - } - } - - private void actionDiagnosticSlider(ActionDiagnosticArgs diagnosticArgs) throws YarnException, IOException - { - // not using member variable clustername because we want to place - // application name after --application option and member variable - // cluster name has to be put behind action - String clusterName = diagnosticArgs.slider; - SliderClusterOperations clusterOperations; - AggregateConf instanceDefinition = null; - try { - clusterOperations = createClusterOperations(clusterName); - instanceDefinition = clusterOperations - .getInstanceDefinition(); - } catch (YarnException e) { - log.error("Exception happened when retrieving instance definition from YARN: " + e.toString()); - throw e; - } catch (IOException e) { - log.error("Network problem happened when retrieving instance definition from YARN: " + e.toString()); - throw e; - } - String imagePath = instanceDefinition.getInternalOperations().get( - InternalKeys.INTERNAL_APPLICATION_IMAGE_PATH); - //if null, it will be uploaded by Slider and thus at slider's path - if(imagePath == null){ - ApplicationReport appReport = findInstance(clusterName); - Path path1 = sliderFileSystem.getTempPathForCluster(clusterName); - Path subPath = new Path(path1, appReport.getApplicationId().toString() + "/am"); - imagePath = subPath.toString(); - } - log.info("The path of slider agent tarball on HDFS is: " + imagePath); - } - - private void actionDiagnosticApplication(ActionDiagnosticArgs diagnosticArgs) throws YarnException, IOException - { - // not using member variable clustername because we want to place - // application name after --application option and member variable - // cluster name has to be put behind action - String clusterName = diagnosticArgs.application; - SliderClusterOperations clusterOperations; - AggregateConf instanceDefinition = null; - try { - clusterOperations = createClusterOperations(clusterName); - instanceDefinition = clusterOperations - .getInstanceDefinition(); - } catch (YarnException e) { - log.error("Exception happened when retrieving instance definition from YARN: " + e.toString()); - throw e; - } catch (IOException e) { - log.error("Network problem happened when retrieving instance definition from YARN: " + e.toString()); - throw e; - } - String clusterDir = instanceDefinition.getAppConfOperations() - .getGlobalOptions().get(AgentKeys.APP_ROOT); - String pkgTarball = instanceDefinition.getAppConfOperations() - .getGlobalOptions().get(AgentKeys.APP_DEF); - String runAsUser = instanceDefinition.getAppConfOperations() - .getGlobalOptions().get(AgentKeys.RUNAS_USER); - - log.info("The location of the cluster instance directory in HDFS is: " - + clusterDir); - log.info("The name of the application package tarball on HDFS is: " - + pkgTarball); - log.info("The runas user of the application in the cluster is: " - + runAsUser); - - if (diagnosticArgs.verbose) { - log.info("App config of the application: " - + instanceDefinition.getAppConf().toJson()); - log.info("Resource config of the application: " - + instanceDefinition.getResources().toJson()); - } - } + } catch (IOException e) { + log.error("can not open application package: {} ", e); + return; + } + } + } + + private void actionDiagnosticAll(ActionDiagnosticArgs diagnosticArgs) + throws IOException, YarnException { + // assign application name from param to each sub diagnostic function + diagnosticArgs.application = diagnosticArgs.all; + diagnosticArgs.slider = diagnosticArgs.all; + actionDiagnosticClient(diagnosticArgs); + actionDiagnosticApplication(diagnosticArgs); + actionDiagnosticSlider(diagnosticArgs); + actionDiagnosticYarn(diagnosticArgs); + actionDiagnosticCredentials(); + } + + private void actionDiagnosticCredentials() throws BadConfigException, + IOException { + if (SliderUtils.isHadoopClusterSecure(SliderUtils + .loadClientConfigurationResource())) { + String credentialCacheFileDescription = null; + try { + credentialCacheFileDescription = SliderUtils.checkCredentialCacheFile(); + } catch (BadConfigException e) { + log.error("The credential config is not valid: " + e.toString()); + throw e; + } catch (IOException e) { + log.error("Unable to read the credential file: " + e.toString()); + throw e; + } + log.info("Credential cache file for the current user: " + + credentialCacheFileDescription); + } else { + log.info("the cluster is not in secure mode"); + } + } + + private void actionDiagnosticYarn(ActionDiagnosticArgs diagnosticArgs) + throws IOException, YarnException { + JSONObject converter = null; + log.info("the node in the YARN cluster has below state: "); + List<NodeReport> yarnClusterInfo; + try { + yarnClusterInfo = yarnClient.getNodeReports(NodeState.RUNNING); + } catch (YarnException e1) { + log.error("Exception happened when fetching node report from the YARN cluster: " + + e1.toString()); + throw e1; + } catch (IOException e1) { + log.error("Network problem happened when fetching node report YARN cluster: " + + e1.toString()); + throw e1; + } + for (NodeReport nodeReport : yarnClusterInfo) { + log.info(nodeReport.toString()); + } + + if (diagnosticArgs.verbose) { + Writer configWriter = new StringWriter(); + try { + Configuration.dumpConfiguration(yarnClient.getConfig(), configWriter); + } catch (IOException e1) { + log.error("Network problem happened when retrieving YARN config from YARN: " + + e1.toString()); + throw e1; + } + try { + converter = new JSONObject(configWriter.toString()); + log.info("the configuration of the YARN cluster is: " + + converter.toString(2)); + + } catch (JSONException e) { + log.error("JSONException happened during parsing response from YARN: " + + e.toString()); + } + } + } + + private void actionDiagnosticSlider(ActionDiagnosticArgs diagnosticArgs) + throws YarnException, IOException { + // not using member variable clustername because we want to place + // application name after --application option and member variable + // cluster name has to be put behind action + String clusterName = diagnosticArgs.slider; + SliderClusterOperations clusterOperations; + AggregateConf instanceDefinition = null; + try { + clusterOperations = createClusterOperations(clusterName); + instanceDefinition = clusterOperations.getInstanceDefinition(); + } catch (YarnException e) { + log.error("Exception happened when retrieving instance definition from YARN: " + + e.toString()); + throw e; + } catch (IOException e) { + log.error("Network problem happened when retrieving instance definition from YARN: " + + e.toString()); + throw e; + } + String imagePath = instanceDefinition.getInternalOperations().get( + InternalKeys.INTERNAL_APPLICATION_IMAGE_PATH); + // if null, it will be uploaded by Slider and thus at slider's path + if (imagePath == null) { + ApplicationReport appReport = findInstance(clusterName); + Path path1 = sliderFileSystem.getTempPathForCluster(clusterName); + Path subPath = new Path(path1, appReport.getApplicationId().toString() + + "/am"); + imagePath = subPath.toString(); + } + log.info("The path of slider agent tarball on HDFS is: " + imagePath); + } + + private void actionDiagnosticApplication(ActionDiagnosticArgs diagnosticArgs) + throws YarnException, IOException { + // not using member variable clustername because we want to place + // application name after --application option and member variable + // cluster name has to be put behind action + String clusterName = diagnosticArgs.application; + SliderClusterOperations clusterOperations; + AggregateConf instanceDefinition = null; + try { + clusterOperations = createClusterOperations(clusterName); + instanceDefinition = clusterOperations.getInstanceDefinition(); + } catch (YarnException e) { + log.error("Exception happened when retrieving instance definition from YARN: " + + e.toString()); + throw e; + } catch (IOException e) { + log.error("Network problem happened when retrieving instance definition from YARN: " + + e.toString()); + throw e; + } + String clusterDir = instanceDefinition.getAppConfOperations() + .getGlobalOptions().get(AgentKeys.APP_ROOT); + String pkgTarball = instanceDefinition.getAppConfOperations() + .getGlobalOptions().get(AgentKeys.APP_DEF); + String runAsUser = instanceDefinition.getAppConfOperations() + .getGlobalOptions().get(AgentKeys.RUNAS_USER); + + log.info("The location of the cluster instance directory in HDFS is: " + + clusterDir); + log.info("The name of the application package tarball on HDFS is: " + + pkgTarball); + log.info("The runas user of the application in the cluster is: " + + runAsUser); + + if (diagnosticArgs.verbose) { + log.info("App config of the application: " + + instanceDefinition.getAppConf().toJson()); + log.info("Resource config of the application: " + + instanceDefinition.getResources().toJson()); + } + } private void actionDiagnosticClient(ActionDiagnosticArgs diagnosticArgs) throws SliderException, IOException { @@ -2656,17 +2669,15 @@ public class SliderClient extends AbstractSliderLaunchedService implements RunSe // security info Configuration config = getConfig(); - if (SliderUtils.isHadoopClusterSecure(config)) { + if (SliderUtils.isHadoopClusterSecure(config)) { println("Hadoop Cluster is secure"); println("Login user is %s", UserGroupInformation.getLoginUser()); println("Current user is %s", UserGroupInformation.getCurrentUser()); - } else { println("Hadoop Cluster is insecure"); } - // verbose? if (diagnosticArgs.verbose) { // do the environment @@ -2674,19 +2685,15 @@ public class SliderClient extends AbstractSliderLaunchedService implements RunSe Set<String> envList = ConfigHelper.sortedConfigKeys(env.entrySet()); StringBuilder builder = new StringBuilder("Environment variables:\n"); for (String key : envList) { - builder.append(key) - .append("=") - .append(env.get(key)) - .append("\n"); + builder.append(key).append("=").append(env.get(key)).append("\n"); } println(builder.toString()); // then the config - println("Slider client configuration:\n" + - ConfigHelper.dumpConfigToString(config)); + println("Slider client configuration:\n" + + ConfigHelper.dumpConfigToString(config)); } - SliderUtils.validateSliderClientEnvironment(log); } catch (SliderException e) { log.error(e.toString()); @@ -2695,9 +2702,8 @@ public class SliderClient extends AbstractSliderLaunchedService implements RunSe log.error(e.toString()); throw e; } - - } + } /** * Log a service record instance http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/f6e2972a/slider-core/src/main/java/org/apache/slider/common/params/ActionDiagnosticArgs.java ---------------------------------------------------------------------- diff --git a/slider-core/src/main/java/org/apache/slider/common/params/ActionDiagnosticArgs.java b/slider-core/src/main/java/org/apache/slider/common/params/ActionDiagnosticArgs.java index 33abb30..0f98ce0 100644 --- a/slider-core/src/main/java/org/apache/slider/common/params/ActionDiagnosticArgs.java +++ b/slider-core/src/main/java/org/apache/slider/common/params/ActionDiagnosticArgs.java @@ -7,18 +7,7 @@ import com.beust.jcommander.Parameters; commandDescription = SliderActions.DESCRIBE_ACTION_DIAGNOSTIC) public class ActionDiagnosticArgs extends AbstractActionArgs { - public static final String USAGE = - "Usage: " + SliderActions.ACTION_DIAGNOSTIC - + " " - + Arguments.ARG_CLIENT + " | " - + Arguments.ARG_SLIDER + " <appname> " + "| " - + Arguments.ARG_APPLICATION + " <appname> " + "| " - + Arguments.ARG_YARN + " | " - + Arguments.ARG_CREDENTIALS + " | " - + Arguments.ARG_ALL + " <appname> " + "| " - + Arguments.ARG_LEVEL + " <appname> " - + " [" + Arguments.ARG_VERBOSE + "] "; - + @Override public String getActionName() { return SliderActions.ACTION_DIAGNOSTIC; http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/f6e2972a/slider-core/src/main/java/org/apache/slider/common/params/ActionHelpArgs.java ---------------------------------------------------------------------- diff --git a/slider-core/src/main/java/org/apache/slider/common/params/ActionHelpArgs.java b/slider-core/src/main/java/org/apache/slider/common/params/ActionHelpArgs.java index f59396a..62773c4 100644 --- a/slider-core/src/main/java/org/apache/slider/common/params/ActionHelpArgs.java +++ b/slider-core/src/main/java/org/apache/slider/common/params/ActionHelpArgs.java @@ -23,7 +23,7 @@ import com.beust.jcommander.Parameters; /** * The Help command */ -@Parameters(commandNames = {SliderActions.ACTION_HELP, SliderActions.ACTION_USAGE}, +@Parameters(commandNames = {SliderActions.ACTION_HELP}, commandDescription = SliderActions.DESCRIBE_ACTION_HELP) public class ActionHelpArgs extends AbstractActionArgs { @Override http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/f6e2972a/slider-core/src/main/java/org/apache/slider/common/params/ActionRegistryArgs.java ---------------------------------------------------------------------- diff --git a/slider-core/src/main/java/org/apache/slider/common/params/ActionRegistryArgs.java b/slider-core/src/main/java/org/apache/slider/common/params/ActionRegistryArgs.java index 1e4aba5..36ba341 100644 --- a/slider-core/src/main/java/org/apache/slider/common/params/ActionRegistryArgs.java +++ b/slider-core/src/main/java/org/apache/slider/common/params/ActionRegistryArgs.java @@ -152,13 +152,14 @@ public class ActionRegistryArgs extends AbstractActionArgs { if (set > 1) { throw new UsageException(USAGE); } + if (out != null && (lists > 0 || set == 0)) { throw new UsageException("output path" - + " is only supported on 'get' operations: " + USAGE); + + " is only supported on 'get' operations: "); } if (!list && !is(name)) { throw new UsageException("Argument " + ARG_NAME - +" missing: " + USAGE); + +" missing: "); } } http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/f6e2972a/slider-core/src/main/java/org/apache/slider/common/params/ClientArgs.java ---------------------------------------------------------------------- diff --git a/slider-core/src/main/java/org/apache/slider/common/params/ClientArgs.java b/slider-core/src/main/java/org/apache/slider/common/params/ClientArgs.java index b0a4950..cf8cc2f 100644 --- a/slider-core/src/main/java/org/apache/slider/common/params/ClientArgs.java +++ b/slider-core/src/main/java/org/apache/slider/common/params/ClientArgs.java @@ -21,6 +21,7 @@ package org.apache.slider.common.params; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.yarn.conf.YarnConfiguration; import org.apache.slider.common.SliderXmlConfKeys; +import org.apache.slider.common.tools.SliderUtils; import org.apache.slider.core.exceptions.BadCommandArgumentsException; import org.apache.slider.core.exceptions.ErrorStrings; import org.apache.slider.core.exceptions.SliderException; @@ -226,8 +227,7 @@ public class ClientArgs extends CommonArgs { } else if (SliderActions.ACTION_FLEX.equals(action)) { bindCoreAction(actionFlexArgs); - } else if (SliderActions.ACTION_HELP.equals(action) || - SliderActions.ACTION_USAGE.equals(action)) { + } else if (SliderActions.ACTION_HELP.equals(action)) { bindCoreAction(actionHelpArgs); } else if (SliderActions.ACTION_INSTALL_PACKAGE.equals(action)) { @@ -257,8 +257,8 @@ public class ClientArgs extends CommonArgs { } else if (SliderActions.ACTION_VERSION.equals(action)) { bindCoreAction(actionVersionArgs); - } else if (action == null || action.isEmpty()) { - throw new BadCommandArgumentsException(ErrorStrings.ERROR_NO_ACTION); + } else if (SliderUtils.isUnset(action)) { + bindCoreAction(actionHelpArgs); } else { throw new BadCommandArgumentsException(ErrorStrings.ERROR_UNKNOWN_ACTION http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/f6e2972a/slider-core/src/main/java/org/apache/slider/common/params/CommonArgs.java ---------------------------------------------------------------------- diff --git a/slider-core/src/main/java/org/apache/slider/common/params/CommonArgs.java b/slider-core/src/main/java/org/apache/slider/common/params/CommonArgs.java index f4c974b..5113617 100644 --- a/slider-core/src/main/java/org/apache/slider/common/params/CommonArgs.java +++ b/slider-core/src/main/java/org/apache/slider/common/params/CommonArgs.java @@ -21,6 +21,7 @@ package org.apache.slider.common.params; import com.beust.jcommander.JCommander; import com.beust.jcommander.Parameter; import com.beust.jcommander.ParameterException; + import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.Path; import org.apache.slider.common.tools.SliderUtils; @@ -49,6 +50,9 @@ public abstract class CommonArgs extends ArgOps implements SliderActions, protected static final Logger log = LoggerFactory.getLogger(CommonArgs.class); + private static final int DIFF_BETWEEN_DESCIPTION_AND_COMMAND_NAME = 20; + + @Parameter(names = ARG_HELP, help = true) public boolean help; @@ -97,14 +101,45 @@ public abstract class CommonArgs extends ArgOps implements SliderActions, commander = new JCommander(this); } - public String usage() { - StringBuilder builder = new StringBuilder("\n"); - commander.usage(builder, " "); - builder.append("\nactions: "); - return builder.toString(); + return usage(this, null); + } + + public static String usage(CommonArgs serviceArgs, String commandOfInterest) { + String result = null; + StringBuilder helperMessage = new StringBuilder(); + if (commandOfInterest == null) { + // JCommander.usage is too verbose for a command with many options like + // slider no short version of that is found Instead, we compose our msg by + helperMessage.append("\n"); + helperMessage.append("Usage: slider COMMAND [options]\n"); + helperMessage.append("where COMMAND is one of\n"); + for (String jcommand : serviceArgs.commander.getCommands().keySet()) { + helperMessage.append(String.format("\t%-" + + DIFF_BETWEEN_DESCIPTION_AND_COMMAND_NAME + "s-%s", jcommand, + serviceArgs.commander.getCommandDescription(jcommand) + "\n")); + } + helperMessage + .append("Most commands print help when invoked without parameters"); + result = helperMessage.toString(); + } else { + // Jcommander framework doesn't provide a working API to fetch all options + // we have to compose options' helper message per action our own + serviceArgs.commander.usage(commandOfInterest, helperMessage); + // eliminate all linebreaks/tabs as there are too many + result = helperMessage.toString().replaceAll("\n|\t|\\s{3,}", " "); + // insert linebreak and indents + result = result.replaceAll("(--|-D|-S)", "\n\t$1"); + // put options and their abbreviations on the same line + result = result.replaceAll(",\\s*\n\t--", ", --"); + result = result.replaceAll("Usage:", "\nUsage:"); + } + return result; } + public static String usage(CommonArgs serviceArgs) { + return usage(serviceArgs, null); + } /** * Parse routine -includes registering the action-specific argument classes @@ -196,12 +231,23 @@ public abstract class CommonArgs extends ArgOps implements SliderActions, */ public void validate() throws BadCommandArgumentsException, UsageException { if (coreAction == null) { - throw new UsageException(ErrorStrings.ERROR_NO_ACTION - + usage()); + throw new UsageException(ErrorStrings.ERROR_NO_ACTION + usage()); } log.debug("action={}", getAction()); - //let the action validate itself - coreAction.validate(); + // let the action validate itself + try { + coreAction.validate(); + } catch (BadCommandArgumentsException e) { + StringBuilder badArgMsgBuilder = new StringBuilder(); + badArgMsgBuilder.append(e.toString() + "\n"); + badArgMsgBuilder.append(usage(this, coreAction.getActionName())); + throw new BadCommandArgumentsException(badArgMsgBuilder.toString()); + } catch (UsageException e) { + StringBuilder badArgMsgBuilder = new StringBuilder(); + badArgMsgBuilder.append(e.toString() + "\n"); + badArgMsgBuilder.append(usage(this, coreAction.getActionName())); + throw new UsageException(badArgMsgBuilder.toString()); + } } /** http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/f6e2972a/slider-core/src/main/java/org/apache/slider/common/params/SliderActions.java ---------------------------------------------------------------------- diff --git a/slider-core/src/main/java/org/apache/slider/common/params/SliderActions.java b/slider-core/src/main/java/org/apache/slider/common/params/SliderActions.java index 7c68d16..ae575f2 100644 --- a/slider-core/src/main/java/org/apache/slider/common/params/SliderActions.java +++ b/slider-core/src/main/java/org/apache/slider/common/params/SliderActions.java @@ -42,7 +42,6 @@ public interface SliderActions { String ACTION_RESOLVE = "resolve"; String ACTION_STATUS = "status"; String ACTION_THAW = "start"; - String ACTION_USAGE = "usage"; String ACTION_VERSION = "version"; String ACTION_DIAGNOSTIC = "diagnostic"; String ACTION_INSTALL_PACKAGE = "install-package"; http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/f6e2972a/slider-core/src/test/groovy/org/apache/slider/client/TestClientBadArgs.groovy ---------------------------------------------------------------------- diff --git a/slider-core/src/test/groovy/org/apache/slider/client/TestClientBadArgs.groovy b/slider-core/src/test/groovy/org/apache/slider/client/TestClientBadArgs.groovy index 7d596d6..3f7c50f 100644 --- a/slider-core/src/test/groovy/org/apache/slider/client/TestClientBadArgs.groovy +++ b/slider-core/src/test/groovy/org/apache/slider/client/TestClientBadArgs.groovy @@ -41,7 +41,7 @@ class TestClientBadArgs extends ServiceLauncherBaseTest { public void testNoAction() throws Throwable { launchExpectingException(SliderClient, new Configuration(), - ErrorStrings.ERROR_NO_ACTION, + "Usage: slider COMMAND", []) } @@ -53,6 +53,14 @@ class TestClientBadArgs extends ServiceLauncherBaseTest { "not-a-known-action", ["not-a-known-action"]) } + + @Test + public void testActionWithoutOptions() throws Throwable { + launchExpectingException(SliderClient, + new Configuration(), + "Usage: build [options] Options:", + [SliderActions.ACTION_BUILD]) + } @Test public void testActionWithoutEnoughArgs() throws Throwable { @@ -84,7 +92,7 @@ class TestClientBadArgs extends ServiceLauncherBaseTest { public void testRegistryUsage() throws Throwable { def exception = launchExpectingException(SliderClient, new Configuration(), - ActionRegistryArgs.USAGE, + "org.apache.slider.core.exceptions.UsageException: Argument --name missing", [SliderActions.ACTION_REGISTRY]) assert exception instanceof UsageException log.info(exception.toString()) http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/f6e2972a/slider-core/src/test/groovy/org/apache/slider/client/TestClientBasicArgs.groovy ---------------------------------------------------------------------- diff --git a/slider-core/src/test/groovy/org/apache/slider/client/TestClientBasicArgs.groovy b/slider-core/src/test/groovy/org/apache/slider/client/TestClientBasicArgs.groovy index 99c2c31..d1e86a1 100644 --- a/slider-core/src/test/groovy/org/apache/slider/client/TestClientBasicArgs.groovy +++ b/slider-core/src/test/groovy/org/apache/slider/client/TestClientBasicArgs.groovy @@ -49,14 +49,10 @@ class TestClientBasicArgs extends ServiceLauncherBaseTest { @Test public void testNoArgs() throws Throwable { - try { - ServiceLauncher launcher = launch(SliderClient, + launchExpectingException(SliderClient, SliderUtils.createConfiguration(), + "Usage: slider COMMAND", []) - assert SliderExitCodes.EXIT_COMMAND_ARGUMENT_ERROR == launcher.serviceExitCode - } catch (BadCommandArgumentsException ignored) { - // expected - } } // removed due to retry policy dicating 15 minutes of retries for the http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/f6e2972a/slider-funtest/src/test/groovy/org/apache/slider/funtest/commands/SimpleCommandsIT.groovy ---------------------------------------------------------------------- diff --git a/slider-funtest/src/test/groovy/org/apache/slider/funtest/commands/SimpleCommandsIT.groovy b/slider-funtest/src/test/groovy/org/apache/slider/funtest/commands/SimpleCommandsIT.groovy index bf742c9..a06a406 100644 --- a/slider-funtest/src/test/groovy/org/apache/slider/funtest/commands/SimpleCommandsIT.groovy +++ b/slider-funtest/src/test/groovy/org/apache/slider/funtest/commands/SimpleCommandsIT.groovy @@ -38,7 +38,7 @@ public class SimpleCommandsIT extends CommandTestBase { @Test public void testUsage() throws Throwable { - SliderShell shell = slider(0, [SliderActions.ACTION_USAGE]) + SliderShell shell = slider(0, [SliderActions.ACTION_HELP]) assertSuccess(shell) }
