Browse Source

AMBARI-6040. Modify configuration with Ambari Shell. (Janos Matyas and Krisztian Horvath via yusaku)

Yusaku Sako 10 years ago
parent
commit
f3345be0b9
16 changed files with 490 additions and 75 deletions
  1. 4 3
      ambari-client/groovy-client/src/main/groovy/org/apache/ambari/groovy/client/AmbariClient.groovy
  2. 11 0
      ambari-shell/ambari-groovy-shell/pom.xml
  3. 163 0
      ambari-shell/ambari-groovy-shell/src/main/java/org/apache/ambari/shell/commands/ConfigCommands.java
  4. 34 0
      ambari-shell/ambari-groovy-shell/src/main/java/org/apache/ambari/shell/completion/AbstractCompletion.java
  5. 2 7
      ambari-shell/ambari-groovy-shell/src/main/java/org/apache/ambari/shell/completion/Blueprint.java
  6. 29 0
      ambari-shell/ambari-groovy-shell/src/main/java/org/apache/ambari/shell/completion/ConfigType.java
  7. 2 7
      ambari-shell/ambari-groovy-shell/src/main/java/org/apache/ambari/shell/completion/Host.java
  8. 5 7
      ambari-shell/ambari-groovy-shell/src/main/java/org/apache/ambari/shell/completion/Service.java
  9. 6 0
      ambari-shell/ambari-groovy-shell/src/main/java/org/apache/ambari/shell/configuration/ConverterConfiguration.java
  10. 63 0
      ambari-shell/ambari-groovy-shell/src/main/java/org/apache/ambari/shell/converter/AbstractConverter.java
  11. 4 17
      ambari-shell/ambari-groovy-shell/src/main/java/org/apache/ambari/shell/converter/BlueprintConverter.java
  12. 45 0
      ambari-shell/ambari-groovy-shell/src/main/java/org/apache/ambari/shell/converter/ConfigTypeConverter.java
  13. 4 17
      ambari-shell/ambari-groovy-shell/src/main/java/org/apache/ambari/shell/converter/HostConverter.java
  14. 7 17
      ambari-shell/ambari-groovy-shell/src/main/java/org/apache/ambari/shell/converter/ServiceConverter.java
  15. 98 0
      ambari-shell/ambari-groovy-shell/src/test/java/org/apache/ambari/shell/commands/ConfigCommandsTest.java
  16. 13 0
      ambari-shell/ambari-groovy-shell/src/test/resources/core-site.xml

+ 4 - 3
ambari-client/groovy-client/src/main/groovy/org/apache/ambari/groovy/client/AmbariClient.groovy

