Repository: incubator-slider
Updated Branches:
  refs/heads/develop 90c9d3e22 -> c0a320db2


SLIDER-464 add an install-keytab command to slider client


Project: http://git-wip-us.apache.org/repos/asf/incubator-slider/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-slider/commit/c0a320db
Tree: http://git-wip-us.apache.org/repos/asf/incubator-slider/tree/c0a320db
Diff: http://git-wip-us.apache.org/repos/asf/incubator-slider/diff/c0a320db

Branch: refs/heads/develop
Commit: c0a320db20e492c9982ba837c7133a51de85b817
Parents: 90c9d3e
Author: Jon Maron <[email protected]>
Authored: Wed Oct 15 17:28:53 2014 -0400
Committer: Jon Maron <[email protected]>
Committed: Wed Oct 15 17:28:53 2014 -0400

----------------------------------------------------------------------
 .../org/apache/slider/client/SliderClient.java  |  47 ++++-
 .../apache/slider/client/SliderClientAPI.java   |  14 +-
 .../common/params/ActionInstallKeytabArgs.java  |  57 +++++
 .../apache/slider/common/params/Arguments.java  |   5 +-
 .../apache/slider/common/params/ClientArgs.java |  10 +-
 .../slider/common/params/SliderActions.java     |   2 +
 .../slider/common/tools/CoreFileSystem.java     |  12 ++
 .../slider/client/TestInstallKeytab.groovy      | 206 +++++++++++++++++++
 .../funtest/framework/CommandTestBase.groovy    |   3 +
 9 files changed, 352 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/c0a320db/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 836fde0..ed62994 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
@@ -24,6 +24,7 @@ import org.apache.commons.lang.StringUtils;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.fs.PathNotFoundException;
+import org.apache.hadoop.fs.permission.FsAction;
 import org.apache.hadoop.fs.permission.FsPermission;
 import org.apache.hadoop.hdfs.DFSConfigKeys;
 import org.apache.hadoop.hdfs.HdfsConfiguration;
@@ -65,6 +66,7 @@ import org.apache.slider.common.SliderKeys;
 import org.apache.slider.common.params.AbstractActionArgs;
 import org.apache.slider.common.params.AbstractClusterBuildingActionArgs;
 import org.apache.slider.common.params.ActionDiagnosticArgs;
+import org.apache.slider.common.params.ActionInstallKeytabArgs;
 import org.apache.slider.common.params.ActionInstallPackageArgs;
 import org.apache.slider.common.params.ActionAMSuicideArgs;
 import org.apache.slider.common.params.ActionCreateArgs;
@@ -172,7 +174,7 @@ public class SliderClient extends 
AbstractSliderLaunchedService implements RunSe
    */
   private SliderClusterOperations sliderClusterOperations;
 
