You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@slider.apache.org by sm...@apache.org on 2014/09/11 04:54:26 UTC

git commit: SLIDER-422. Automatically upload slider-agent tarball to the app instance directory

Repository: incubator-slider
Updated Branches:
  refs/heads/feature/slider_install_package 809dc7860 -> fc3574e0f


SLIDER-422. Automatically upload slider-agent tarball to the app instance directory


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

Branch: refs/heads/feature/slider_install_package
Commit: fc3574e0fa4db8fdeb94f53c6cbcbfe85d373ae8
Parents: 809dc78
Author: Sumit Mohanty <sm...@hortonworks.com>
Authored: Wed Sep 10 19:54:19 2014 -0700
Committer: Sumit Mohanty <sm...@hortonworks.com>
Committed: Wed Sep 10 19:54:19 2014 -0700

----------------------------------------------------------------------
 slider-assembly/pom.xml                         | 20 ++++++++
 slider-assembly/src/assembly/slider-bin.xml     |  8 +++
 slider-core/pom.xml                             | 28 +++++++++++
 .../org/apache/slider/api/InternalKeys.java     |  6 ++-
 .../org/apache/slider/client/SliderClient.java  | 12 ++---
 .../org/apache/slider/common/SliderKeys.java    |  1 +
 .../apache/slider/common/tools/SliderUtils.java |  4 ++
 .../slider/core/build/InstanceBuilder.java      | 28 +++++------
 .../apache/slider/providers/ProviderUtils.java  | 33 ++++++++++--
 .../providers/agent/AgentClientProvider.java    | 41 +++++++--------
 .../providers/agent/AgentProviderService.java   | 19 ++++++-
 .../providers/agent/TestBuildBasicAgent.groovy  | 19 -------
 .../agent/TestAgentClientProvider.java          | 53 ++++++++++++++++++++
 13 files changed, 203 insertions(+), 69 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/fc3574e0/slider-assembly/pom.xml
----------------------------------------------------------------------
diff --git a/slider-assembly/pom.xml b/slider-assembly/pom.xml
index c2d0ecb..ac395fb 100644
--- a/slider-assembly/pom.xml
+++ b/slider-assembly/pom.xml
@@ -104,6 +104,26 @@
               </artifactItems>
             </configuration>
           </execution>
+          <execution>
+            <!-- copy in the agent tar file -->
+            <id>copy-to-lib</id>
+            <phase>package</phase>
+            <goals>
+              <goal>copy</goal>
+            </goals>
+            <configuration>
+              <artifactItems>
+                <artifactItem>
+                  <groupId>org.apache.slider</groupId>
+                  <artifactId>slider-agent</artifactId>
+                  <type>tar.gz</type>
+                  <overWrite>false</overWrite>
+                  <outputDirectory>${project.build.directory}/lib</outputDirectory>
+                  <destFileName>slider-agent.tar.gz</destFileName>
+                </artifactItem>
+              </artifactItems>
+            </configuration>
+          </execution>
         </executions>
       </plugin>
 

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/fc3574e0/slider-assembly/src/assembly/slider-bin.xml
----------------------------------------------------------------------
diff --git a/slider-assembly/src/assembly/slider-bin.xml b/slider-assembly/src/assembly/slider-bin.xml
index 6f3b021..c5611f8 100644
--- a/slider-assembly/src/assembly/slider-bin.xml
+++ b/slider-assembly/src/assembly/slider-bin.xml
@@ -59,6 +59,14 @@
 
     <fileSet>
       <directory>${project.build.directory}/agent</directory>
+      <outputDirectory>lib</outputDirectory>
+      <includes>
+        <include>slider-agent.tar.gz</include>
+      </includes>
+    </fileSet>
+
+    <fileSet>
+      <directory>${project.build.directory}/agent</directory>
       <outputDirectory>agent</outputDirectory>
       <includes>
         <include>slider-agent.tar.gz</include>

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/fc3574e0/slider-core/pom.xml
----------------------------------------------------------------------
diff --git a/slider-core/pom.xml b/slider-core/pom.xml
index 326af88..96b0f83 100644
--- a/slider-core/pom.xml
+++ b/slider-core/pom.xml
@@ -484,6 +484,34 @@
       <artifactId>jetty-sslengine</artifactId>
     </dependency>
 