@@ -443,7 +443,7 @@ class AmbariClient {
 
   /**
    * Adds a blueprint with the desired configurations.
-   * 
+   *
    * @param json blueprint to be added
    * @param configurations blueprint will be extended with these configurations
    * @return the extended blueprint as json
@@ -752,11 +752,12 @@ class AmbariClient {
    *
    * @return a Map with entries of format <servicename, Map<property, value>>
    */
-  def Map<String, Map<String, String>> getServiceConfigMap() {
+  def Map<String, Map<String, String>> getServiceConfigMap(String type = "") {
     def Map<String, Integer> serviceToTags = new HashMap<>()
 
     //get services and last versions configurations
-    Map<String, ?> configsResourceRequestMap = getResourceRequestMap("clusters/${getClusterName()}/configurations", [:])
+    def path = "clusters/${getClusterName()}/configurations"
+    Map<String, ?> configsResourceRequestMap = getResourceRequestMap(path, type ? ["type": type] : [:])
     def rawConfigs = getSlurpedResource(configsResourceRequestMap)
 
     rawConfigs?.items.collect { object ->

+ 11 - 0
ambari-shell/ambari-groovy-shell/pom.xml

@@ -71,6 +71,16 @@
       <groupId>org.codehaus.jackson</groupId>
       <artifactId>jackson-mapper-asl</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.apache.hadoop</groupId>
+      <artifactId>hadoop-common</artifactId>
+      <version>2.4.1</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.httpcomponents</groupId>
+      <artifactId>httpclient</artifactId>
+      <version>4.2.5</version>
+    </dependency>
   </dependencies>
   <build>
     <plugins>
@@ -87,6 +97,7 @@
             <exclude>src/test/resources/2columns</exclude>
             <exclude>src/test/resources/3columns</exclude>
             <exclude>src/test/resources/testBlueprint.json</exclude>
+            <exclude>src/test/resources/core-site.xml</exclude>
           </excludes>
         </configuration>
         <executions>

+ 163 - 0
ambari-shell/ambari-groovy-shell/src/main/java/org/apache/ambari/shell/commands/ConfigCommands.java

@@ -0,0 +1,163 @@
+/**
+ * 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.ambari.shell.commands;
+
+import static org.apache.ambari.shell.support.TableRenderer.renderSingleMap;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.ambari.groovy.client.AmbariClient;
+import org.apache.ambari.shell.completion.ConfigType;
+import org.apache.ambari.shell.model.AmbariContext;
+import org.apache.hadoop.conf.Configuration;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.shell.core.CommandMarker;
+import org.springframework.shell.core.annotation.CliAvailabilityIndicator;
+import org.springframework.shell.core.annotation.CliCommand;
+import org.springframework.shell.core.annotation.CliOption;
+import org.springframework.stereotype.Component;
+
+/**
+ * Configuration related commands used in the shell.
+ *
+ * @see org.apache.ambari.groovy.client.AmbariClient
+ */
+@Component
+public class ConfigCommands implements CommandMarker {
+
+  private AmbariClient client;
+  private AmbariContext context;
+
+  @Autowired
+  public ConfigCommands(AmbariClient client, AmbariContext context) {
+    this.client = client;
+    this.context = context;
+  }
+
+  /**
+   * Checks whether the configuration show command is available or not.
+   *
+   * @return true if available false otherwise
+   */
+  @CliAvailabilityIndicator("configuration show")
+  public boolean isConfigShowCommandAvailable() {
+    return context.isConnectedToCluster();
+  }
+
+  /**
+   * Prints the desired configuration.
+   */
+  @CliCommand(value = "configuration show", help = "Prints the desired configuration")
+  public String showConfig(@CliOption(key = "type", mandatory = true, help = "Type of the configuration") ConfigType configType) {
+    String configTypeName = configType.getName();
+    Map<String, Map<String, String>> configMap = client.getServiceConfigMap(configTypeName);
+    return renderSingleMap(configMap.get(configTypeName), "KEY", "VALUE");
+  }
+
+  /**
+   * Checks whether the configuration set command is available or not.
+   *
+   * @return true if available false otherwise
+   */
+  @CliAvailabilityIndicator("configuration set")
+  public boolean isConfigSetCommandAvailable() {
+    return context.isConnectedToCluster();
+  }
+
+  /**
+   * Sets the desired configuration.
+   */
+  @CliCommand(value = "configuration set", help = "Sets the desired configuration")
+  public String setConfig(@CliOption(key = "type", mandatory = true, help = "Type of the configuration") ConfigType configType,
+    @CliOption(key = "url", help = "URL of the config") String url,
+    @CliOption(key = "file", help = "File of the config") File file) throws IOException {
+    Configuration configuration = new Configuration(false);
+    if (file == null) {
+      configuration.addResource(new URL(url));
+    } else {
+      configuration.addResource(new FileInputStream(file));
+    }
+    Map<String, String> config = new HashMap<String, String>();
+    Iterator<Map.Entry<String, String>> iterator = configuration.iterator();
+    while (iterator.hasNext()) {
+      Map.Entry<String, String> entry = iterator.next();
+      config.put(entry.getKey(), entry.getValue());
+    }
+    client.modifyConfiguration(configType.getName(), config);
+    return "Restart is required!\n" + renderSingleMap(config, "KEY", "VALUE");
+  }
+
+  /**
+   * Checks whether the configuration modify command is available or not.
+   *
+   * @return true if available false otherwise
+   */
+  @CliAvailabilityIndicator("configuration modify")
+  public boolean isConfigModifyCommandAvailable() {
+    return context.isConnectedToCluster();
+  }
+
+  /**
+   * Modify the desired configuration.
+   */
+  @CliCommand(value = "configuration modify", help = "Modify the desired configuration")
+  public String modifyConfig(@CliOption(key = "type", mandatory = true, help = "Type of the configuration") ConfigType configType,
+    @CliOption(key = "key", mandatory = true, help = "Key of the config") String key,
+    @CliOption(key = "value", mandatory = true, help = "Value of the config") String value) {
+    String configTypeName = configType.getName();
+    Map<String, String> config = client.getServiceConfigMap(configTypeName).get(configTypeName);
+    config.put(key, value);
+    client.modifyConfiguration(configTypeName, config);
+    return "Restart is required!\n" + renderSingleMap(config, "KEY", "VALUE");
+  }
+
+  /**
+   * Checks whether the configuration modify command is available or not.
+   *
+   * @return true if available false otherwise
+   */
+  @CliAvailabilityIndicator("configuration download")
+  public boolean isConfigDownloadCommandAvailable() {
+    return context.isConnectedToCluster();
+  }
+
+  /**
+   * Modify the desired configuration.
+   */
+  @CliCommand(value = "configuration download", help = "Downloads the desired configuration")
+  public String downloadConfig(@CliOption(key = "type", mandatory = true, help = "Type of the configuration") ConfigType configType) throws IOException {
+    String configTypeName = configType.getName();
+    Map<String, String> config = client.getServiceConfigMap(configTypeName).get(configTypeName);
+    Configuration configuration = new Configuration(false);
+    for (String key : config.keySet()) {
+      configuration.set(key, config.get(key));
+    }
+    File file = new File(configTypeName);
+    FileWriter writer = new FileWriter(file);
+    configuration.writeXml(writer);
+    return "Configuration saved to: " + file.getAbsolutePath();
+  }
+
+}

+ 34 - 0
ambari-shell/ambari-groovy-shell/src/main/java/org/apache/ambari/shell/completion/AbstractCompletion.java

@@ -0,0 +1,34 @@
+/**
+ * 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.ambari.shell.completion;
+
+/**
+ * Base class for completions.
+ */
+public abstract class AbstractCompletion {
+
+  private final String name;
+
+  protected AbstractCompletion(String name) {
+    this.name = name;
+  }
+
+  public String getName() {
+    return name;
+  }
+}

+ 2 - 7
ambari-shell/ambari-groovy-shell/src/main/java/org/apache/ambari/shell/completion/Blueprint.java

@@ -20,15 +20,10 @@ package org.apache.ambari.shell.completion;
 /**
  * Wrapper class for TAB completion to blueprint names.
  */
-public class Blueprint {
-
-  private final String name;
+public class Blueprint extends AbstractCompletion {
 
   public Blueprint(String name) {
-    this.name = name;
+    super(name);
   }
 
-  public String getName() {
-    return name;
-  }
 }

+ 29 - 0
ambari-shell/ambari-groovy-shell/src/main/java/org/apache/ambari/shell/completion/ConfigType.java

@@ -0,0 +1,29 @@
+/**
+ * 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.ambari.shell.completion;
+
+/**
+ * Wrapper class for TAB completion to config names.
+ */
+public class ConfigType extends AbstractCompletion {
+
+  public ConfigType(String name) {
+    super(name);
+  }
+
+}

+ 2 - 7
ambari-shell/ambari-groovy-shell/src/main/java/org/apache/ambari/shell/completion/Host.java

@@ -20,15 +20,10 @@ package org.apache.ambari.shell.completion;
 /**
  * Wrapper class for TAB completion to host names.
  */
-public class Host {
-
-  private final String name;
+public class Host extends AbstractCompletion {
 
   public Host(String name) {
-    this.name = name;
+    super(name);
   }
 
-  public String getName() {
-    return name;
-  }
 }

+ 5 - 7
ambari-shell/ambari-groovy-shell/src/main/java/org/apache/ambari/shell/completion/Service.java

@@ -17,15 +17,13 @@
  */
 package org.apache.ambari.shell.completion;
 
-public class Service {
-
-  private final String name;
+/**
+ * Wrapper class for TAB completion to service names.
+ */
+public class Service extends AbstractCompletion {
 
   public Service(String name) {
-    this.name = name;
+    super(name);
   }
 
-  public String getName() {
-    return name;
-  }
 }

+ 6 - 0
ambari-shell/ambari-groovy-shell/src/main/java/org/apache/ambari/shell/configuration/ConverterConfiguration.java

@@ -19,6 +19,7 @@ package org.apache.ambari.shell.configuration;
 
 import org.apache.ambari.groovy.client.AmbariClient;
 import org.apache.ambari.shell.converter.BlueprintConverter;
+import org.apache.ambari.shell.converter.ConfigTypeConverter;
 import org.apache.ambari.shell.converter.HostConverter;
 import org.apache.ambari.shell.converter.ServiceConverter;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -145,4 +146,9 @@ public class ConverterConfiguration {
   Converter serviceConverter() {
     return new ServiceConverter(client);
   }
+
+  @Bean
+  Converter configConverter() {
+    return new ConfigTypeConverter(client);
+  }
 }

+ 63 - 0
ambari-shell/ambari-groovy-shell/src/main/java/org/apache/ambari/shell/converter/AbstractConverter.java

@@ -0,0 +1,63 @@
+/**
+ * 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.ambari.shell.converter;
+
+import java.lang.reflect.Constructor;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.ambari.groovy.client.AmbariClient;
+import org.apache.ambari.shell.completion.AbstractCompletion;
+import org.springframework.shell.core.Completion;
+import org.springframework.shell.core.Converter;
+
+/**
+ * Base class of completion converters.
+ *
+ * @param <T> completion class type
+ */
+public abstract class AbstractConverter<T extends AbstractCompletion> implements Converter<T> {
+
+  private AmbariClient client;
+
+  protected AbstractConverter(AmbariClient client) {
+    this.client = client;
+  }
+
+  @Override
+  public T convertFromText(String value, Class<?> clazz, String optionContext) {
+    try {
+      Constructor<?> constructor = clazz.getDeclaredConstructor(String.class);
+      return (T) constructor.newInstance(value);
+    } catch (Exception e) {
+      return null;
+    }
+  }
+
+  public boolean getAllPossibleValues(List<Completion> completions, Collection<String> values) {
+    for (String value : values) {
+      completions.add(new Completion(value));
+    }
+    return true;
+  }
+
+  public AmbariClient getClient() {
+    return client;
+  }
+
+}

+ 4 - 17
ambari-shell/ambari-groovy-shell/src/main/java/org/apache/ambari/shell/converter/BlueprintConverter.java

@@ -18,41 +18,28 @@
 package org.apache.ambari.shell.converter;
 
 import java.util.List;
-import java.util.Set;
 
 import org.apache.ambari.groovy.client.AmbariClient;
 import org.apache.ambari.shell.completion.Blueprint;
 import org.springframework.shell.core.Completion;
-import org.springframework.shell.core.Converter;
 import org.springframework.shell.core.MethodTarget;
 
 /**
  * Converter used to complete blueprint names.
  */
-public class BlueprintConverter implements Converter<Blueprint> {
-
-  private AmbariClient client;
+public class BlueprintConverter extends AbstractConverter<Blueprint> {
 
   public BlueprintConverter(AmbariClient client) {
-    this.client = client;
+    super(client);
   }
 
   @Override
-  public boolean supports(Class<?> type, String optionContext) {
+  public boolean supports(Class<?> type, String s) {
     return Blueprint.class.isAssignableFrom(type);
   }
 
-  @Override
-  public Blueprint convertFromText(String value, Class<?> targetType, String optionContext) {
-    return new Blueprint(value);
-  }
-
   @Override
   public boolean getAllPossibleValues(List<Completion> completions, Class<?> targetType, String existingData, String optionContext, MethodTarget target) {
-    Set<String> blueprints = client.getBlueprintsMap().keySet();
-    for (String blueprint : blueprints) {
-      completions.add(new Completion(blueprint));
-    }
-    return true;
+    return getAllPossibleValues(completions, getClient().getBlueprintsMap().keySet());
   }
 }

+ 45 - 0
ambari-shell/ambari-groovy-shell/src/main/java/org/apache/ambari/shell/converter/ConfigTypeConverter.java

@@ -0,0 +1,45 @@
+/**
+ * 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.ambari.shell.converter;
+
+import java.util.List;
+
+import org.apache.ambari.groovy.client.AmbariClient;
+import org.apache.ambari.shell.completion.ConfigType;
+import org.springframework.shell.core.Completion;
+import org.springframework.shell.core.MethodTarget;
+
+/**
+ * Converter used to complete config names.
+ */
+public class ConfigTypeConverter extends AbstractConverter<ConfigType> {
+
+  public ConfigTypeConverter(AmbariClient client) {
+    super(client);
+  }
+
+  @Override
+  public boolean supports(Class<?> type, String s) {
+    return ConfigType.class.isAssignableFrom(type);
+  }
+
+  @Override
+  public boolean getAllPossibleValues(List<Completion> completions, Class<?> aClass, String s, String s2, MethodTarget methodTarget) {
+    return getAllPossibleValues(completions, getClient().getServiceConfigMap().keySet());
+  }
+}

+ 4 - 17
ambari-shell/ambari-groovy-shell/src/main/java/org/apache/ambari/shell/converter/HostConverter.java

@@ -18,41 +18,28 @@
 package org.apache.ambari.shell.converter;
 
 import java.util.List;
-import java.util.Set;
 
 import org.apache.ambari.groovy.client.AmbariClient;
 import org.apache.ambari.shell.completion.Host;
 import org.springframework.shell.core.Completion;
-import org.springframework.shell.core.Converter;
 import org.springframework.shell.core.MethodTarget;
 
 /**
  * Converter used to complete host names.
  */
-public class HostConverter implements Converter<Host> {
-
-  private AmbariClient client;
+public class HostConverter extends AbstractConverter<Host> {
 
   public HostConverter(AmbariClient client) {
-    this.client = client;
+    super(client);
   }
 
   @Override
-  public boolean supports(Class<?> type, String optionContext) {
+  public boolean supports(Class<?> type, String s) {
     return Host.class.isAssignableFrom(type);
   }
 
-  @Override
-  public Host convertFromText(String value, Class<?> targetType, String optionContext) {
-    return new Host(value);
-  }
-
   @Override
   public boolean getAllPossibleValues(List<Completion> completions, Class<?> targetType, String existingData, String optionContext, MethodTarget target) {
-    Set<String> hosts = client.getHostNames().keySet();
-    for (String host : hosts) {
-      completions.add(new Completion(host));
-    }
-    return true;
+    return getAllPossibleValues(completions, getClient().getHostNames().keySet());
   }
 }

+ 7 - 17
ambari-shell/ambari-groovy-shell/src/main/java/org/apache/ambari/shell/converter/ServiceConverter.java

@@ -18,38 +18,28 @@
 package org.apache.ambari.shell.converter;
 
 import java.util.List;
-import java.util.Set;
 
 import org.apache.ambari.groovy.client.AmbariClient;
 import org.apache.ambari.shell.completion.Service;
 import org.springframework.shell.core.Completion;
-import org.springframework.shell.core.Converter;
 import org.springframework.shell.core.MethodTarget;
 
-public class ServiceConverter implements Converter<Service> {
-
-  private AmbariClient client;
+/**
+ * Converter used to complete service names.
+ */
+public class ServiceConverter extends AbstractConverter<Service> {
 
   public ServiceConverter(AmbariClient client) {
-    this.client = client;
+    super(client);
   }
 
   @Override
-  public boolean supports(Class<?> type, String optionContext) {
+  public boolean supports(Class<?> type, String s) {
     return Service.class.isAssignableFrom(type);
   }
 
-  @Override
-  public Service convertFromText(String value, Class<?> targetType, String optionContext) {
-    return new Service(value);
-  }
-
   @Override
   public boolean getAllPossibleValues(List<Completion> completions, Class<?> targetType, String existingData, String optionContext, MethodTarget target) {
-    Set<String> services = client.getServicesMap().keySet();
-    for (String service : services) {
-      completions.add(new Completion(service));
-    }
-    return true;
+    return getAllPossibleValues(completions, getClient().getServicesMap().keySet());
   }
 }

+ 98 - 0
ambari-shell/ambari-groovy-shell/src/test/java/org/apache/ambari/shell/commands/ConfigCommandsTest.java

@@ -0,0 +1,98 @@
+/**
+ * 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.ambari.shell.commands;
+
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.ambari.groovy.client.AmbariClient;
+import org.apache.ambari.shell.completion.ConfigType;
+import org.apache.ambari.shell.model.AmbariContext;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+
+@RunWith(MockitoJUnitRunner.class)
+public class ConfigCommandsTest {
+
+  private static final String CORE_SITE = "core-site";
+
+  @InjectMocks
+  private ConfigCommands configCommands;
+
+  @Mock
+  private AmbariClient client;
+  @Mock
+  private AmbariContext context;
+
+  @Test
+  public void testShowConfig() {
+    ConfigType configType = mock(ConfigType.class);
+    Map<String, Map<String, String>> mockResult = mock(Map.class);
+    when(configType.getName()).thenReturn(CORE_SITE);
+    when(client.getServiceConfigMap(anyString())).thenReturn(mockResult);
+    when(mockResult.get(CORE_SITE)).thenReturn(new HashMap<String, String>());
+
+    configCommands.showConfig(configType);
+
+    verify(client).getServiceConfigMap(CORE_SITE);
+  }
+
+  @Test
+  public void testSetConfigForFile() throws IOException {
+    ConfigType configType = mock(ConfigType.class);
+    File file = new File("src/test/resources/core-site.xml");
+    when(configType.getName()).thenReturn(CORE_SITE);
+
+    configCommands.setConfig(configType, "", file);
+
+    Map<String, String> config = new HashMap<String, String>();
+    config.put("fs.trash.interval", "350");
+    config.put("ipc.client.connection.maxidletime", "30000");
+    verify(client).modifyConfiguration(CORE_SITE, config);
+  }
+
+  @Test
+  public void testModifyConfig() throws IOException {
+    ConfigType configType = mock(ConfigType.class);
+    Map<String, Map<String, String>> mockResult = mock(Map.class);
+    Map<String, String> config = new HashMap<String, String>();
+    config.put("fs.trash.interval", "350");
+    config.put("ipc.client.connection.maxidletime", "30000");
+    when(configType.getName()).thenReturn(CORE_SITE);
+    when(mockResult.get(CORE_SITE)).thenReturn(config);
+    when(client.getServiceConfigMap(CORE_SITE)).thenReturn(mockResult);
+
+    configCommands.modifyConfig(configType, "fs.trash.interval", "510");
+
+    Map<String, String> config2 = new HashMap<String, String>();
+    config2.put("fs.trash.interval", "510");
+    config2.put("ipc.client.connection.maxidletime", "30000");
+    verify(client).modifyConfiguration(CORE_SITE, config2);
+  }
+
+}

+ 13 - 0
ambari-shell/ambari-groovy-shell/src/test/resources/core-site.xml

@@ -0,0 +1,13 @@
+<configuration>
+
+  <property>
+    <name>fs.trash.interval</name>
+    <value>350</value>
+  </property>
+
+  <property>
+    <name>ipc.client.connection.maxidletime</name>
+    <value>30000</value>
+  </property>
+
+</configuration>