-  private SliderFileSystem sliderFileSystem;
+  protected SliderFileSystem sliderFileSystem;
 
   /**
    * Yarn client service
@@ -326,6 +328,8 @@ public class SliderClient extends 
AbstractSliderLaunchedService implements RunSe
     // actions
     if (ACTION_INSTALL_PACKAGE.equals(action)) {
       exitCode = actionInstallPkg(serviceArgs.getActionInstallPackageArgs());
+    } else if (ACTION_INSTALL_KEYTAB.equals(action)) {
+      exitCode = actionInstallKeytab(serviceArgs.getActionInstallKeytabArgs());
     } else if (ACTION_BUILD.equals(action)) {
       exitCode = actionBuild(clusterName, serviceArgs.getActionBuildArgs());
     } else if (ACTION_CREATE.equals(action)) {
@@ -625,6 +629,47 @@ public class SliderClient extends 
AbstractSliderLaunchedService implements RunSe
   }
 
   @Override
+  public int actionInstallKeytab(ActionInstallKeytabArgs installKeytabInfo)
+      throws YarnException, IOException {
+
+    Path srcFile = null;
+    if (StringUtils.isEmpty(installKeytabInfo.folder )) {
+      throw new BadCommandArgumentsException("A valid destination keytab 
sub-folder name is required (e.g. 'security').");
+    }
+
+    if (StringUtils.isEmpty(installKeytabInfo.keytabUri)) {
+      throw new BadCommandArgumentsException("A valid local keytab location is 
required.");
+    } else {
+      File keytabFile = new File(installKeytabInfo.keytabUri);
+      if (!keytabFile.exists() || keytabFile.isDirectory()) {
+        throw new BadCommandArgumentsException("Unable to access supplied 
keytab file at " +
+                                               keytabFile.getAbsolutePath());
+      } else {
+        srcFile = new Path(keytabFile.toURI());
+      }
+    }
+
+    Path pkgPath = 
sliderFileSystem.buildKeytabInstallationDirPath(installKeytabInfo.folder);
+    sliderFileSystem.getFileSystem().mkdirs(pkgPath);
+    sliderFileSystem.getFileSystem().setPermission(pkgPath, new FsPermission(
+        FsAction.ALL, FsAction.NONE, FsAction.NONE));
+
+    Path fileInFs = new Path(pkgPath, srcFile.getName());
+    log.info("Installing keytab {} at {} and overwrite is {}.", srcFile, 
fileInFs, installKeytabInfo.overwrite);
+    if (sliderFileSystem.getFileSystem().exists(fileInFs) && 
!installKeytabInfo.overwrite) {
+      throw new BadCommandArgumentsException("Keytab exists at " +
+                                             fileInFs.toUri().toString() +
+                                             ". Use --overwrite to 
overwrite.");
+    }
+
+    sliderFileSystem.getFileSystem().copyFromLocalFile(false, 
installKeytabInfo.overwrite, srcFile, fileInFs);
+    sliderFileSystem.getFileSystem().setPermission(fileInFs, new FsPermission(
+        FsAction.READ_WRITE, FsAction.NONE, FsAction.NONE));
+
+    return EXIT_SUCCESS;
+  }
+
+  @Override
   public int actionInstallPkg(ActionInstallPackageArgs installPkgInfo) throws
       YarnException,
       IOException {

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/c0a320db/slider-core/src/main/java/org/apache/slider/client/SliderClientAPI.java
----------------------------------------------------------------------
diff --git 
a/slider-core/src/main/java/org/apache/slider/client/SliderClientAPI.java 
b/slider-core/src/main/java/org/apache/slider/client/SliderClientAPI.java
index 3d2c8cd..09ca8fa 100644
--- a/slider-core/src/main/java/org/apache/slider/client/SliderClientAPI.java
+++ b/slider-core/src/main/java/org/apache/slider/client/SliderClientAPI.java
@@ -29,6 +29,7 @@ import org.apache.slider.common.params.ActionDiagnosticArgs;
 import org.apache.slider.common.params.ActionEchoArgs;
 import org.apache.slider.common.params.ActionFlexArgs;
 import org.apache.slider.common.params.ActionFreezeArgs;
+import org.apache.slider.common.params.ActionInstallKeytabArgs;
 import org.apache.slider.common.params.ActionInstallPackageArgs;
 import org.apache.slider.common.params.ActionKillContainerArgs;
 import org.apache.slider.common.params.ActionRegistryArgs;
@@ -84,9 +85,20 @@ public interface SliderClientAPI extends Service {
       AbstractClusterBuildingActionArgs buildInfo) throws YarnException, 
IOException;
 
   /**
+   * Upload keytab to a designated sub-directory of the user home directory
+   *
+   * @param installKeytabInfo the arguments needed to upload the keytab
+   * @throws YarnException Yarn problems
+   * @throws IOException other problems
+   * @throws BadCommandArgumentsException bad arguments.
+   */
+  int actionInstallKeytab(ActionInstallKeytabArgs installKeytabInfo)
+      throws YarnException, IOException;
+
+  /**
    * Upload application package to user home directory
    *
-   * @param installPkgInfo the arguments needed to build the cluster
+   * @param installPkgInfo the arguments needed to upload the package
    * @throws YarnException Yarn problems
    * @throws IOException other problems
    * @throws BadCommandArgumentsException bad arguments.

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/c0a320db/slider-core/src/main/java/org/apache/slider/common/params/ActionInstallKeytabArgs.java
----------------------------------------------------------------------
diff --git 
a/slider-core/src/main/java/org/apache/slider/common/params/ActionInstallKeytabArgs.java
 
b/slider-core/src/main/java/org/apache/slider/common/params/ActionInstallKeytabArgs.java
new file mode 100644
index 0000000..4cfb889
--- /dev/null
+++ 
b/slider-core/src/main/java/org/apache/slider/common/params/ActionInstallKeytabArgs.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.slider.common.params;
+
+import com.beust.jcommander.Parameter;
+import com.beust.jcommander.Parameters;
+
+@Parameters(commandNames = {SliderActions.ACTION_INSTALL_KEYTAB},
+            commandDescription = SliderActions.DESCRIBE_ACTION_INSTALL_KEYTAB)
+
+public class ActionInstallKeytabArgs extends AbstractActionArgs {
+  
+  @Override
+  public String getActionName() {
+    return SliderActions.ACTION_INSTALL_KEYTAB;
+  }
+
+  @Parameter(names = {ARG_KEYTAB},
+             description = "Path to keytab on local disk")
+  public String keytabUri;
+
+  @Parameter(names = {ARG_FOLDER},
+             description = "The name of the folder in which to store the 
keytab")
+  public String folder;
+
+  @Parameter(names = {ARG_OVERWRITE}, description = "Overwrite existing 
keytab")
+  public boolean overwrite = false;
+
+  /**
+   * Get the min #of params expected
+   * @return the min number of params in the {@link #parameters} field
+   */
+  public int getMinParams() {
+    return 0;
+  }
+
+  @Override
+  public int getMaxParams() {
+    return 3;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/c0a320db/slider-core/src/main/java/org/apache/slider/common/params/Arguments.java
----------------------------------------------------------------------
diff --git 
a/slider-core/src/main/java/org/apache/slider/common/params/Arguments.java 
b/slider-core/src/main/java/org/apache/slider/common/params/Arguments.java
index ff064c8..24ad442 100644
--- a/slider-core/src/main/java/org/apache/slider/common/params/Arguments.java
+++ b/slider-core/src/main/java/org/apache/slider/common/params/Arguments.java
@@ -65,16 +65,19 @@ public interface Arguments {
   String ARG_MANAGER = "--manager";
   String ARG_MANAGER_SHORT = "--m";
   String ARG_MESSAGE = "--message";
-  String ARG_NAME = "--name";
   String ARG_OPTION = "--option";
   String ARG_OPTION_SHORT = "-O";
+  String ARG_NAME = "--name";
+  String ARG_FOLDER = "--folder";
   String ARG_OUTPUT = "--out";
   String ARG_OUTPUT_SHORT = "-o";
   String ARG_PACKAGE = "--package";
+  String ARG_KEYTAB = "--keytab";
   String ARG_PATH = "--path";
   String ARG_PROVIDER = "--provider";
   String ARG_QUEUE = "--queue";
   String ARG_REPLACE_PKG = "--replacepkg";
+  String ARG_OVERWRITE = "--overwrite";
   String ARG_RESOURCES = "--resources";
   String ARG_RES_COMP_OPT = "--rescompopt";
   String ARG_RES_COMP_OPT_SHORT = "--rco";

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/c0a320db/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 6e03d4b..b0a4950 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
@@ -47,6 +47,7 @@ public class ClientArgs extends CommonArgs {
   private final ActionAMSuicideArgs actionAMSuicideArgs = new 
ActionAMSuicideArgs();
   private final ActionBuildArgs actionBuildArgs = new ActionBuildArgs();
   private final ActionInstallPackageArgs actionInstallPackageArgs = new 
ActionInstallPackageArgs();
+  private final ActionInstallKeytabArgs actionInstallKeytabArgs = new 
ActionInstallKeytabArgs();
   private final ActionUpdateArgs actionUpdateArgs = new ActionUpdateArgs();
   private final ActionCreateArgs actionCreateArgs = new ActionCreateArgs();
   private final ActionDestroyArgs actionDestroyArgs = new ActionDestroyArgs();
@@ -88,6 +89,7 @@ public class ClientArgs extends CommonArgs {
         actionFreezeArgs,
         actionHelpArgs,
         actionInstallPackageArgs,
+        actionInstallKeytabArgs,
         actionKillContainerArgs,
         actionListArgs,
         actionRegistryArgs,
@@ -115,7 +117,7 @@ public class ClientArgs extends CommonArgs {
   }
 
   public ActionDiagnosticArgs getActionDiagnosticArgs() {
-       return actionDiagnosticArgs;
+         return actionDiagnosticArgs;
   }
 
   public AbstractClusterBuildingActionArgs getBuildingActionArgs() {
@@ -133,6 +135,9 @@ public class ClientArgs extends CommonArgs {
   public ActionInstallPackageArgs getActionInstallPackageArgs() {
     return actionInstallPackageArgs; }
 
+  public ActionInstallKeytabArgs getActionInstallKeytabArgs() {
+    return actionInstallKeytabArgs; }
+
   public ActionUpdateArgs getActionUpdateArgs() {
     return actionUpdateArgs;
   }
@@ -228,6 +233,9 @@ public class ClientArgs extends CommonArgs {
     } else if (SliderActions.ACTION_INSTALL_PACKAGE.equals(action)) {
       bindCoreAction(actionInstallPackageArgs);
 
+    } else if (SliderActions.ACTION_INSTALL_KEYTAB.equals(action)) {
+      bindCoreAction(actionInstallKeytabArgs);
+
     } else if (SliderActions.ACTION_KILL_CONTAINER.equals(action)) {
       bindCoreAction(actionKillContainerArgs);
 

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/c0a320db/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 abb669a..7c68d16 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
@@ -46,6 +46,7 @@ public interface SliderActions {
   String ACTION_VERSION = "version";
   String ACTION_DIAGNOSTIC = "diagnostic";
   String ACTION_INSTALL_PACKAGE = "install-package";
+  String ACTION_INSTALL_KEYTAB = "install-keytab";
   String DESCRIBE_ACTION_AM_SUICIDE =
     "Tell the Slider Application Master to simulate a process failure by 
terminating itself";
   String DESCRIBE_ACTION_BUILD =
@@ -81,6 +82,7 @@ public interface SliderActions {
   String DESCRIBE_ACTION_VERSION =
                         "Print the Slider version information";
   String DESCRIBE_ACTION_INSTALL_PACKAGE = "Install the application package in 
the home directory under sub-folder packages";
+  String DESCRIBE_ACTION_INSTALL_KEYTAB = "Install the Kerberos keytab file in 
the sub-folder 'keytabs' of the user's Slider base directory";
   String DESCRIBE_ACTION_DIAGNOSTIC = "Diagnose the configuration of the 
running slider application and slider client";
   
 }

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/c0a320db/slider-core/src/main/java/org/apache/slider/common/tools/CoreFileSystem.java
----------------------------------------------------------------------
diff --git 
a/slider-core/src/main/java/org/apache/slider/common/tools/CoreFileSystem.java 
b/slider-core/src/main/java/org/apache/slider/common/tools/CoreFileSystem.java
index 9a96bd1..23eeefe 100644
--- 
a/slider-core/src/main/java/org/apache/slider/common/tools/CoreFileSystem.java
+++ 
b/slider-core/src/main/java/org/apache/slider/common/tools/CoreFileSystem.java
@@ -137,6 +137,18 @@ public class CoreFileSystem {
    * Build up the path string for keytab install location -no attempt to
    * create the directory is made
    *
+   * @return the path for keytab
+   */
+  public Path buildKeytabInstallationDirPath(String keytabFolder) {
+    Preconditions.checkNotNull(keytabFolder);
+    Path path = getBaseApplicationPath();
+    return new Path(path, SliderKeys.KEYTAB_DIR + "/" + keytabFolder);
+  }
+
+  /**
+   * Build up the path string for keytab install location -no attempt to
+   * create the directory is made
+   *
    * @return the path for keytab installation location
    */
   public Path buildKeytabPath(String keytabDir, String keytabName, String 
clusterName) {

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/c0a320db/slider-core/src/test/groovy/org/apache/slider/client/TestInstallKeytab.groovy
----------------------------------------------------------------------
diff --git 
a/slider-core/src/test/groovy/org/apache/slider/client/TestInstallKeytab.groovy 
b/slider-core/src/test/groovy/org/apache/slider/client/TestInstallKeytab.groovy
new file mode 100644
index 0000000..b8a14eb
--- /dev/null
+++ 
b/slider-core/src/test/groovy/org/apache/slider/client/TestInstallKeytab.groovy
@@ -0,0 +1,206 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.slider.client
+
+import org.apache.commons.io.FileUtils
+import org.apache.hadoop.fs.FileUtil
+import org.apache.hadoop.fs.Path
+import org.apache.hadoop.fs.RawLocalFileSystem
+import org.apache.hadoop.yarn.conf.YarnConfiguration
+import org.apache.slider.common.params.Arguments
+import org.apache.slider.common.params.ClientArgs
+import org.apache.slider.common.tools.SliderFileSystem
+import org.apache.slider.common.tools.SliderUtils
+import org.apache.slider.core.exceptions.BadCommandArgumentsException
+import org.apache.slider.core.exceptions.SliderException
+import org.apache.slider.core.main.ServiceLauncher
+import org.apache.slider.core.main.ServiceLauncherBaseTest
+import org.junit.Before
+import org.junit.Test
+
+/**
+ * Test a keytab installation
+ */
+class TestInstallKeytab extends ServiceLauncherBaseTest {
+  final shouldFail = new GroovyTestCase().&shouldFail
+
+  private static SliderFileSystem testFileSystem
+
+  @Before
+  public void setupFilesystem() {
+    org.apache.hadoop.fs.FileSystem fileSystem = new RawLocalFileSystem()
+    YarnConfiguration configuration = SliderUtils.createConfiguration()
+    fileSystem.setConf(configuration)
+    testFileSystem = new SliderFileSystem(fileSystem, configuration)
+  }
+
+  @Test
+  public void testInstallKeytab() throws Throwable {
+    // create a mock keytab file
+    File localKeytab =
+      FileUtil.createLocalTempFile(FileUtils.getTempDirectory(), "test", true);
+    String contents = UUID.randomUUID().toString()
+    FileUtils.write(localKeytab, contents);
+    YarnConfiguration conf = SliderUtils.createConfiguration()
+    ServiceLauncher launcher = launch(TestSliderClient,
+                                      conf,
+                                      [
+                                          ClientArgs.ACTION_INSTALL_KEYTAB,
+                                          ClientArgs.ARG_KEYTAB,
+                                          localKeytab.absolutePath,
+                                          Arguments.ARG_FOLDER,
+                                          "testFolder"])
+    Path installedPath = new 
Path(testFileSystem.buildKeytabInstallationDirPath("testFolder"), 
localKeytab.getName())
+    File installedKeytab = new File(installedPath.toUri().path)
+    assert installedKeytab.exists()
+    assert FileUtils.readFileToString(installedKeytab).equals(
+        FileUtils.readFileToString(localKeytab))
+  }
+
+  @Test
+  public void testInstallKeytabWithNoFolder() throws Throwable {
+    // create a mock keytab file
+    File localKeytab =
+      FileUtil.createLocalTempFile(FileUtils.getTempDirectory(), "test", true);
+    String contents = UUID.randomUUID().toString()
+    FileUtils.write(localKeytab, contents);
+    YarnConfiguration conf = SliderUtils.createConfiguration()
+    shouldFail(BadCommandArgumentsException) {
+      ServiceLauncher launcher = launch(TestSliderClient,
+                                        conf,
+                                        [
+                                            ClientArgs.ACTION_INSTALL_KEYTAB,
+                                            ClientArgs.ARG_KEYTAB,
+                                            localKeytab.absolutePath])
+    }
+  }
+
+  @Test
+  public void testInstallKeytabWithNoKeytab() throws Throwable {
+    // create a mock keytab file
+    File localKeytab =
+      FileUtil.createLocalTempFile(FileUtils.getTempDirectory(), "test", true);
+    String contents = UUID.randomUUID().toString()
+    FileUtils.write(localKeytab, contents);
+    YarnConfiguration conf = SliderUtils.createConfiguration()
+    shouldFail(BadCommandArgumentsException) {
+      ServiceLauncher launcher = launch(TestSliderClient,
+                                        conf,
+                                        [
+                                            ClientArgs.ACTION_INSTALL_KEYTAB,
+                                            ClientArgs.ARG_FOLDER,
+                                            "testFolder"])
+    }
+  }
+
+  @Test
+  public void testInstallKeytabAllowingOverwrite() throws Throwable {
+    // create a mock keytab file
+    File localKeytab =
+      FileUtil.createLocalTempFile(FileUtils.getTempDirectory(), "test", true);
+    String contents = UUID.randomUUID().toString()
+    FileUtils.write(localKeytab, contents);
+    YarnConfiguration conf = SliderUtils.createConfiguration()
+    ServiceLauncher launcher = launch(TestSliderClient,
+                                      conf,
+                                      [
+                                          ClientArgs.ACTION_INSTALL_KEYTAB,
+                                          ClientArgs.ARG_KEYTAB,
+                                          localKeytab.absolutePath,
+                                          Arguments.ARG_FOLDER,
+                                          "testFolder"])
+    Path installedPath = new 
Path(testFileSystem.buildKeytabInstallationDirPath("testFolder"), 
localKeytab.getName())
+    File installedKeytab = new File(installedPath.toUri().path)
+    assert installedKeytab.exists()
+    assert 
FileUtils.readFileToString(installedKeytab).equals(FileUtils.readFileToString(localKeytab))
+    launcher = launch(TestSliderClient,
+                      conf,
+                      [
+                          ClientArgs.ACTION_INSTALL_KEYTAB,
+                          ClientArgs.ARG_KEYTAB,
+                          localKeytab.absolutePath,
+                          Arguments.ARG_FOLDER,
+                          "testFolder",
+                          Arguments.ARG_OVERWRITE]
+    )
+    assert installedKeytab.exists()
+    assert FileUtils.readFileToString(installedKeytab).equals(
+        FileUtils.readFileToString(localKeytab))
+  }
+
+  @Test
+  public void testInstallKeytabNotAllowingOverwrite() throws Throwable {
+    // create a mock keytab file
+    File localKeytab =
+      FileUtil.createLocalTempFile(FileUtils.getTempDirectory(), "test", true);
+    String contents = UUID.randomUUID().toString()
+    FileUtils.write(localKeytab, contents);
+    YarnConfiguration conf = SliderUtils.createConfiguration()
+    ServiceLauncher launcher = launch(TestSliderClient,
+                                      conf,
+                                      [
+                                          ClientArgs.ACTION_INSTALL_KEYTAB,
+                                          ClientArgs.ARG_KEYTAB,
+                                          localKeytab.absolutePath,
+                                          Arguments.ARG_FOLDER,
+                                          "testFolder"])
+    Path installedPath = new 
Path(testFileSystem.buildKeytabInstallationDirPath("testFolder"), 
localKeytab.getName())
+    File installedKeytab = new File(installedPath.toUri().path)
+    assert installedKeytab.exists()
+    assert 
FileUtils.readFileToString(installedKeytab).equals(FileUtils.readFileToString(localKeytab))
+    shouldFail(BadCommandArgumentsException) {
+      launcher = launch(TestSliderClient,
+                        conf,
+                        [
+                            ClientArgs.ACTION_INSTALL_KEYTAB,
+                            ClientArgs.ARG_KEYTAB,
+                            localKeytab.absolutePath,
+                            Arguments.ARG_FOLDER,
+                            "testFolder"])
+    }
+  }
+
+  @Test
+  public void testInstallKeytabWithMissingKeytab() throws Throwable {
+    // create a mock keytab file
+    YarnConfiguration conf = SliderUtils.createConfiguration()
+    shouldFail(BadCommandArgumentsException) {
+      ServiceLauncher launcher = launch(TestSliderClient,
+                                        conf,
+                                        [
+                                            ClientArgs.ACTION_INSTALL_KEYTAB,
+                                            ClientArgs.ARG_KEYTAB,
+                                            "HeyIDontExist.keytab",
+                                            Arguments.ARG_FOLDER,
+                                            "testFolder"])
+    }
+  }
+
+  static class TestSliderClient extends SliderClient {
+    public TestSliderClient() {
+      super()
+    }
+
+    @Override
+    protected void initHadoopBinding() throws IOException, SliderException {
+      sliderFileSystem = testFileSystem
+    }
+
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/c0a320db/slider-funtest/src/main/groovy/org/apache/slider/funtest/framework/CommandTestBase.groovy
----------------------------------------------------------------------
diff --git 
a/slider-funtest/src/main/groovy/org/apache/slider/funtest/framework/CommandTestBase.groovy
 
b/slider-funtest/src/main/groovy/org/apache/slider/funtest/framework/CommandTestBase.groovy
index 86d15d4..dc74d16 100644
--- 
a/slider-funtest/src/main/groovy/org/apache/slider/funtest/framework/CommandTestBase.groovy
+++ 
b/slider-funtest/src/main/groovy/org/apache/slider/funtest/framework/CommandTestBase.groovy
@@ -526,6 +526,9 @@ abstract class CommandTestBase extends SliderTestUtils {
         [ARG_COMP_OPT, SliderKeys.COMPONENT_AM, 
SliderXmlConfKeys.KEY_AM_LOGIN_KEYTAB_NAME],
         SLIDER_CONFIG.getTrimmed(SliderXmlConfKeys.KEY_AM_LOGIN_KEYTAB_NAME));
     maybeAddCommandOption(commands,
+        [ARG_COMP_OPT, SliderKeys.COMPONENT_AM,  
SliderXmlConfKeys.KEY_HDFS_KEYTAB_DIR ],
+        SLIDER_CONFIG.getTrimmed(SliderXmlConfKeys.KEY_HDFS_KEYTAB_DIR));
+    maybeAddCommandOption(commands,
         [ARG_COMP_OPT, SliderKeys.COMPONENT_AM, 
SliderXmlConfKeys.KEY_AM_KEYTAB_LOCAL_PATH],
         SLIDER_CONFIG.getTrimmed(SliderXmlConfKeys.KEY_AM_KEYTAB_LOCAL_PATH));
     maybeAddCommandOption(commands,

Reply via email to