hadoop-common-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jia...@apache.org
Subject [51/60] [abbrv] hadoop git commit: YARN-7384. Remove apiserver cmd and merge service cmd into application cmd. Contributed by Billie Rinaldi
Date Mon, 06 Nov 2017 22:11:09 GMT
http://git-wip-us.apache.org/repos/asf/hadoop/blob/ba7ed7b6/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/test/java/org/apache/hadoop/yarn/service/client/TestServiceCLI.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/test/java/org/apache/hadoop/yarn/service/client/TestServiceCLI.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/test/java/org/apache/hadoop/yarn/service/client/TestServiceCLI.java
index f22d487..df4b1df 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/test/java/org/apache/hadoop/yarn/service/client/TestServiceCLI.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-services/hadoop-yarn-services-core/src/test/java/org/apache/hadoop/yarn/service/client/TestServiceCLI.java
@@ -20,88 +20,71 @@ package org.apache.hadoop.yarn.service.client;
 
 import org.apache.commons.io.FileUtils;
 import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.CommonConfigurationKeysPublic;
-import org.apache.hadoop.yarn.api.records.ApplicationReport;
-import org.apache.hadoop.yarn.api.records.YarnApplicationState;
+import org.apache.hadoop.util.ToolRunner;
+import org.apache.hadoop.yarn.client.cli.ApplicationCLI;
 import org.apache.hadoop.yarn.conf.YarnConfiguration;
-import org.apache.hadoop.yarn.service.ClientAMProtocol;
 import org.apache.hadoop.yarn.service.api.records.Component;
-import org.apache.hadoop.yarn.service.client.params.ClientArgs;
+import org.apache.hadoop.yarn.service.api.records.Service;
 import org.apache.hadoop.yarn.service.conf.ExampleAppJson;
 import org.apache.hadoop.yarn.service.utils.ServiceApiUtil;
 import org.apache.hadoop.yarn.service.utils.SliderFileSystem;
-import org.apache.hadoop.yarn.util.Records;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.io.File;
 import java.io.IOException;
+import java.util.Arrays;
 import java.util.List;
 
-import static org.apache.hadoop.yarn.conf.YarnConfiguration.RESOURCEMANAGER_CONNECT_MAX_WAIT_MS;
-import static org.apache.hadoop.yarn.conf.YarnConfiguration.RESOURCEMANAGER_CONNECT_RETRY_INTERVAL_MS;
-import static org.apache.hadoop.yarn.service.client.params.Arguments.ARG_FILE;
 import static org.apache.hadoop.yarn.service.conf.YarnServiceConf.YARN_SERVICE_BASE_PATH;