+    <dependency>
+      <groupId>org.powermock</groupId>
+      <artifactId>powermock-core</artifactId>
+      <version>1.5</version>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.powermock</groupId>
+      <artifactId>powermock-reflect</artifactId>
+      <version>1.5</version>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.powermock</groupId>
+      <artifactId>powermock-api-easymock</artifactId>
+      <version>1.5</version>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.powermock</groupId>
+      <artifactId>powermock-module-junit4</artifactId>
+      <version>1.5</version>
+      <scope>test</scope>
+    </dependency>
+
   </dependencies>
 
 

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/fc3574e0/slider-core/src/main/java/org/apache/slider/api/InternalKeys.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/api/InternalKeys.java b/slider-core/src/main/java/org/apache/slider/api/InternalKeys.java
index b58f1c6..ffa3600 100644
--- a/slider-core/src/main/java/org/apache/slider/api/InternalKeys.java
+++ b/slider-core/src/main/java/org/apache/slider/api/InternalKeys.java
@@ -47,7 +47,11 @@ public interface InternalKeys {
   /**
    * internal temp directory: {@value}
    */
-  String INTERNAL_AM_TMP_DIR = "internal.tmp.dir";
+  String INTERNAL_AM_TMP_DIR = "internal.am.tmp.dir";
+  /**
+   * internal temp directory: {@value}
+   */
+  String INTERNAL_TMP_DIR = "internal.tmp.dir";
   /**
    * where a snapshot of the original conf dir is: {@value}
    */

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/fc3574e0/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 8d0978c..21d0ad0 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
@@ -764,8 +764,7 @@ public class SliderClient extends AbstractSliderLaunchedService implements RunSe
     builder.init(providerName, instanceDefinition);
     builder.propagateFilename();
     builder.propagatePrincipals();
-    builder.setImageDetails(buildInfo.getImage(), buildInfo.getAppHomeDir());
-
+    builder.setImageDetailsIfAvailable(buildInfo.getImage(), buildInfo.getAppHomeDir());
 
     String quorum = buildInfo.getZKhosts();
     if (SliderUtils.isUnset(quorum)) {
@@ -1009,10 +1008,6 @@ public class SliderClient extends AbstractSliderLaunchedService implements RunSe
         InternalKeys.INTERNAL_PROVIDER_NAME));
     // make sure the conf dir is valid;
     
-    // now build up the image path
-    // TODO: consider supporting apps that don't have an image path
-    Path imagePath =
-      SliderUtils.extractImagePath(sliderFileSystem, internalOptions);
     if (log.isDebugEnabled()) {
       log.debug(instanceDefinition.toString());
     }
@@ -1147,12 +1142,13 @@ public class SliderClient extends AbstractSliderLaunchedService implements RunSe
     );
 
 
-    // now add the image if it was set
+    // TODO: consider supporting apps that don't have an image path
+    Path imagePath =
+        SliderUtils.extractImagePath(sliderFileSystem, internalOptions);
     if (sliderFileSystem.maybeAddImagePath(localResources, imagePath)) {
       log.debug("Registered image path {}", imagePath);
     }
 
