Browse Source

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

Yusaku Sako 10 năm trước cách đây
mục cha
commit
f3345be0b9
16 tập tin đã thay đổi với 490 bổ sung75 xóa
  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>