-import static org.mockito.Mockito.*;
 
 public class TestServiceCLI {
+  private static final Logger LOG = LoggerFactory.getLogger(TestServiceCLI
+      .class);
 
-  protected Configuration conf = new YarnConfiguration();
+  private Configuration conf = new YarnConfiguration();
   private File basedir;
-  private ServiceCLI cli;
   private SliderFileSystem fs;
+  private String basedirProp;
 
-  private void buildApp(String appDef) throws Throwable {
-    String[] args =
-        { "build", ARG_FILE, ExampleAppJson.resourceName(appDef)};
-    ClientArgs clientArgs = new ClientArgs(args);
-    clientArgs.parse();
-    cli.exec(clientArgs);
+  private void runCLI(String[] args) throws Exception {
+    LOG.info("running CLI: yarn {}", Arrays.asList(args));
+    ApplicationCLI cli = new ApplicationCLI();
+    cli.setSysOutPrintStream(System.out);
+    cli.setSysErrPrintStream(System.err);
+    int res = ToolRunner.run(cli, ApplicationCLI.preProcessArgs(args));
+    cli.stop();
+  }
+
+  private void buildApp(String serviceName, String appDef) throws Throwable {
+    String[] args = {"app", "-D", basedirProp, "-save", serviceName,
+        ExampleAppJson.resourceName(appDef)};
+    runCLI(args);
+  }
+
+  private void buildApp(String serviceName, String appDef, String lifetime,
+      String queue) throws Throwable {
+    String[] args = {"app", "-D", basedirProp, "-save", serviceName,
+        ExampleAppJson.resourceName(appDef), "-updateLifetime", lifetime,
+        "-changeQueue", queue};
+    runCLI(args);
   }
 
   @Before
   public void setup() throws Throwable {
     basedir = new File("target", "apps");
+    basedirProp = YARN_SERVICE_BASE_PATH + "=" + basedir.getAbsolutePath();
     conf.set(YARN_SERVICE_BASE_PATH, basedir.getAbsolutePath());
-    conf.setLong(RESOURCEMANAGER_CONNECT_MAX_WAIT_MS, 0);
-    conf.setLong(RESOURCEMANAGER_CONNECT_RETRY_INTERVAL_MS, 1);
-    conf.setInt(
-        CommonConfigurationKeysPublic.IPC_CLIENT_CONNECT_MAX_RETRIES_KEY, 0);
-    conf.setInt(CommonConfigurationKeysPublic.
-        IPC_CLIENT_CONNECT_MAX_RETRIES_ON_SOCKET_TIMEOUTS_KEY, 0);
     fs = new SliderFileSystem(conf);
     if (basedir.exists()) {
       FileUtils.deleteDirectory(basedir);
     } else {
       basedir.mkdirs();
     }
-
-    // create a CLI and skip connection to AM
-    cli = new ServiceCLI() {
-      @Override protected void createServiceClient() {
-        client = new ServiceClient() {
-          @Override
-          protected void serviceInit(Configuration configuration)
-              throws Exception {
-            super.serviceInit(conf);
-            yarnClient = spy(yarnClient);
-            ApplicationReport report = Records.newRecord(ApplicationReport.class);
-            report.setYarnApplicationState(YarnApplicationState.RUNNING);
-            report.setHost("localhost");
-            doReturn(report).when(yarnClient).getApplicationReport(anyObject());
-          }
-          @Override
-          protected ClientAMProtocol createAMProxy(String host, int port)
-              throws IOException {
-            return mock(ClientAMProtocol.class);
-          }
-        };
-        client.init(conf);
-        client.start();
-      }
-    };
   }
 
   @After
@@ -111,41 +94,31 @@ public class TestServiceCLI {
     }
   }
 
-  // Test flex components count are persisted.
   @Test
   public void testFlexComponents() throws Throwable {
+    // currently can only test building apps, since that is the only
+    // operation that doesn't require an RM
+    // TODO: expand CLI test to try other commands
     String serviceName = "app-1";
-    buildApp(ExampleAppJson.APP_JSON);
-    checkCompCount("master",serviceName,  1L);
-
-    // increase by 2
-    String[] flexUpArgs = {"flex", serviceName, "--component", "master" , "+2"};
-    ClientArgs clientArgs = new ClientArgs(flexUpArgs);
-    clientArgs.parse();
-    cli.exec(clientArgs);
-    checkCompCount("master", serviceName, 3L);
-
-    // decrease by 1
-    String[] flexDownArgs = {"flex", serviceName, "--component", "master", "-1"};
-    clientArgs = new ClientArgs(flexDownArgs);
-    clientArgs.parse();
-    cli.exec(clientArgs);
-    checkCompCount("master", serviceName, 2L);
+    buildApp(serviceName, ExampleAppJson.APP_JSON);
+    checkApp(serviceName, "master", 1L, 3600L, null);
 
-    String[] flexAbsoluteArgs = {"flex", serviceName, "--component", "master", "10"};
-    clientArgs = new ClientArgs(flexAbsoluteArgs);
-    clientArgs.parse();
-    cli.exec(clientArgs);
-    checkCompCount("master", serviceName, 10L);
+    serviceName = "app-2";
+    buildApp(serviceName, ExampleAppJson.APP_JSON, "1000", "qname");
+    checkApp(serviceName, "master", 1L, 1000L, "qname");
   }
 
-  private void checkCompCount(String compName, String serviceName, long count)
-      throws IOException {
-    List<Component> components =
-        ServiceApiUtil.getComponents(fs, serviceName);
+  private void checkApp(String serviceName, String compName, long count, Long
+      lifetime, String queue) throws IOException {
+    Service service = ServiceApiUtil.loadService(fs, serviceName);
+    Assert.assertEquals(serviceName, service.getName());
+    Assert.assertEquals(lifetime, service.getLifetime());
+    Assert.assertEquals(queue, service.getQueue());
+    List<Component> components = service.getComponents();
     for (Component component : components) {
       if (component.getName().equals(compName)) {
-        Assert.assertEquals(count, component.getNumberOfContainers().longValue());
+        Assert.assertEquals(count, component.getNumberOfContainers()
+            .longValue());
         return;
       }
     }

http://git-wip-us.apache.org/repos/asf/hadoop/blob/ba7ed7b6/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/api/AppAdminClient.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/api/AppAdminClient.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/api/AppAdminClient.java
new file mode 100644
index 0000000..6310178
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/api/AppAdminClient.java
@@ -0,0 +1,222 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.yarn.client.api;
+
+import org.apache.hadoop.classification.InterfaceAudience.Private;
+import org.apache.hadoop.classification.InterfaceAudience.Public;
+import org.apache.hadoop.classification.InterfaceStability.Unstable;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.service.CompositeService;
+import org.apache.hadoop.util.ReflectionUtils;
+import org.apache.hadoop.yarn.exceptions.YarnException;
+import org.apache.hadoop.yarn.exceptions.YarnRuntimeException;
+
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * Client for managing applications.
+ */
+@Public
+@Unstable
+public abstract class AppAdminClient extends CompositeService {
+  public static final String YARN_APP_ADMIN_CLIENT_PREFIX = "yarn" +
+      ".application.admin.client.class.";
+  public static final String DEFAULT_TYPE = "yarn-service";
+  public static final String DEFAULT_CLASS_NAME = "org.apache.hadoop.yarn" +
+      ".service.client.ServiceClient";
+
+  @Private
+  protected AppAdminClient() {
+    super(AppAdminClient.class.getName());
+  }
+
+  /**
+   * <p>
+   * Create a new instance of AppAdminClient.
+   * </p>
+   *
+   * @param appType application type
+   * @param conf configuration
+   * @return app admin client
+   */
+  @Public
+  @Unstable
+  public static AppAdminClient createAppAdminClient(String appType,
+      Configuration conf) {
+    Map<String, String> clientClassMap =
+        conf.getPropsWithPrefix(YARN_APP_ADMIN_CLIENT_PREFIX);
+    if (!clientClassMap.containsKey(DEFAULT_TYPE)) {
+      clientClassMap.put(DEFAULT_TYPE, DEFAULT_CLASS_NAME);
+    }
+    if (!clientClassMap.containsKey(appType)) {
+      throw new IllegalArgumentException("App admin client class name not " +
+          "specified for type " + appType);
+    }
+    String clientClassName = clientClassMap.get(appType);
+    Class<? extends AppAdminClient> clientClass;
+    try {
+      clientClass = (Class<? extends AppAdminClient>) Class.forName(
+          clientClassName);
+    } catch (ClassNotFoundException e) {
+      throw new YarnRuntimeException("Invalid app admin client class", e);
+    }
+
+    AppAdminClient appAdminClient = ReflectionUtils.newInstance(clientClass,
+        conf);
+    appAdminClient.init(conf);
+    appAdminClient.start();
+    return appAdminClient;
+  }
+
+  /**
+   * <p>
+   * Launch a new YARN application.
+   * </p>
+   *
+   * @param fileName specification of application
+   * @param appName name of the application
+   * @param lifetime lifetime of the application
+   * @param queue queue of the application
+   * @return exit code
+   * @throws IOException IOException
+   * @throws YarnException exception in client or server
+   */
+  @Public
+  @Unstable
+  public abstract int actionLaunch(String fileName, String appName, Long
+      lifetime, String queue) throws IOException, YarnException;
+
+  /**
+   * <p>
+   * Stop a YARN application (attempt to stop gracefully before killing the
+   * application). In the case of a long-running service, the service may be
+   * restarted later.
+   * </p>
+   *
+   * @param appName the name of the application
+   * @return exit code
+   * @throws IOException IOException
+   * @throws YarnException exception in client or server
+   */
+  @Public
+  @Unstable
+  public abstract int actionStop(String appName) throws IOException,
+      YarnException;
+
+  /**
+   * <p>
+   * Start a YARN application from a previously saved specification. In the
+   * case of a long-running service, the service must have been previously
+   * launched/started and then stopped, or previously saved but not started.
+   * </p>
+   *
+   * @param appName the name of the application
+   * @return exit code
+   * @throws IOException IOException
+   * @throws YarnException exception in client or server
+   */
+  @Public
+  @Unstable
+  public abstract int actionStart(String appName) throws IOException,
+      YarnException;
+
+  /**
+   * <p>
+   * Save the specification for a YARN application / long-running service.
+   * The application may be started later.
+   * </p>
+   *
+   * @param fileName specification of application to save
+   * @param appName name of the application
+   * @param lifetime lifetime of the application
+   * @param queue queue of the application
+   * @return exit code
+   * @throws IOException IOException
+   * @throws YarnException exception in client or server
+   */
+  @Public
+  @Unstable
+  public abstract int actionSave(String fileName, String appName, Long
+      lifetime, String queue) throws IOException, YarnException;
+
+  /**
+   * <p>
+   * Remove the specification and all application data for a YARN application.
+   * The application cannot be running.
+   * </p>
+   *
+   * @param appName the name of the application
+   * @return exit code
+   * @throws IOException IOException
+   * @throws YarnException exception in client or server
+   */
+  @Public
+  @Unstable
+  public abstract int actionDestroy(String appName) throws IOException,
+      YarnException;
+
+  /**
+   * <p>
+   * Change the number of running containers for a component of a YARN
+   * application / long-running service.
+   * </p>
+   *
+   * @param appName the name of the application
+   * @param componentCounts map of component name to new component count or
+   *                        amount to change existing component count (e.g.
+   *                        5, +5, -5)
+   * @return exit code
+   * @throws IOException IOException
+   * @throws YarnException exception in client or server
+   */
+  @Public
+  @Unstable
+  public abstract int actionFlex(String appName, Map<String, String>
+      componentCounts) throws IOException, YarnException;
+
+  /**
+   * <p>
+   * Upload AM dependencies to HDFS. This makes future application launches
+   * faster since the dependencies do not have to be uploaded on each launch.
+   * </p>
+   *
+   * @return exit code
+   * @throws IOException IOException
+   * @throws YarnException exception in client or server
+   */
+  @Public
+  @Unstable
+  public abstract int enableFastLaunch() throws IOException,
+      YarnException;
+
+  /**
+   * <p>
+   * Get detailed status string for a YARN application.
+   * </p>
+   *
+   * @param applicationId application id
+   * @return status string
+   * @throws IOException IOException
+   * @throws YarnException exception in client or server
+   */
+  @Public
+  @Unstable
+  public abstract String getStatusString(String applicationId) throws
+      IOException, YarnException;
+}

http://git-wip-us.apache.org/repos/asf/hadoop/blob/ba7ed7b6/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/cli/ApplicationCLI.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/cli/ApplicationCLI.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/cli/ApplicationCLI.java
index 2a9b3bc..fb08fcd 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/cli/ApplicationCLI.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/main/java/org/apache/hadoop/yarn/client/cli/ApplicationCLI.java
@@ -23,12 +23,7 @@ import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
 import java.nio.charset.Charset;
 import java.text.DecimalFormat;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
 
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.GnuParser;
@@ -54,6 +49,7 @@ import org.apache.hadoop.yarn.api.records.ContainerReport;
 import org.apache.hadoop.yarn.api.records.Priority;
 import org.apache.hadoop.yarn.api.records.SignalContainerCommand;
 import org.apache.hadoop.yarn.api.records.YarnApplicationState;
+import org.apache.hadoop.yarn.client.api.AppAdminClient;
 import org.apache.hadoop.yarn.exceptions.ApplicationAttemptNotFoundException;
 import org.apache.hadoop.yarn.exceptions.ApplicationNotFoundException;
 import org.apache.hadoop.yarn.exceptions.ContainerNotFoundException;
@@ -85,6 +81,7 @@ public class ApplicationCLI extends YarnCLI {
     "%30s\t%20s\t%20s\t%20s\t%20s\t%20s\t%35s"
       + System.getProperty("line.separator");
 
+  public static final String APP = "app";
   public static final String APPLICATION = "application";
   public static final String APPLICATION_ATTEMPT = "applicationattempt";
   public static final String CONTAINER = "container";
@@ -93,22 +90,52 @@ public class ApplicationCLI extends YarnCLI {
   public static final String UPDATE_LIFETIME = "updateLifetime";
   public static final String CHANGE_APPLICATION_QUEUE = "changeQueue";
 
+  // app admin options
+  public static final String LAUNCH_CMD = "launch";
+  public static final String STOP_CMD = "stop";
+  public static final String START_CMD = "start";
+  public static final String SAVE_CMD = "save";
+  public static final String DESTROY_CMD = "destroy";
+  public static final String FLEX_CMD = "flex";
+  public static final String COMPONENT = "component";
+  public static final String ENABLE_FAST_LAUNCH = "enableFastLaunch";
+
+  private static String firstArg = null;
+
   private boolean allAppStates;
 
   public static void main(String[] args) throws Exception {
     ApplicationCLI cli = new ApplicationCLI();
     cli.setSysOutPrintStream(System.out);
     cli.setSysErrPrintStream(System.err);
-    int res = ToolRunner.run(cli, args);
+    int res = ToolRunner.run(cli, preProcessArgs(args));
     cli.stop();
     System.exit(res);
   }
 
+  @VisibleForTesting
+  public static String[] preProcessArgs(String[] args) {
+    if (args.length > 0) {
+      // first argument (app|application|applicationattempt|container) must
+      // be stripped off for GenericOptionsParser to work
+      firstArg = args[0];
+      return Arrays.copyOfRange(args, 1, args.length);
+    } else {
+      return args;
+    }
+  }
+
   @Override
   public int run(String[] args) throws Exception {
     Options opts = new Options();
     String title = null;
-    if (args.length > 0 && args[0].equalsIgnoreCase(APPLICATION)) {
+    if (firstArg != null) {
+      title = firstArg;
+    } else if (args.length > 0) {
+      title = args[0];
+    }
+    if (title != null && (title.equalsIgnoreCase(APPLICATION) || title
+        .equalsIgnoreCase(APP))) {
       title = APPLICATION;
       opts.addOption(STATUS_CMD, true,
           "Prints the status of the application.");
@@ -168,8 +195,52 @@ public class ApplicationCLI extends YarnCLI {
       opts.getOption(UPDATE_PRIORITY).setArgName("Priority");
       opts.getOption(UPDATE_LIFETIME).setArgName("Timeout");
       opts.getOption(CHANGE_APPLICATION_QUEUE).setArgName("Queue Name");
-    } else if (args.length > 0 && args[0].equalsIgnoreCase(APPLICATION_ATTEMPT)) {
-      title = APPLICATION_ATTEMPT;
+      opts.addOption(LAUNCH_CMD, true, "Launches application from " +
+          "specification file (saves specification and starts application). " +
+          "Options -updateLifetime and -changeQueue can be specified to alter" +
+          " the values provided in the file. Supports -appTypes option to " +
+          "specify which client implementation to use.");
+      opts.addOption(STOP_CMD, true, "Stops application gracefully (may be " +
+          "started again later). If name is provided, appType must be " +
+          "provided unless it is the default yarn-service. If ID is provided," +
+          " the appType will be looked up. Supports -appTypes option to " +
+          "specify which client implementation to use.");
+      opts.addOption(START_CMD, true, "Starts a previously saved " +
+          "application. Supports -appTypes option to specify which client " +
+          "implementation to use.");
+      opts.addOption(SAVE_CMD, true, "Saves specification file for " +
+          "an application. Options -updateLifetime and -changeQueue can be " +
+          "specified to alter the values provided in the file. Supports " +
+          "-appTypes option to specify which client implementation to use.");
+      opts.addOption(DESTROY_CMD, true, "Destroys a saved application " +
+          "specification and removes all application data permanently. " +
+          "Supports -appTypes option to specify which client implementation " +
+          "to use.");
+      opts.addOption(FLEX_CMD, true, "Changes number of " +
+          "running containers for a component of an application / " +
+          "long-running service. Requires -component option. If name is " +
+          "provided, appType must be provided unless it is the default " +
+          "yarn-service. If ID is provided, the appType will be looked up. " +
+          "Supports -appTypes option to specify which client implementation " +
+          "to use.");
+      opts.addOption(COMPONENT, true, "Works with -flex option to change " +
+          "the number of components/containers running for an application / " +
+          "long-running service. Supports absolute or relative changes, such " +
+          "as +1, 2, or -3.");
+      opts.addOption(ENABLE_FAST_LAUNCH, false, "Uploads AM dependencies " +
+          "to HDFS to make future launches faster.  Supports -appTypes option" +
+          " to specify which client implementation to use.");
+      opts.getOption(LAUNCH_CMD).setArgName("Application Name> <File Name");
+      opts.getOption(LAUNCH_CMD).setArgs(2);
+      opts.getOption(START_CMD).setArgName("Application Name");
+      opts.getOption(STOP_CMD).setArgName("Application Name or ID");
+      opts.getOption(SAVE_CMD).setArgName("Application Name> <File Name");
+      opts.getOption(SAVE_CMD).setArgs(2);
+      opts.getOption(DESTROY_CMD).setArgName("Application Name");
+      opts.getOption(FLEX_CMD).setArgName("Application Name or ID");
+      opts.getOption(COMPONENT).setArgName("Component Name> <Count");
+      opts.getOption(COMPONENT).setArgs(2);
+    } else if (title != null && title.equalsIgnoreCase(APPLICATION_ATTEMPT)) {
       opts.addOption(STATUS_CMD, true,
           "Prints the status of the application attempt.");
       opts.addOption(LIST_CMD, true,
@@ -179,8 +250,7 @@ public class ApplicationCLI extends YarnCLI {
       opts.getOption(STATUS_CMD).setArgName("Application Attempt ID");
       opts.getOption(LIST_CMD).setArgName("Application ID");
       opts.getOption(FAIL_CMD).setArgName("Application Attempt ID");
-    } else if (args.length > 0 && args[0].equalsIgnoreCase(CONTAINER)) {
-      title = CONTAINER;
+    } else if (title != null && title.equalsIgnoreCase(CONTAINER)) {
       opts.addOption(STATUS_CMD, true,
           "Prints the status of the container.");
       opts.addOption(LIST_CMD, true,
@@ -205,23 +275,53 @@ public class ApplicationCLI extends YarnCLI {
       printUsage(title, opts);
       return exitCode;
     }
+    String[] unparsedArgs = cliParser.getArgs();
+    if (firstArg == null) {
+      if (unparsedArgs.length != 1) {
+        printUsage(title, opts);
+        return exitCode;
+      }
+    } else {
+      if (unparsedArgs.length != 0) {
+        printUsage(title, opts);
+        return exitCode;
+      }
+    }
 
     if (cliParser.hasOption(STATUS_CMD)) {
-      if (args.length != 3) {
+      if (hasAnyOtherCLIOptions(cliParser, opts, STATUS_CMD)) {
         printUsage(title, opts);
         return exitCode;
       }
-      if (args[0].equalsIgnoreCase(APPLICATION)) {
-        exitCode = printApplicationReport(cliParser.getOptionValue(STATUS_CMD));
-      } else if (args[0].equalsIgnoreCase(APPLICATION_ATTEMPT)) {
+      if (title.equalsIgnoreCase(APPLICATION) ||
+          title.equalsIgnoreCase(APP)) {
+        ApplicationReport report = printApplicationReport(cliParser
+            .getOptionValue(STATUS_CMD));
+        if (report == null) {
+          exitCode = -1;
+        } else {
+          exitCode = 0;
+          String appType = report.getApplicationType();
+          try {
+            AppAdminClient client = AppAdminClient.createAppAdminClient(appType,
+                getConf());
+            sysout.println("Detailed Application Status :");
+            sysout.println(client.getStatusString(cliParser.getOptionValue(
+                STATUS_CMD)));
+          } catch (IllegalArgumentException e) {
+            // app type does not have app admin client implementation
+          }
+        }
+      } else if (title.equalsIgnoreCase(APPLICATION_ATTEMPT)) {
         exitCode = printApplicationAttemptReport(cliParser
             .getOptionValue(STATUS_CMD));
-      } else if (args[0].equalsIgnoreCase(CONTAINER)) {
+      } else if (title.equalsIgnoreCase(CONTAINER)) {
         exitCode = printContainerReport(cliParser.getOptionValue(STATUS_CMD));
       }
       return exitCode;
     } else if (cliParser.hasOption(LIST_CMD)) {
-      if (args[0].equalsIgnoreCase(APPLICATION)) {
+      if (title.equalsIgnoreCase(APPLICATION) ||
+          title.equalsIgnoreCase(APP)) {
         allAppStates = false;
         Set<String> appTypes = new HashSet<String>();
         if (cliParser.hasOption(APP_TYPE_CMD)) {
@@ -272,21 +372,21 @@ public class ApplicationCLI extends YarnCLI {
           }
         }
         listApplications(appTypes, appStates, appTags);
-      } else if (args[0].equalsIgnoreCase(APPLICATION_ATTEMPT)) {
-        if (args.length != 3) {
+      } else if (title.equalsIgnoreCase(APPLICATION_ATTEMPT)) {
+        if (hasAnyOtherCLIOptions(cliParser, opts, LIST_CMD)) {
           printUsage(title, opts);
           return exitCode;
         }
         listApplicationAttempts(cliParser.getOptionValue(LIST_CMD));
-      } else if (args[0].equalsIgnoreCase(CONTAINER)) {
-        if (args.length != 3) {
+      } else if (title.equalsIgnoreCase(CONTAINER)) {
+        if (hasAnyOtherCLIOptions(cliParser, opts, LIST_CMD)) {
           printUsage(title, opts);
           return exitCode;
         }
         listContainers(cliParser.getOptionValue(LIST_CMD));
       }
     } else if (cliParser.hasOption(KILL_CMD)) {
-      if (args.length < 3 || hasAnyOtherCLIOptions(cliParser, opts, KILL_CMD)) {
+      if (hasAnyOtherCLIOptions(cliParser, opts, KILL_CMD)) {
         printUsage(title, opts);
         return exitCode;
       }
@@ -299,7 +399,7 @@ public class ApplicationCLI extends YarnCLI {
       moveApplicationAcrossQueues(cliParser.getOptionValue(MOVE_TO_QUEUE_CMD),
           cliParser.getOptionValue(QUEUE_CMD));
     } else if (cliParser.hasOption(FAIL_CMD)) {
-      if (!args[0].equalsIgnoreCase(APPLICATION_ATTEMPT)) {
+      if (!title.equalsIgnoreCase(APPLICATION_ATTEMPT)) {
         printUsage(title, opts);
         return exitCode;
       }
@@ -314,6 +414,103 @@ public class ApplicationCLI extends YarnCLI {
       }
       updateApplicationPriority(cliParser.getOptionValue(APP_ID),
           cliParser.getOptionValue(UPDATE_PRIORITY));
+    } else if (cliParser.hasOption(SIGNAL_CMD)) {
+      if (hasAnyOtherCLIOptions(cliParser, opts, SIGNAL_CMD)) {
+        printUsage(title, opts);
+        return exitCode;
+      }
+      final String[] signalArgs = cliParser.getOptionValues(SIGNAL_CMD);
+      final String containerId = signalArgs[0];
+      SignalContainerCommand command =
+          SignalContainerCommand.OUTPUT_THREAD_DUMP;
+      if (signalArgs.length == 2) {
+        command = SignalContainerCommand.valueOf(signalArgs[1]);
+      }
+      signalToContainer(containerId, command);
+    } else if (cliParser.hasOption(LAUNCH_CMD)) {
+      if (hasAnyOtherCLIOptions(cliParser, opts, LAUNCH_CMD, APP_TYPE_CMD,
+          UPDATE_LIFETIME, CHANGE_APPLICATION_QUEUE)) {
+        printUsage(title, opts);
+        return exitCode;
+      }
+      String appType = getSingleAppTypeFromCLI(cliParser);
+      Long lifetime = null;
+      if (cliParser.hasOption(UPDATE_LIFETIME)) {
+        lifetime = Long.parseLong(cliParser.getOptionValue(UPDATE_LIFETIME));
+      }
+      String queue = null;
+      if (cliParser.hasOption(CHANGE_APPLICATION_QUEUE)) {
+        queue = cliParser.getOptionValue(CHANGE_APPLICATION_QUEUE);
+      }
+      String[] nameAndFile = cliParser.getOptionValues(LAUNCH_CMD);
+      return AppAdminClient.createAppAdminClient(appType, getConf())
+          .actionLaunch(nameAndFile[1], nameAndFile[0], lifetime, queue);
+    } else if (cliParser.hasOption(STOP_CMD)) {
+      if (hasAnyOtherCLIOptions(cliParser, opts, STOP_CMD, APP_TYPE_CMD)) {
+        printUsage(title, opts);
+        return exitCode;
+      }
+      String[] appNameAndType = getAppNameAndType(cliParser, STOP_CMD);
+      return AppAdminClient.createAppAdminClient(appNameAndType[1], getConf())
+          .actionStop(appNameAndType[0]);
+    } else if (cliParser.hasOption(START_CMD)) {
+      if (hasAnyOtherCLIOptions(cliParser, opts, START_CMD, APP_TYPE_CMD)) {
+        printUsage(title, opts);
+        return exitCode;
+      }
+      String appType = getSingleAppTypeFromCLI(cliParser);
+      return AppAdminClient.createAppAdminClient(appType, getConf())
+          .actionStart(cliParser.getOptionValue(START_CMD));
+    } else if (cliParser.hasOption(SAVE_CMD)) {
+      if (hasAnyOtherCLIOptions(cliParser, opts, SAVE_CMD, APP_TYPE_CMD,
+          UPDATE_LIFETIME, CHANGE_APPLICATION_QUEUE)) {
+        printUsage(title, opts);
+        return exitCode;
+      }
+      String appType = getSingleAppTypeFromCLI(cliParser);
+      Long lifetime = null;
+      if (cliParser.hasOption(UPDATE_LIFETIME)) {
+        lifetime = Long.parseLong(cliParser.getOptionValue(UPDATE_LIFETIME));
+      }
+      String queue = null;
+      if (cliParser.hasOption(CHANGE_APPLICATION_QUEUE)) {
+        queue = cliParser.getOptionValue(CHANGE_APPLICATION_QUEUE);
+      }
+      String[] nameAndFile = cliParser.getOptionValues(SAVE_CMD);
+      return AppAdminClient.createAppAdminClient(appType, getConf())
+          .actionSave(nameAndFile[1], nameAndFile[0], lifetime, queue);
+    } else if (cliParser.hasOption(DESTROY_CMD)) {
+      if (hasAnyOtherCLIOptions(cliParser, opts, DESTROY_CMD, APP_TYPE_CMD)) {
+        printUsage(title, opts);
+        return exitCode;
+      }
+      String appType = getSingleAppTypeFromCLI(cliParser);
+      return AppAdminClient.createAppAdminClient(appType, getConf())
+          .actionDestroy(cliParser.getOptionValue(DESTROY_CMD));
+    } else if (cliParser.hasOption(FLEX_CMD)) {
+      if (!cliParser.hasOption(COMPONENT) ||
+          hasAnyOtherCLIOptions(cliParser, opts, FLEX_CMD, COMPONENT,
+              APP_TYPE_CMD)) {
+        printUsage(title, opts);
+        return exitCode;
+      }
+      String[] rawCounts = cliParser.getOptionValues(COMPONENT);
+      Map<String, String> counts = new HashMap<>(rawCounts.length/2);
+      for (int i = 0; i < rawCounts.length - 1; i+=2) {
+        counts.put(rawCounts[i], rawCounts[i+1]);
+      }
+      String[] appNameAndType = getAppNameAndType(cliParser, FLEX_CMD);
+      return AppAdminClient.createAppAdminClient(appNameAndType[1], getConf())
+          .actionFlex(appNameAndType[0], counts);
+    } else if (cliParser.hasOption(ENABLE_FAST_LAUNCH)) {
+      String appType = getSingleAppTypeFromCLI(cliParser);
+      if (hasAnyOtherCLIOptions(cliParser, opts, ENABLE_FAST_LAUNCH,
+          APP_TYPE_CMD)) {
+        printUsage(title, opts);
+        return exitCode;
+      }
+      return AppAdminClient.createAppAdminClient(appType, getConf())
+          .enableFastLaunch();
     } else if (cliParser.hasOption(UPDATE_LIFETIME)) {
       if (!cliParser.hasOption(APP_ID)) {
         printUsage(title, opts);
@@ -332,19 +529,6 @@ public class ApplicationCLI extends YarnCLI {
       }
       moveApplicationAcrossQueues(cliParser.getOptionValue(APP_ID),
           cliParser.getOptionValue(CHANGE_APPLICATION_QUEUE));
-    } else if (cliParser.hasOption(SIGNAL_CMD)) {
-      if (args.length < 3 || args.length > 4) {
-        printUsage(title, opts);
-        return exitCode;
-      }
-      final String[] signalArgs = cliParser.getOptionValues(SIGNAL_CMD);
-      final String containerId = signalArgs[0];
-      SignalContainerCommand command =
-          SignalContainerCommand.OUTPUT_THREAD_DUMP;
-      if (signalArgs.length == 2) {
-        command = SignalContainerCommand.valueOf(signalArgs[1]);
-      }
-      signalToContainer(containerId, command);
     } else {
       syserr.println("Invalid Command Usage : ");
       printUsage(title, opts);
@@ -352,6 +536,47 @@ public class ApplicationCLI extends YarnCLI {
     return 0;
   }
 
+  private ApplicationReport getApplicationReport(ApplicationId applicationId)
+      throws IOException, YarnException {
+    ApplicationReport appReport = null;
+    try {
+      appReport = client.getApplicationReport(applicationId);
+    } catch (ApplicationNotFoundException e) {
+      throw new YarnException("Application with id '" + applicationId
+          + "' doesn't exist in RM or Timeline Server.");
+    }
+    return appReport;
+  }
+
+  private String[] getAppNameAndType(CommandLine cliParser, String option)
+      throws IOException, YarnException {
+    String applicationIdOrName = cliParser.getOptionValue(option);
+    try {
+      ApplicationId id = ApplicationId.fromString(applicationIdOrName);
+      ApplicationReport report = getApplicationReport(id);
+      return new String[]{report.getName(), report.getApplicationType()};
+    } catch (IllegalArgumentException e) {
+      // assume CLI option provided the app name
+      // and read appType from command line since id wasn't provided
+      String appType = getSingleAppTypeFromCLI(cliParser);
+      return new String[]{applicationIdOrName, appType};
+    }
+  }
+
+  private static String getSingleAppTypeFromCLI(CommandLine cliParser) {
+    if (cliParser.hasOption(APP_TYPE_CMD)) {
+      String[] types = cliParser.getOptionValues(APP_TYPE_CMD);
+      if (types != null) {
+        for (String type : types) {
+          if (!type.trim().isEmpty()) {
+            return StringUtils.toLowerCase(type).trim();
+          }
+        }
+      }
+    }
+    return AppAdminClient.DEFAULT_TYPE;
+  }
+
   private void updateApplicationTimeout(String applicationId,
       ApplicationTimeoutType timeoutType, long timeoutInSec)
       throws YarnException, IOException {
@@ -572,7 +797,7 @@ public class ApplicationCLI extends YarnCLI {
   /**
    * Kills applications with the application id as appId
    *
-   * @param Array of applicationIds
+   * @param applicationIds Array of applicationIds
    * @return errorCode
    * @throws YarnException
    * @throws IOException
@@ -663,10 +888,10 @@ public class ApplicationCLI extends YarnCLI {
    * Prints the application report for an application id.
    * 
    * @param applicationId
-   * @return exitCode
+   * @return ApplicationReport
    * @throws YarnException
    */
-  private int printApplicationReport(String applicationId)
+  private ApplicationReport printApplicationReport(String applicationId)
       throws YarnException, IOException {
     ApplicationReport appReport = null;
     try {
@@ -675,7 +900,7 @@ public class ApplicationCLI extends YarnCLI {
     } catch (ApplicationNotFoundException e) {
       sysout.println("Application with id '" + applicationId
           + "' doesn't exist in RM or Timeline Server.");
-      return -1;
+      return null;
     }
     // Use PrintWriter.println, which uses correct platform line ending.
     ByteArrayOutputStream baos = new ByteArrayOutputStream();
@@ -739,11 +964,11 @@ public class ApplicationCLI extends YarnCLI {
           + "' doesn't exist in RM.");
       appReportStr.close();
       sysout.println(baos.toString("UTF-8"));
-      return -1;
+      return null;
     }
     appReportStr.close();
     sysout.println(baos.toString("UTF-8"));
-    return 0;
+    return appReport;
   }
 
   private void printResourceUsage(PrintWriter appReportStr,
@@ -856,11 +1081,12 @@ public class ApplicationCLI extends YarnCLI {
 
   @SuppressWarnings("unchecked")
   private boolean hasAnyOtherCLIOptions(CommandLine cliParser, Options opts,
-      String excludeOption) {
+      String... excludeOptions) {
     Collection<Option> ops = opts.getOptions();
+    Set<String> excludeSet = new HashSet<>(Arrays.asList(excludeOptions));
     for (Option op : ops) {
-      // Skip exclude option from the option list
-      if (op.getOpt().equals(excludeOption)) {
+      // Skip exclude options from the option list
+      if (excludeSet.contains(op.getOpt())) {
         continue;
       }
       if (cliParser.hasOption(op.getOpt())) {

http://git-wip-us.apache.org/repos/asf/hadoop/blob/ba7ed7b6/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/cli/TestYarnCLI.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/cli/TestYarnCLI.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/cli/TestYarnCLI.java
index 84cfb0a..da1659f 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/cli/TestYarnCLI.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-client/src/test/java/org/apache/hadoop/yarn/client/cli/TestYarnCLI.java
@@ -2025,49 +2025,121 @@ public class TestYarnCLI {
     ByteArrayOutputStream baos = new ByteArrayOutputStream();
     PrintWriter pw = new PrintWriter(baos);
     pw.println("usage: application");
-    pw.println(" -appId <Application ID>         Specify Application Id to be operated");
-    pw.println(" -appStates <States>             Works with -list to filter applications");
-    pw.println("                                 based on input comma-separated list of");
-    pw.println("                                 application states. The valid application");
-    pw.println("                                 state can be one of the following:");
-    pw.println("                                 ALL,NEW,NEW_SAVING,SUBMITTED,ACCEPTED,RUN");
-    pw.println("                                 NING,FINISHED,FAILED,KILLED");
-    pw.println(" -appTags <Tags>                 Works with -list to filter applications");
-    pw.println("                                 based on input comma-separated list of");
-    pw.println("                                 application tags.");
-    pw.println(" -appTypes <Types>               Works with -list to filter applications");
-    pw.println("                                 based on input comma-separated list of");
-    pw.println("                                 application types.");
-    pw.println(" -changeQueue <Queue Name>       Moves application to a new queue.");
-    pw.println("                                 ApplicationId can be passed using 'appId'");
-    pw.println("                                 option. 'movetoqueue' command is");
-    pw.println("                                 deprecated, this new command");
-    pw.println("                                 'changeQueue' performs same");
-    pw.println("                                 functionality.");
-    pw.println(" -help                           Displays help for all commands.");
-    pw.println(" -kill <Application ID>          Kills the application. Set of");
-    pw.println("                                 applications can be provided separated");
-    pw.println("                                 with space");
-    pw.println(" -list                           List applications. Supports optional use");
-    pw.println("                                 of -appTypes to filter applications based");
-    pw.println("                                 on application type, -appStates to filter");
-    pw.println("                                 applications based on application state");
-    pw.println("                                 and -appTags to filter applications based");
-    pw.println("                                 on application tag.");
-    pw.println(" -movetoqueue <Application ID>   Moves the application to a different");
-    pw.println("                                 queue. Deprecated command. Use");
-    pw.println("                                 'changeQueue' instead.");
-    pw.println(" -queue <Queue Name>             Works with the movetoqueue command to");
-    pw.println("                                 specify which queue to move an");
-    pw.println("                                 application to.");
-    pw.println(" -status <Application ID>        Prints the status of the application.");
-    pw.println(" -updateLifetime <Timeout>       update timeout of an application from");
-    pw.println("                                 NOW. ApplicationId can be passed using");
-    pw.println("                                 'appId' option. Timeout value is in");
-    pw.println("                                 seconds.");
-    pw.println(" -updatePriority <Priority>      update priority of an application.");
-    pw.println("                                 ApplicationId can be passed using 'appId'");
-    pw.println("                                 option.");
+    pw.println(" -appId <Application ID>                  Specify Application Id to be");
+    pw.println("                                          operated");
+    pw.println(" -appStates <States>                      Works with -list to filter");
+    pw.println("                                          applications based on input");
+    pw.println("                                          comma-separated list of");
+    pw.println("                                          application states. The valid");
+    pw.println("                                          application state can be one of");
+    pw.println("                                          the following:");
+    pw.println("                                          ALL,NEW,NEW_SAVING,SUBMITTED,ACC");
+    pw.println("                                          EPTED,RUNNING,FINISHED,FAILED,KI");
+    pw.println("                                          LLED");
+    pw.println(" -appTags <Tags>                          Works with -list to filter");
+    pw.println("                                          applications based on input");
+    pw.println("                                          comma-separated list of");
+    pw.println("                                          application tags.");
+    pw.println(" -appTypes <Types>                        Works with -list to filter");
+    pw.println("                                          applications based on input");
+    pw.println("                                          comma-separated list of");
+    pw.println("                                          application types.");
+    pw.println(" -changeQueue <Queue Name>                Moves application to a new");
+    pw.println("                                          queue. ApplicationId can be");
+    pw.println("                                          passed using 'appId' option.");
+    pw.println("                                          'movetoqueue' command is");
+    pw.println("                                          deprecated, this new command");
+    pw.println("                                          'changeQueue' performs same");
+    pw.println("                                          functionality.");
+    pw.println(" -component <Component Name> <Count>      Works with -flex option to");
+    pw.println("                                          change the number of");
+    pw.println("                                          components/containers running");
+    pw.println("                                          for an application /");
+    pw.println("                                          long-running service. Supports");
+    pw.println("                                          absolute or relative changes,");
+    pw.println("                                          such as +1, 2, or -3.");
+    pw.println(" -destroy <Application Name>              Destroys a saved application");
+    pw.println("                                          specification and removes all");
+    pw.println("                                          application data permanently.");
+    pw.println("                                          Supports -appTypes option to");
+    pw.println("                                          specify which client");
+    pw.println("                                          implementation to use.");
+    pw.println(" -enableFastLaunch                        Uploads AM dependencies to HDFS");
+    pw.println("                                          to make future launches faster.");
+    pw.println("                                          Supports -appTypes option to");
+    pw.println("                                          specify which client");
+    pw.println("                                          implementation to use.");
+    pw.println(" -flex <Application Name or ID>           Changes number of running");
+    pw.println("                                          containers for a component of an");
+    pw.println("                                          application / long-running");
+    pw.println("                                          service. Requires -component");
+    pw.println("                                          option. If name is provided,");
+    pw.println("                                          appType must be provided unless");
+    pw.println("                                          it is the default yarn-service.");
+    pw.println("                                          If ID is provided, the appType");
+    pw.println("                                          will be looked up. Supports");
+    pw.println("                                          -appTypes option to specify");
+    pw.println("                                          which client implementation to");
+    pw.println("                                          use.");
+    pw.println(" -help                                    Displays help for all commands.");
+    pw.println(" -kill <Application ID>                   Kills the application. Set of");
+    pw.println("                                          applications can be provided");
+    pw.println("                                          separated with space");
+    pw.println(" -launch <Application Name> <File Name>   Launches application from");
+    pw.println("                                          specification file (saves");
+    pw.println("                                          specification and starts");
+    pw.println("                                          application). Options");
+    pw.println("                                          -updateLifetime and -changeQueue");
+    pw.println("                                          can be specified to alter the");
+    pw.println("                                          values provided in the file.");
+    pw.println("                                          Supports -appTypes option to");
+    pw.println("                                          specify which client");
+    pw.println("                                          implementation to use.");
+    pw.println(" -list                                    List applications. Supports");
+    pw.println("                                          optional use of -appTypes to");
+    pw.println("                                          filter applications based on");
+    pw.println("                                          application type, -appStates to");
+    pw.println("                                          filter applications based on");
+    pw.println("                                          application state and -appTags");
+    pw.println("                                          to filter applications based on");
+    pw.println("                                          application tag.");
+    pw.println(" -movetoqueue <Application ID>            Moves the application to a");
+    pw.println("                                          different queue. Deprecated");
+    pw.println("                                          command. Use 'changeQueue'");
+    pw.println("                                          instead.");
+    pw.println(" -queue <Queue Name>                      Works with the movetoqueue");
+    pw.println("                                          command to specify which queue");
+    pw.println("                                          to move an application to.");
+    pw.println(" -save <Application Name> <File Name>     Saves specification file for an");
+    pw.println("                                          application. Options");
+    pw.println("                                          -updateLifetime and -changeQueue");
+    pw.println("                                          can be specified to alter the");
+    pw.println("                                          values provided in the file.");
+    pw.println("                                          Supports -appTypes option to");
+    pw.println("                                          specify which client");
+    pw.println("                                          implementation to use.");
+    pw.println(" -start <Application Name>                Starts a previously saved");
+    pw.println("                                          application. Supports -appTypes");
+    pw.println("                                          option to specify which client");
+    pw.println("                                          implementation to use.");
+    pw.println(" -status <Application ID>                 Prints the status of the");
+    pw.println("                                          application.");
+    pw.println(" -stop <Application Name or ID>           Stops application gracefully");
+    pw.println("                                          (may be started again later). If");
+    pw.println("                                          name is provided, appType must");
+    pw.println("                                          be provided unless it is the");
+    pw.println("                                          default yarn-service. If ID is");
+    pw.println("                                          provided, the appType will be");
+    pw.println("                                          looked up. Supports -appTypes");
+    pw.println("                                          option to specify which client");
+    pw.println("                                          implementation to use.");
+    pw.println(" -updateLifetime <Timeout>                update timeout of an application");
+    pw.println("                                          from NOW. ApplicationId can be");
+    pw.println("                                          passed using 'appId' option.");
+    pw.println("                                          Timeout value is in seconds.");
+    pw.println(" -updatePriority <Priority>               update priority of an");
+    pw.println("                                          application. ApplicationId can");
+    pw.println("                                          be passed using 'appId' option.");
     pw.close();
     String appsHelpStr = baos.toString("UTF-8");
     return appsHelpStr;

http://git-wip-us.apache.org/repos/asf/hadoop/blob/ba7ed7b6/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/markdown/YarnCommands.md
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/markdown/YarnCommands.md b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/markdown/YarnCommands.md
index 6f00c5c..71c9e80 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/markdown/YarnCommands.md
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/markdown/YarnCommands.md
@@ -37,25 +37,36 @@ User Commands
 
 Commands useful for users of a Hadoop cluster.
 
-### `application`
+### `application` or `app`
 
 Usage: `yarn application [options] `
+Usage: `yarn app [options] `
 
 | COMMAND\_OPTIONS | Description |
 |:---- |:---- |
 | -appId \<ApplicationId\> | Specify Application Id to be operated |
 | -appStates \<States\> | Works with -list to filter applications based on input comma-separated list of application states. The valid application state can be one of the following:  ALL, NEW, NEW\_SAVING, SUBMITTED, ACCEPTED, RUNNING, FINISHED, FAILED, KILLED |
+| -appTags \<Tags\> | Works with -list to filter applications based on input comma-separated list of application tags. |
 | -appTypes \<Types\> | Works with -list to filter applications based on input comma-separated list of application types. |
-| -help | Help |
-| -list | Lists applications from the RM. Supports optional use of -appTypes to filter applications based on application type, and -appStates to filter applications based on application state. |
-| -kill \<ApplicationId\> | Kills the application. |
-| -movetoqueue \<Application Id\> | Moves the application to a different queue. |
+| -changeQueue \<Queue Name\> | Moves application to a new queue. ApplicationId can be passed using 'appId' option. 'movetoqueue' command is deprecated, this new command 'changeQueue' performs same functionality. |
+| -component \<Component Name\> \<Count\> | Works with -flex option to change the number of components/containers running for an application / long-running service. Supports absolute or relative changes, such as +1, 2, or -3. |
+| -destroy \<Application Name\> | Destroys a saved application specification and removes all application data permanently. Supports -appTypes option to specify which client implementation to use. |
+| -enableFastLaunch | Uploads AM dependencies to HDFS to make future launches faster. Supports -appTypes option to specify which client implementation to use. |
+| -flex \<Application Name or ID\> | Changes number of running containers for a component of an application / long-running service. Requires -component option. If name is provided, appType must be provided unless it is the default yarn-service. If ID is provided, the appType will be looked up. Supports -appTypes option to specify which client implementation to use. |
+| -help | Displays help for all commands. |
+| -kill \<Application ID\> | Kills the application. Set of applications can be provided separated with space |
+| -launch \<Application Name\> \<File Name\> | Launches application from specification file (saves specification and starts application). Options -updateLifetime and -changeQueue can be specified to alter the values provided in the file. Supports -appTypes option to specify which client implementation to use. |
+| -list | List applications. Supports optional use of -appTypes to filter applications based on application type, -appStates to filter applications based on application state and -appTags to filter applications based on application tag. |
+| -movetoqueue \<Application ID\> | Moves the application to a different queue. Deprecated command. Use 'changeQueue' instead. |
 | -queue \<Queue Name\> | Works with the movetoqueue command to specify which queue to move an application to. |
+| -save \<Application Name\> \<File Name\> | Saves specification file for an application. Options -updateLifetime and -changeQueue can be specified to alter the values provided in the file. Supports -appTypes option to specify which client implementation to use. |
+| -start \<Application Name\> | Starts a previously saved application. Supports -appTypes option to specify which client implementation to use. |
 | -status \<ApplicationId\> | Prints the status of the application. |
-| -updateLifetime \<Timeout\> | Update application timeout (from the time of request) in seconds. ApplicationId can be specified using 'appId' option. |
+| -stop \<Application Name or ID\> | Stops application gracefully (may be started again later). If name is provided, appType must be provided unless it is the default yarn-service. If ID is provided, the appType will be looked up. Supports -appTypes option to specify which client implementation to use. |
+| -updateLifetime \<Timeout\> | Update timeout of an application from NOW. ApplicationId can be passed using 'appId' option. Timeout value is in seconds. |
 | -updatePriority \<Priority\> | Update priority of an application. ApplicationId can be passed using 'appId' option. |
 
-Prints application(s) report/kill application
+Prints application(s) report/kill application/manage long running application
 
 ### `applicationattempt`
 
@@ -69,61 +80,6 @@ Usage: `yarn applicationattempt [options] `
 
 prints applicationattempt(s) report
 
-### `service`
-Usage `yarn service [sub-command] [service-name] [options]`
-
-#### `SUB_COMMAND`
-
-* `build`:  Build a service with its specifications, but do not start it.
-    ```
-    Usage: yarn service build [service-name] --file [file]
-    Fields:
-    service-name     Optional. If specified, it will override the name in the service definition.
-
-    Options:
-      --file,-f      The local path to the service definition file
-    ```
-
-* `create`:  create a service, it's equivalent to first invoke build and then start.
-   ```
-   Usage: yarn service create [service-name] --file [file]
-   Fields:
-    service-name    Optional. If specified, it will override the name in the service definition.
-
-   Options:
-    --file,-f       The local path to the service definition file.
-    --queue,-q      The queue to which the service is submitted.
-    --example,-e    The name of the example service such as:
-                    Sleeper      A simple service that launches a few non-docker sleep containers on YARN.
-   ```
-
-* `dependency`:  Yarn service framework dependency (libraries) management.
-  ```
-  Usage: yarn service dependency [options]
-  Option:
-     --upload      Pre-upload the dependency jars onto HDFS to expediate service launch process.
-  ```
-
-* `destroy`:  Destroy a stopped service, service must be stopped first before destroying.
-  ```
-  Usage: yarn service destroy [service-name]
-  ```
-* `flex`:   Flex a service's component by increasing or decreasing the number of containers.
-  ```
-  Usage: yarn service flex [service-name] --component [component-name] [count]
-  Options:
-    --component [component-name] [count]
-            Specifies the component name and its number of containers. e.g. +1 incr by 1, -2 decr by 2, and 3 makes final count 3.
-  ```
-* `status`:  Get the status of a service.
-  ```
-  Usage: yarn service status [service-name]
-  ```
-* `start`:  Start a service with pre-built specification or a previously stopped service.
-  ```
-  Usage: yarn service start [service-name]
-  ```
-
 ### `classpath`
 
 Usage: `yarn classpath [--glob |--jar <path> |-h |--help]`
@@ -328,12 +284,6 @@ Usage: `yarn timelineserver`
 
 Start the TimeLineServer
 
-### apiserver
-
-Usage: `yarn apiserver`
-
-Start the API-server for deploying/managing services on YARN
-
 ### registrydns
 
 Usage: `yarn registrydns`

http://git-wip-us.apache.org/repos/asf/hadoop/blob/ba7ed7b6/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/markdown/yarn-service/Examples.md
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/markdown/yarn-service/Examples.md b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/markdown/yarn-service/Examples.md
index db6d553..e4881ce 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/markdown/yarn-service/Examples.md
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/markdown/yarn-service/Examples.md
@@ -100,16 +100,18 @@ ProxyPassReverse "/"  "balancer://test/"
 
 Then run the service with the command:
 ```
-yarn service create [service-name] --example httpd
+yarn app -launch <service-name> httpd
 ```
-where `service-name` is optional. If omitted, it uses the name defined in the `Yarnfile`.
+
+The last argument is either the path to a JSON specification of the service, or in this case, the name of an example service.
+The directory where examples can be found can be configured by setting the YARN\_EXAMPLES\_DIR environment variable.
 
 Once the service is running, navigate to `http://httpd-proxy-0.${SERVICE_NAME}.${USER}.${DOMAIN}:8080` to see the root page.
 The pages should alternately show "Hello from httpd-0!" or "Hello from httpd-1!"
 
 The individual httpd URLs can also be visited, `http://httpd-0.${SERVICE_NAME}.${USER}.${DOMAIN}:8080` and `http://httpd-1.${SERVICE_NAME}.${USER}.${DOMAIN}:8080`.
 
-If unsure of your hostnames, visit the apiserver REST endpoint `http://<apiserver host>:9191/ws/v1/services/httpd-service`.
+If unsure of your hostnames, visit the RM REST endpoint `http://<RM host>:8088/ws/v1/services/httpd-service`.
 
 ## Apache web server - httpd (without registry DNS)
 
@@ -151,9 +153,9 @@ hdfs dfs -copyFromLocal ${HADOOP_YARN_HOME}/share/hadoop/yarn/yarn-service-examp
 
 Then run the service with the command:
 ```
-yarn service create [service-name] --example httpd-no-dns
+yarn app -launch <service-name> httpd-no-dns
 ```
 where `service-name` is optional. If omitted, it uses the name defined in the `Yarnfile`.
 
-Look up your IPs at the apiserver REST endpoint `http://<apiserver host>:9191/ws/v1/services/httpd-service`.
+Look up your IPs at the RM REST endpoint `http://<RM host>:8088/ws/v1/services/httpd-service`.
 Then visit port 8080 for each IP to view the pages.

http://git-wip-us.apache.org/repos/asf/hadoop/blob/ba7ed7b6/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/markdown/yarn-service/QuickStart.md
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/markdown/yarn-service/QuickStart.md b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/markdown/yarn-service/QuickStart.md
index afcd5f5..512c011 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/markdown/yarn-service/QuickStart.md
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/markdown/yarn-service/QuickStart.md
@@ -45,11 +45,11 @@ Below is a simple service definition that launches sleep containers on YARN by w
 ```
 User can simply run a pre-built example service on YARN using below command:
 ```
-yarn service create [service-name] --example [example-name]
+yarn app -launch <service-name> <example-name>
 ```
 e.g. Below command launches a `sleeper` service named as `my-sleeper` on YARN.
 ```
-yarn service create my-sleeper --example sleeper
+yarn app -launch my-sleeper sleeper
 ```
 For launching docker based services using YARN Service framework, please refer to [API doc](YarnServiceAPI.md).
 
@@ -58,51 +58,53 @@ Below steps walk you through deploying a services on YARN using CLI.
 Refer to [Yarn Commands](../YarnCommands.md) for the full list of commands and options.
 ### Deploy a service
 ```
-yarn service create --file ${PATH_TO_SERVICE_DEF_FILE}
+yarn app -launch ${SERVICE_NAME} ${PATH_TO_SERVICE_DEF_FILE}
 ```
 Params:
-- SERVICE_NAME: The name of the service. Note that this needs to be unique across all running services.
+- SERVICE_NAME: The name of the service. Note that this needs to be unique across running services for the current user.
 - PATH_TO_SERVICE_DEF: The path to the service definition file in JSON format.
 
 For example:
 ```
-yarn service create --file /path/to/local/sleeper.json
+yarn app -launch sleeper-service /path/to/local/sleeper.json
 ```
 
 ### Flex a component of a service
 Increase or decrease the number of containers for a component.
 ```
-yarn service flex ${SERVICE_NAME} --component ${COMPONENT_NAME} ${NUMBER_OF_CONTAINERS}
+yarn app -flex ${SERVICE_NAME} -component ${COMPONENT_NAME} ${NUMBER_OF_CONTAINERS}
 ```
 For example, for a service named `sleeper-service`:
 
 Set the `sleeper` component to `2` containers (absolute number).
 
 ```
-yarn service flex sleeper-service --component sleeper 2
+yarn app -flex sleeper-service -component sleeper 2
 ```
 
+Relative changes are also supported for the ${NUMBER_OF_CONTAINERS} in the flex command, such as +2 or -2.
+
 ### Stop a service
 Stopping a service will stop all containers of the service and the ApplicationMaster, but does not delete the state of a service, such as the service root folder on hdfs.
 ```
-yarn service stop ${SERVICE_NAME}
+yarn app -stop ${SERVICE_NAME}
 ```
 
 ### Restart a stopped service
 Restarting a stopped service is easy - just call start!
 ```
-yarn service start ${SERVICE_NAME}
+yarn app -start ${SERVICE_NAME}
 ```
 
 ### Destroy a service
 In addition to stopping a service, it also deletes the service root folder on hdfs and the records in YARN Service Registry.
 ```
-yarn service destroy ${SERVICE_NAME}
+yarn app -destroy ${SERVICE_NAME}
 ```
 
 ## Manage services on YARN via REST API
 
-YARN API Server REST API can be activated in two modes: embedded or standalone.
+YARN API Server REST API can be activated as part of the ResourceManager.
 
 ### Start Embedded API-Server as part of ResourceManager
 For running inside ResourceManager, add this property to `yarn-site.xml` and restart ResourceManager.
@@ -119,13 +121,6 @@ For running inside ResourceManager, add this property to `yarn-site.xml` and res
 
 Services can be deployed on YARN through the ResourceManager web endpoint.
 
-### Start Standalone API-Server for deploying services on YARN
-API server is the service that sits in front of YARN ResourceManager and lets users submit their service specs via HTTP.
-```
- yarn --daemon start apiserver
- ```
-The above command starts the API Server on the localhost at port 9191 by default. 
-
 Refer to [API doc](YarnServiceAPI.md)  for the detailed API specificatiosn.
 
 ### Deploy a service
@@ -135,19 +130,14 @@ POST the aforementioned example service definition to the ResourceManager api-se
 POST  http://localhost:8088/ws/v1/services
 ```
 
-Or standalone API server:
-```
-POST  http://localhost:9191/ws/v1/services
-```
-
 ### Get a service status
 ```
-GET  http://localhost:9191/ws/v1/services/${SERVICE_NAME}
+GET  http://localhost:8088/ws/v1/services/${SERVICE_NAME}
 ```
 
 ### Flex a component of a service
 ```
-PUT  http://localhost:9191/ws/v1/services/${SERVICE_NAME}/components/${COMPONENT_NAME}
+PUT  http://localhost:8088/ws/v1/services/${SERVICE_NAME}/components/${COMPONENT_NAME}
 ```
 `PUT` Request body:
 ```
@@ -168,7 +158,7 @@ For example:
 Stopping a service will stop all containers of the service and the ApplicationMaster, but does not delete the state of a service, such as the service root folder on hdfs.
 
 ```
-PUT  http://localhost:9191/ws/v1/services/${SERVICE_NAME}
+PUT  http://localhost:8088/ws/v1/services/${SERVICE_NAME}
 ```
 
 `PUT` Request body:
@@ -183,7 +173,7 @@ PUT  http://localhost:9191/ws/v1/services/${SERVICE_NAME}
 Restarting a stopped service is easy.
 
 ```
-PUT  http://localhost:9191/ws/v1/services/${SERVICE_NAME}
+PUT  http://localhost:8088/ws/v1/services/${SERVICE_NAME}
 ```
 
 `PUT` Request body:
@@ -196,7 +186,7 @@ PUT  http://localhost:9191/ws/v1/services/${SERVICE_NAME}
 ### Destroy a service
 In addition to stopping a service, it also deletes the service root folder on hdfs and the records in YARN Service Registry.
 ```
-DELETE  http://localhost:9191/ws/v1/services/${SERVICE_NAME}
+DELETE  http://localhost:8088/ws/v1/services/${SERVICE_NAME}
 ```
 
 ## Services UI with YARN UI2 and Timeline Service v2

http://git-wip-us.apache.org/repos/asf/hadoop/blob/ba7ed7b6/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/markdown/yarn-service/YarnServiceAPI.md
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/markdown/yarn-service/YarnServiceAPI.md b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/markdown/yarn-service/YarnServiceAPI.md
index e9aaf7e..7a2490e 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/markdown/yarn-service/YarnServiceAPI.md
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/markdown/yarn-service/YarnServiceAPI.md
@@ -37,7 +37,7 @@ License URL: http://www.apache.org/licenses/LICENSE-2.0.html
 ### URI scheme
 Host: host.mycompany.com
 
-Port: 9191(default)
+Port: 8088(default RM port)
 
 Schemes: HTTP
 
@@ -368,7 +368,7 @@ The current status of a submitted service, returned as a response to the GET API
 ## Examples
 
 ### Create a simple single-component service with most attribute values as defaults
-POST URL - http://localhost:9191/ws/v1/services
+POST URL - http://localhost:8088/ws/v1/services
 
 ##### POST Request JSON
 ```json
@@ -394,7 +394,7 @@ POST URL - http://localhost:9191/ws/v1/services
 ```
 
 ##### GET Response JSON
-GET URL - http://localhost:9191/ws/v1/services/hello-world
+GET URL - http://localhost:8088/ws/v1/services/hello-world
 
 Note, lifetime value of -1 means unlimited lifetime.
 
@@ -452,7 +452,7 @@ Note, lifetime value of -1 means unlimited lifetime.
 
 ```
 ### Update to modify the lifetime of a service
-PUT URL - http://localhost:9191/ws/v1/services/hello-world
+PUT URL - http://localhost:8088/ws/v1/services/hello-world
 
 ##### PUT Request JSON
 
@@ -464,7 +464,7 @@ Note, irrespective of what the current lifetime value is, this update request wi
 }
 ```
 ### Stop a service
-PUT URL - http://localhost:9191/ws/v1/services/hello-world
+PUT URL - http://localhost:8088/ws/v1/services/hello-world
 
 ##### PUT Request JSON
 ```json
@@ -474,7 +474,7 @@ PUT URL - http://localhost:9191/ws/v1/services/hello-world
 ```
 
 ### Start a service
-PUT URL - http://localhost:9191/ws/v1/services/hello-world
+PUT URL - http://localhost:8088/ws/v1/services/hello-world
 
 ##### PUT Request JSON
 ```json
@@ -484,7 +484,7 @@ PUT URL - http://localhost:9191/ws/v1/services/hello-world
 ```
 
 ### Update to flex up/down the no of containers (instances) of a component of a service
-PUT URL - http://localhost:9191/ws/v1/services/hello-world/components/hello
+PUT URL - http://localhost:8088/ws/v1/services/hello-world/components/hello
 
 ##### PUT Request JSON
 ```json
@@ -495,12 +495,12 @@ PUT URL - http://localhost:9191/ws/v1/services/hello-world/components/hello
 ```
 
 ### Destroy a service
-DELETE URL - http://localhost:9191/ws/v1/services/hello-world
+DELETE URL - http://localhost:8088/ws/v1/services/hello-world
 
 ***
 
 ### Create a complicated service  - HBase
-POST URL - http://localhost:9191:/ws/v1/services/hbase-app-1
+POST URL - http://localhost:8088:/ws/v1/services/hbase-app-1
 
 ##### POST Request JSON
 
@@ -595,4 +595,4 @@ POST URL - http://localhost:9191:/ws/v1/services/hbase-app-1
     "Proxied HBase Master Status UI": "http://app-proxy/${DOMAIN}/${USER}/${SERVICE_NAME}/hbasemaster/16010/"
   }
 }
-```
\ No newline at end of file
+```


---------------------------------------------------------------------
To unsubscribe, e-mail: common-commits-unsubscribe@hadoop.apache.org
For additional commands, e-mail: common-commits-help@hadoop.apache.org


Mime
View raw message