-
     // build the environment
     amLauncher.putEnv(
       SliderUtils.buildEnvMap(sliderAMResourceComponent));

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/fc3574e0/slider-core/src/main/java/org/apache/slider/common/SliderKeys.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/common/SliderKeys.java b/slider-core/src/main/java/org/apache/slider/common/SliderKeys.java
index 14528b1..ddb9ee0 100644
--- a/slider-core/src/main/java/org/apache/slider/common/SliderKeys.java
+++ b/slider-core/src/main/java/org/apache/slider/common/SliderKeys.java
@@ -144,6 +144,7 @@ public interface SliderKeys extends SliderXmlConfKeys {
   String SLIDER_JAR = "slider.jar";
   String JCOMMANDER_JAR = "jcommander.jar";
   String GSON_JAR = "gson.jar";
+  String AGENT_TAR = "slider-agent.tar.gz";
 
   String DEFAULT_JVM_HEAP = "256M";
   int DEFAULT_YARN_MEMORY = 256;

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/fc3574e0/slider-core/src/main/java/org/apache/slider/common/tools/SliderUtils.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/common/tools/SliderUtils.java b/slider-core/src/main/java/org/apache/slider/common/tools/SliderUtils.java
index 4cdc580..c44fba9 100644
--- a/slider-core/src/main/java/org/apache/slider/common/tools/SliderUtils.java
+++ b/slider-core/src/main/java/org/apache/slider/common/tools/SliderUtils.java
@@ -1354,6 +1354,10 @@ public final class SliderUtils {
     String appHomeOption =
         internalOptions.get(InternalKeys.INTERNAL_APPLICATION_HOME);
     if (!isUnset(imagePathOption)) {
+      if(!isUnset(appHomeOption)) {
+        throw new BadClusterStateException(
+            ErrorStrings.E_BOTH_IMAGE_AND_HOME_DIR_SPECIFIED);
+      }
       imagePath = fs.createPathThatMustExist(imagePathOption);
     } else {
       imagePath = null;

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/fc3574e0/slider-core/src/main/java/org/apache/slider/core/build/InstanceBuilder.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/core/build/InstanceBuilder.java b/slider-core/src/main/java/org/apache/slider/core/build/InstanceBuilder.java
index bfa7097..528a0c4 100644
--- a/slider-core/src/main/java/org/apache/slider/core/build/InstanceBuilder.java
+++ b/slider-core/src/main/java/org/apache/slider/core/build/InstanceBuilder.java
@@ -50,6 +50,7 @@ import java.io.IOException;
 import java.util.Map;
 
 import static org.apache.slider.api.OptionKeys.INTERNAL_AM_TMP_DIR;
+import static org.apache.slider.api.OptionKeys.INTERNAL_TMP_DIR;
 import static org.apache.slider.api.OptionKeys.INTERNAL_APPLICATION_HOME;
 import static org.apache.slider.api.OptionKeys.INTERNAL_APPLICATION_IMAGE_PATH;
 import static org.apache.slider.api.OptionKeys.INTERNAL_DATA_DIR_PATH;
@@ -132,6 +133,8 @@ public class InstanceBuilder {
 
     internalOps.set(INTERNAL_AM_TMP_DIR,
                     instancePaths.tmpPathAM.toUri());
+    internalOps.set(INTERNAL_TMP_DIR,
+                    instancePaths.tmpPath.toUri());
     internalOps.set(INTERNAL_SNAPSHOT_CONF_PATH,
                     instancePaths.snapshotConfPath.toUri());
     internalOps.set(INTERNAL_GENERATED_CONF_PATH,
@@ -147,36 +150,33 @@ public class InstanceBuilder {
 
   /**
    * Set up the image/app home path
-   * @param appImage path in the DFS to the tar file
+   * @param appImage   path in the DFS to the tar file
    * @param appHomeDir other strategy: home dir
-   * @throws BadConfigException if both or neither are found (its an xor)
+   * @throws BadConfigException if both are found
    */
-  public void setImageDetails(
-    Path appImage,
-    String appHomeDir) throws BadConfigException {
+  public void setImageDetailsIfAvailable(
+      Path appImage,
+      String appHomeDir) throws BadConfigException {
     boolean appHomeUnset = SliderUtils.isUnset(appHomeDir);
     // App home or image
     if (appImage != null) {
       if (!appHomeUnset) {
         // both args have been set
         throw new BadConfigException(
-          ErrorStrings.E_BOTH_IMAGE_AND_HOME_DIR_SPECIFIED);
+            ErrorStrings.E_BOTH_IMAGE_AND_HOME_DIR_SPECIFIED);
       }
       instanceDescription.getInternalOperations().set(INTERNAL_APPLICATION_IMAGE_PATH,
-                                               appImage.toUri());
+                                                      appImage.toUri());
     } else {
       // the alternative is app home, which now MUST be set
-      if (appHomeUnset) {
-        // both args have been set
-        throw new BadConfigException(ErrorStrings.E_NO_IMAGE_OR_HOME_DIR_SPECIFIED);
-          
+      if (!appHomeUnset) {
+        instanceDescription.getInternalOperations().set(INTERNAL_APPLICATION_HOME,
+                                                        appHomeDir);
       }
-      instanceDescription.getInternalOperations().set(INTERNAL_APPLICATION_HOME,
-                                               appHomeDir);
-
     }
   }
 
+
   /**
    * Propagate any critical principals from the current site config down to the HBase one.
    */

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/fc3574e0/slider-core/src/main/java/org/apache/slider/providers/ProviderUtils.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/providers/ProviderUtils.java b/slider-core/src/main/java/org/apache/slider/providers/ProviderUtils.java
index 4b8724a..464aba5 100644
--- a/slider-core/src/main/java/org/apache/slider/providers/ProviderUtils.java
+++ b/slider-core/src/main/java/org/apache/slider/providers/ProviderUtils.java
@@ -106,6 +106,30 @@ public class ProviderUtils implements RoleKeys {
       }
     }
   }
+
+  /**
+   * Add/overwrite the agent tarball (overwritten every time application is restarted)
+   * @param provider
+   * @param tarName
+   * @param sliderFileSystem
+   * @param agentDir
+   * @return
+   * @throws IOException
+   */
+  public static boolean addAgentTar(Object provider,
+                                    String tarName,
+                                    SliderFileSystem sliderFileSystem,
+                                    Path agentDir) throws
+  IOException {
+    File localFile = SliderUtils.findContainingJar(provider.getClass());
+    if(localFile != null) {
+      String parentDir = localFile.getParent();
+      Path agentTarPath = new Path(parentDir, tarName);
+      sliderFileSystem.getFileSystem().copyFromLocalFile(false, true, agentTarPath, agentDir);
+      return true;
+    }
+    return false;
+  }
   
   /**
    * Add a set of dependencies to the provider resources being built up,
@@ -252,7 +276,7 @@ public class ProviderUtils implements RoleKeys {
   /**
    * Propagate an option from the cluster specification option map
    * to the site XML map, using the site key for the name
-   * @param clusterSpec cluster specification
+   * @param global global config spec
    * @param optionKey key in the option map
    * @param sitexml  map for XML file to build up
    * @param siteKey key to assign the value to in the site XML
@@ -268,14 +292,13 @@ public class ProviderUtils implements RoleKeys {
 
   /**
    * Build the image dir. This path is relative and only valid at the far end
-   * @param clusterSpec cluster spec
+   * @param instanceDefinition instance definition
    * @param bindir bin subdir
    * @param script script in bin subdir
    * @return the path to the script
    * @throws FileNotFoundException if a file is not found, or it is not a directory* 
    */
-  public String buildPathToHomeDir(AggregateConf instanceDefinition
-                                   ,
+  public String buildPathToHomeDir(AggregateConf instanceDefinition,
                                   String bindir,
                                   String script) throws
                                                  FileNotFoundException,
@@ -327,7 +350,7 @@ public class ProviderUtils implements RoleKeys {
   
   /**
    * Build the image dir. This path is relative and only valid at the far end
-   * @param internal internal options
+   * @param instance instance options
    * @param bindir bin subdir
    * @param script script in bin subdir
    * @return the path to the script

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/fc3574e0/slider-core/src/main/java/org/apache/slider/providers/agent/AgentClientProvider.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/providers/agent/AgentClientProvider.java b/slider-core/src/main/java/org/apache/slider/providers/agent/AgentClientProvider.java
index 3a1ee76..4c2f213 100644
--- a/slider-core/src/main/java/org/apache/slider/providers/agent/AgentClientProvider.java
+++ b/slider-core/src/main/java/org/apache/slider/providers/agent/AgentClientProvider.java
@@ -164,32 +164,33 @@ public class AgentClientProvider extends AbstractClientProvider
     if (!"zip".equalsIgnoreCase(extension)) {
       throw new BadConfigException("App definition must be packaged as a .zip file. File provided is " + appDef);
     }
-
-    String appHome = instanceDefinition.getAppConfOperations().
-        getGlobalOptions().get(AgentKeys.PACKAGE_PATH);
-    String agentImage = instanceDefinition.getInternalOperations().
-        get(InternalKeys.INTERNAL_APPLICATION_IMAGE_PATH);
-
-    if (SliderUtils.isUnset(appHome) && SliderUtils.isUnset(agentImage)) {
-      throw new BadConfigException("Either agent package path " +
-                                   AgentKeys.PACKAGE_PATH + " or image root " +
-                                   InternalKeys.INTERNAL_APPLICATION_IMAGE_PATH
-                                   + " must be provided.");
-    }
   }
 
   @Override
   public void prepareAMAndConfigForLaunch(SliderFileSystem fileSystem,
-      Configuration serviceConf,
-      AbstractLauncher launcher,
-      AggregateConf instanceDescription,
-      Path snapshotConfDirPath,
-      Path generatedConfDirPath,
-      Configuration clientConfExtras,
-      String libdir,
-      Path tempPath, boolean miniClusterTestRun) throws
+                                          Configuration serviceConf,
+                                          AbstractLauncher launcher,
+                                          AggregateConf instanceDefinition,
+                                          Path snapshotConfDirPath,
+                                          Path generatedConfDirPath,
+                                          Configuration clientConfExtras,
+                                          String libdir,
+                                          Path tempPath,
+                                          boolean miniClusterTestRun) throws
       IOException,
       SliderException {
+    String agentImage = instanceDefinition.getInternalOperations().
+        get(InternalKeys.INTERNAL_APPLICATION_IMAGE_PATH);
+    if (SliderUtils.isUnset(agentImage)) {
+      Path agentPath = new Path(tempPath.getParent(), AgentKeys.PROVIDER_AGENT);
+      log.info("Automatically uploading the agent tarball at {}", agentPath);
+      fileSystem.getFileSystem().mkdirs(agentPath);
+      if(ProviderUtils.addAgentTar(this, AGENT_TAR, fileSystem, agentPath)) {
+        instanceDefinition.getInternalOperations().set(
+            InternalKeys.INTERNAL_APPLICATION_IMAGE_PATH,
+            new Path(agentPath, AGENT_TAR).toUri());
+      }
+    }
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/fc3574e0/slider-core/src/main/java/org/apache/slider/providers/agent/AgentProviderService.java
----------------------------------------------------------------------
diff --git a/slider-core/src/main/java/org/apache/slider/providers/agent/AgentProviderService.java b/slider-core/src/main/java/org/apache/slider/providers/agent/AgentProviderService.java
index 9d1df61..bb98588 100644
--- a/slider-core/src/main/java/org/apache/slider/providers/agent/AgentProviderService.java
+++ b/slider-core/src/main/java/org/apache/slider/providers/agent/AgentProviderService.java
@@ -279,11 +279,26 @@ public class AgentProviderService extends AbstractProviderService implements
     launcher.setEnv(PYTHONPATH, pythonPath);
     log.info("PYTHONPATH set to {}", pythonPath);
 
+    Path agentImagePath = null;
     String agentImage = instanceDefinition.getInternalOperations().
         get(InternalKeys.INTERNAL_APPLICATION_IMAGE_PATH);
-    if (agentImage != null) {
-      LocalResource agentImageRes = fileSystem.createAmResource(new Path(agentImage), LocalResourceType.ARCHIVE);
+    if (SliderUtils.isUnset(agentImage)) {
+      agentImagePath =
+          new Path(new Path(new Path(instanceDefinition.getInternalOperations().get(InternalKeys.INTERNAL_TMP_DIR),
+                                     container.getId().getApplicationAttemptId().getApplicationId().toString()),
+                            AgentKeys.PROVIDER_AGENT),
+                   SliderKeys.AGENT_TAR);
+    } else {
+       agentImagePath = new Path(agentImage);
+    }
+
+    // TODO: throw exception when agent tarball is not available
+
+    if (fileSystem.getFileSystem().exists(agentImagePath)) {
+      LocalResource agentImageRes = fileSystem.createAmResource(agentImagePath, LocalResourceType.ARCHIVE);
       launcher.addLocalResource(AgentKeys.AGENT_INSTALL_DIR, agentImageRes);
+    } else {
+      log.error("Required agent image slider-agent.tar.gz is unavailable.");
     }
 
     log.info("Using {} for agent.", scriptPath);

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/fc3574e0/slider-core/src/test/groovy/org/apache/slider/providers/agent/TestBuildBasicAgent.groovy
----------------------------------------------------------------------
diff --git a/slider-core/src/test/groovy/org/apache/slider/providers/agent/TestBuildBasicAgent.groovy b/slider-core/src/test/groovy/org/apache/slider/providers/agent/TestBuildBasicAgent.groovy
index 99f7f49..1b5269a 100644
--- a/slider-core/src/test/groovy/org/apache/slider/providers/agent/TestBuildBasicAgent.groovy
+++ b/slider-core/src/test/groovy/org/apache/slider/providers/agent/TestBuildBasicAgent.groovy
@@ -367,25 +367,6 @@ class TestBuildBasicAgent extends AgentTestBase {
         false)
 
     try {
-      def badArgs1 = "test_bad_agent_args-1"
-      buildAgentCluster(badArgs1,
-          [:],
-          [
-              ARG_OPTION, CONTROLLER_URL, "http://localhost",
-              ARG_OPTION, APP_DEF, "file://" + getAppDef().absolutePath,
-              ARG_OPTION, AGENT_CONF, "file://" + getAgentConf().absolutePath,
-              ARG_RESOURCES, TEST_FILES + "good/resources.json",
-              ARG_TEMPLATE, TEST_FILES + "good/appconf.json"
-          ],
-          true, false,
-          false)
-      failWithBuildSucceeding(badArgs1, "missing package home or image path")
-    } catch (BadConfigException expected) {
-      log.info("Expected failure.", expected)
-      assert expected.message.contains("Either agent package path agent.package.root or image root internal.application.image.path must be provided")
-    }
-
-    try {
       def badArgs1 = "test_bad_agent_args-2"
       buildAgentCluster(badArgs1,
           [:],

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/fc3574e0/slider-core/src/test/java/org/apache/slider/providers/agent/TestAgentClientProvider.java
----------------------------------------------------------------------
diff --git a/slider-core/src/test/java/org/apache/slider/providers/agent/TestAgentClientProvider.java b/slider-core/src/test/java/org/apache/slider/providers/agent/TestAgentClientProvider.java
index 4cb35aa..1ad59e3 100644
--- a/slider-core/src/test/java/org/apache/slider/providers/agent/TestAgentClientProvider.java
+++ b/slider-core/src/test/java/org/apache/slider/providers/agent/TestAgentClientProvider.java
@@ -18,22 +18,38 @@ package org.apache.slider.providers.agent;
 
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.fs.Path;
+import org.apache.slider.api.InternalKeys;
 import org.apache.slider.common.tools.SliderFileSystem;
 import org.apache.slider.core.conf.AggregateConf;
+import org.apache.slider.core.conf.ConfTree;
 import org.apache.slider.core.exceptions.BadConfigException;
+import org.apache.slider.providers.ProviderUtils;
 import org.apache.slider.tools.TestUtility;
+import org.easymock.EasyMock;
 import org.junit.Assert;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.powermock.api.easymock.PowerMock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.util.Set;
 
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.easymock.EasyMock.anyObject;
+
 /**
  *
  */
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(ProviderUtils.class)
 public class TestAgentClientProvider {
   protected static final Logger log =
       LoggerFactory.getLogger(TestAgentClientProvider.class);
@@ -74,4 +90,41 @@ public class TestAgentClientProvider {
       Assert.assertTrue(e.getMessage().contains("Application definition must be provided"));
     }
   }
+
+  @Test
+  public void testPrepareAMAndConfigForLaunch() throws Exception {
+    AgentClientProvider provider = new AgentClientProvider(null);
+    SliderFileSystem sfs = PowerMock.createMock(SliderFileSystem.class);
+    FileSystem fs = PowerMock.createMock(FileSystem.class);
+    Configuration serviceConf = PowerMock.createMock(Configuration.class);
+    PowerMock.mockStatic(ProviderUtils.class);
+
+    expect(sfs.getFileSystem()).andReturn(fs);
+    expect(fs.mkdirs(anyObject(Path.class))).andReturn(true);
+    expect(ProviderUtils.addAgentTar(
+        anyObject(), anyObject(String.class), anyObject(SliderFileSystem.class), anyObject(Path.class))).
+        andReturn(true);
+
+    AggregateConf instanceDefinition = new AggregateConf();
+    ConfTree tree = new ConfTree();
+    tree.global.put(InternalKeys.INTERNAL_APPLICATION_IMAGE_PATH, ".");
+    instanceDefinition.setInternal(tree);
+
+    PowerMock.replay(sfs, fs, serviceConf, ProviderUtils.class);
+
+    provider.prepareAMAndConfigForLaunch(
+        sfs, serviceConf, null, instanceDefinition, null,
+        null, null, null, null, false);
+
+    Assert.assertTrue(tree.global.containsKey(InternalKeys.INTERNAL_APPLICATION_IMAGE_PATH));
+    tree.global.remove(InternalKeys.INTERNAL_APPLICATION_IMAGE_PATH);
+
+    // Verify that slider-agent.tar.gz got added
+    Path tempPath = new Path(".", "temp");
+    provider.prepareAMAndConfigForLaunch(
+        sfs, serviceConf, null, instanceDefinition, null,
+        null, null, null, tempPath, false);
+    PowerMock.verify(sfs, fs, ProviderUtils.class);
+    Assert.assertTrue(tree.global.containsKey(InternalKeys.INTERNAL_APPLICATION_IMAGE_PATH));
+  }
 }