You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by ji...@apache.org on 2017/08/29 16:30:34 UTC

[17/25] geode git commit: GEODE-3436: Restore refactoring of ConfigCommands

GEODE-3436: Restore refactoring of ConfigCommands

* See initial commit GEODE-3254 (97c4e9a59f17c7bc914e39dd048b0a4cd96293c4)


Project: http://git-wip-us.apache.org/repos/asf/geode/repo
Commit: http://git-wip-us.apache.org/repos/asf/geode/commit/3bfe7a20
Tree: http://git-wip-us.apache.org/repos/asf/geode/tree/3bfe7a20
Diff: http://git-wip-us.apache.org/repos/asf/geode/diff/3bfe7a20

Branch: refs/heads/develop
Commit: 3bfe7a201ce77365f6197be36a3947afea749f10
Parents: 611095f
Author: YehEmily <em...@gmail.com>
Authored: Wed Jul 26 11:07:09 2017 -0700
Committer: Jinmei Liao <ji...@pivotal.io>
Committed: Tue Aug 29 09:27:26 2017 -0700

----------------------------------------------------------------------
 .../org/apache/geode/BundledJarsJUnitTest.java  |  44 +-
 .../cli/commands/AlterRuntimeConfigCommand.java | 246 ++++++++++
 .../internal/cli/commands/ConfigCommands.java   | 490 -------------------
 .../cli/commands/DescribeConfigCommand.java     | 153 ++++++
 .../cli/commands/ExportConfigCommand.java       | 159 ++++++
 .../controllers/ConfigCommandsController.java   |  17 +-
 .../controllers/DeployCommandsController.java   |  19 +-
 .../cli/commands/LogLevelInterceptorTest.java   |   2 +-
 .../internal/security/TestCommand.java          |   2 +-
 9 files changed, 600 insertions(+), 532 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/geode/blob/3bfe7a20/geode-assembly/src/test/java/org/apache/geode/BundledJarsJUnitTest.java
----------------------------------------------------------------------
diff --git a/geode-assembly/src/test/java/org/apache/geode/BundledJarsJUnitTest.java b/geode-assembly/src/test/java/org/apache/geode/BundledJarsJUnitTest.java
index 3f0e2c0..3a5538c 100644
--- a/geode-assembly/src/test/java/org/apache/geode/BundledJarsJUnitTest.java
+++ b/geode-assembly/src/test/java/org/apache/geode/BundledJarsJUnitTest.java
@@ -16,14 +16,6 @@ package org.apache.geode;
 
 import static org.junit.Assert.assertTrue;
 
-import org.apache.commons.io.FileUtils;
-import org.apache.geode.test.junit.categories.IntegrationTest;
-import org.apache.geode.test.junit.categories.RestAPITest;
-import org.apache.geode.util.test.TestUtil;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-
 import java.io.File;
 import java.io.IOException;
 import java.nio.file.Files;
@@ -36,11 +28,20 @@ import java.util.jar.JarFile;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
+import org.apache.commons.io.FileUtils;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import org.apache.geode.test.junit.categories.IntegrationTest;
+import org.apache.geode.test.junit.categories.RestAPITest;
+import org.apache.geode.util.test.TestUtil;
+
 @Category({IntegrationTest.class, RestAPITest.class})
 public class BundledJarsJUnitTest {
 
   private static final String VERSION_PATTERN = "[0-9-_.v]{3,}.*\\.jar$";
-  protected static final String GEODE_HOME = System.getenv("GEODE_HOME");
+  private static final String GEODE_HOME = System.getenv("GEODE_HOME");
   private Set<String> expectedJars;
 
   @Before
@@ -65,27 +66,22 @@ public class BundledJarsJUnitTest {
     TreeSet<String> missingJars = new TreeSet<String>(expectedJars);
     missingJars.removeAll(bundledJarNames);
 
-    StringBuilder message = new StringBuilder();
-    message.append(
-        "The bundled jars have changed. Please make sure you update the licence and notice");
-    message.append(
-        "\nas described in https://cwiki.apache.org/confluence/display/GEODE/License+Guide+for+Contributors");
-    message.append("\nWhen fixed, copy geode-assembly/build/test/bundled_jars.txt");
-    message.append("\nto src/test/resources/expected_jars.txt");
-    message.append("\nRemoved Jars\n--------------\n");
-    message.append(String.join("\n", missingJars));
-    message.append("\n\nAdded Jars\n--------------\n");
-    message.append(String.join("\n", newJars));
-    message.append("\n\n");
-
-    assertTrue(message.toString(), expectedJars.equals(bundledJarNames));
+    String message =
+        "The bundled jars have changed. Please make sure you update the licence and notice"
+            + "\nas described in https://cwiki.apache.org/confluence/display/GEODE/License+Guide+for+Contributors"
+            + "\nWhen fixed, copy geode-assembly/build/test/bundled_jars.txt"
+            + "\nto src/test/resources/expected_jars.txt" + "\nRemoved Jars\n--------------\n"
+            + String.join("\n", missingJars) + "\n\nAdded Jars\n--------------\n"
+            + String.join("\n", newJars) + "\n\n";
+
+    assertTrue(message, expectedJars.equals(bundledJarNames));
 
   }
 
   /**
    * Find all of the jars bundled with the project. Key is the name of the jar, value is the path.
    */
-  protected TreeMap<String, String> getBundledJars() {
+  private TreeMap<String, String> getBundledJars() {
     File geodeHomeDirectory = new File(GEODE_HOME);
 
     assertTrue(

http://git-wip-us.apache.org/repos/asf/geode/blob/3bfe7a20/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/AlterRuntimeConfigCommand.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/AlterRuntimeConfigCommand.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/AlterRuntimeConfigCommand.java
new file mode 100644
index 0000000..3b75977
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/AlterRuntimeConfigCommand.java
@@ -0,0 +1,246 @@
+/*
+ * 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.geode.management.internal.cli.commands;
+
+import static org.apache.geode.distributed.ConfigurationProperties.STATISTIC_SAMPLING_ENABLED;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.logging.log4j.Logger;
+import org.springframework.shell.core.annotation.CliCommand;
+import org.springframework.shell.core.annotation.CliOption;
+
+import org.apache.geode.cache.execute.ResultCollector;
+import org.apache.geode.distributed.DistributedMember;
+import org.apache.geode.internal.cache.xmlcache.CacheXml;
+import org.apache.geode.internal.logging.LogService;
+import org.apache.geode.internal.logging.log4j.LogLevel;
+import org.apache.geode.management.cli.CliMetaData;
+import org.apache.geode.management.cli.ConverterHint;
+import org.apache.geode.management.cli.Result;
+import org.apache.geode.management.internal.cli.AbstractCliAroundInterceptor;
+import org.apache.geode.management.internal.cli.CliUtil;
+import org.apache.geode.management.internal.cli.GfshParseResult;
+import org.apache.geode.management.internal.cli.functions.AlterRuntimeConfigFunction;
+import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
+import org.apache.geode.management.internal.cli.i18n.CliStrings;
+import org.apache.geode.management.internal.cli.result.ResultBuilder;
+import org.apache.geode.management.internal.configuration.domain.XmlEntity;
+import org.apache.geode.management.internal.security.ResourceOperation;
+import org.apache.geode.security.ResourcePermission;
+
+public class AlterRuntimeConfigCommand implements GfshCommand {
+  private final AlterRuntimeConfigFunction alterRunTimeConfigFunction =
+      new AlterRuntimeConfigFunction();
+  private static Logger logger = LogService.getLogger();
+
+  @CliCommand(value = {CliStrings.ALTER_RUNTIME_CONFIG},
+      help = CliStrings.ALTER_RUNTIME_CONFIG__HELP)
+  @CliMetaData(relatedTopic = {CliStrings.TOPIC_GEODE_CONFIG},
+      interceptor = "org.apache.geode.management.internal.cli.commands.AlterRuntimeConfigCommand$AlterRuntimeInterceptor")
+  @ResourceOperation(resource = ResourcePermission.Resource.CLUSTER,
+      operation = ResourcePermission.Operation.MANAGE)
+  public Result alterRuntimeConfig(
+      @CliOption(key = {CliStrings.MEMBER, CliStrings.MEMBERS},
+          optionContext = ConverterHint.ALL_MEMBER_IDNAME,
+          help = CliStrings.ALTER_RUNTIME_CONFIG__MEMBER__HELP) String[] memberNameOrId,
+      @CliOption(key = {CliStrings.GROUP, CliStrings.GROUPS},
+          optionContext = ConverterHint.MEMBERGROUP,
+          help = CliStrings.ALTER_RUNTIME_CONFIG__MEMBER__HELP) String[] group,
+      @CliOption(key = {CliStrings.ALTER_RUNTIME_CONFIG__ARCHIVE__DISK__SPACE__LIMIT},
+          help = CliStrings.ALTER_RUNTIME_CONFIG__ARCHIVE__DISK__SPACE__LIMIT__HELP) Integer archiveDiskSpaceLimit,
+      @CliOption(key = {CliStrings.ALTER_RUNTIME_CONFIG__ARCHIVE__FILE__SIZE__LIMIT},
+          help = CliStrings.ALTER_RUNTIME_CONFIG__ARCHIVE__FILE__SIZE__LIMIT__HELP) Integer archiveFileSizeLimit,
+      @CliOption(key = {CliStrings.ALTER_RUNTIME_CONFIG__LOG__DISK__SPACE__LIMIT},
+          help = CliStrings.ALTER_RUNTIME_CONFIG__LOG__DISK__SPACE__LIMIT__HELP) Integer logDiskSpaceLimit,
+      @CliOption(key = {CliStrings.ALTER_RUNTIME_CONFIG__LOG__FILE__SIZE__LIMIT},
+          help = CliStrings.ALTER_RUNTIME_CONFIG__LOG__FILE__SIZE__LIMIT__HELP) Integer logFileSizeLimit,
+      @CliOption(key = {CliStrings.ALTER_RUNTIME_CONFIG__LOG__LEVEL},
+          optionContext = ConverterHint.LOG_LEVEL,
+          help = CliStrings.ALTER_RUNTIME_CONFIG__LOG__LEVEL__HELP) String logLevel,
+      @CliOption(key = {CliStrings.ALTER_RUNTIME_CONFIG__STATISTIC__ARCHIVE__FILE},
+          help = CliStrings.ALTER_RUNTIME_CONFIG__STATISTIC__ARCHIVE__FILE__HELP) String statisticArchiveFile,
+      @CliOption(key = {CliStrings.ALTER_RUNTIME_CONFIG__STATISTIC__SAMPLE__RATE},
+          help = CliStrings.ALTER_RUNTIME_CONFIG__STATISTIC__SAMPLE__RATE__HELP) Integer statisticSampleRate,
+      @CliOption(key = {CliStrings.ALTER_RUNTIME_CONFIG__STATISTIC__SAMPLING__ENABLED},
+          help = CliStrings.ALTER_RUNTIME_CONFIG__STATISTIC__SAMPLING__ENABLED__HELP) Boolean statisticSamplingEnabled,
+      @CliOption(key = {CliStrings.ALTER_RUNTIME_CONFIG__COPY__ON__READ},
+          specifiedDefaultValue = "false",
+          help = CliStrings.ALTER_RUNTIME_CONFIG__COPY__ON__READ__HELP) Boolean setCopyOnRead,
+      @CliOption(key = {CliStrings.ALTER_RUNTIME_CONFIG__LOCK__LEASE},
+          help = CliStrings.ALTER_RUNTIME_CONFIG__LOCK__LEASE__HELP) Integer lockLease,
+      @CliOption(key = {CliStrings.ALTER_RUNTIME_CONFIG__LOCK__TIMEOUT},
+          help = CliStrings.ALTER_RUNTIME_CONFIG__LOCK__TIMEOUT__HELP) Integer lockTimeout,
+      @CliOption(key = {CliStrings.ALTER_RUNTIME_CONFIG__MESSAGE__SYNC__INTERVAL},
+          help = CliStrings.ALTER_RUNTIME_CONFIG__MESSAGE__SYNC__INTERVAL__HELP) Integer messageSyncInterval,
+      @CliOption(key = {CliStrings.ALTER_RUNTIME_CONFIG__SEARCH__TIMEOUT},
+          help = CliStrings.ALTER_RUNTIME_CONFIG__SEARCH__TIMEOUT__HELP) Integer searchTimeout) {
+
+    Map<String, String> runTimeDistributionConfigAttributes = new HashMap<>();
+    Map<String, String> rumTimeCacheAttributes = new HashMap<>();
+    Set<DistributedMember> targetMembers = CliUtil.findMembers(group, memberNameOrId);
+
+    if (targetMembers.isEmpty()) {
+      return ResultBuilder.createUserErrorResult(CliStrings.NO_MEMBERS_FOUND_MESSAGE);
+    }
+
+    if (archiveDiskSpaceLimit != null) {
+      runTimeDistributionConfigAttributes.put(
+          CliStrings.ALTER_RUNTIME_CONFIG__ARCHIVE__DISK__SPACE__LIMIT,
+          archiveDiskSpaceLimit.toString());
+    }
+
+    if (archiveFileSizeLimit != null) {
+      runTimeDistributionConfigAttributes.put(
+          CliStrings.ALTER_RUNTIME_CONFIG__ARCHIVE__FILE__SIZE__LIMIT,
+          archiveFileSizeLimit.toString());
+    }
+
+    if (logDiskSpaceLimit != null) {
+      runTimeDistributionConfigAttributes.put(
+          CliStrings.ALTER_RUNTIME_CONFIG__LOG__DISK__SPACE__LIMIT, logDiskSpaceLimit.toString());
+    }
+
+    if (logFileSizeLimit != null) {
+      runTimeDistributionConfigAttributes.put(
+          CliStrings.ALTER_RUNTIME_CONFIG__LOG__FILE__SIZE__LIMIT, logFileSizeLimit.toString());
+    }
+
+    if (logLevel != null && !logLevel.isEmpty()) {
+      runTimeDistributionConfigAttributes.put(CliStrings.ALTER_RUNTIME_CONFIG__LOG__LEVEL,
+          logLevel);
+    }
+
+    if (statisticArchiveFile != null && !statisticArchiveFile.isEmpty()) {
+      runTimeDistributionConfigAttributes
+          .put(CliStrings.ALTER_RUNTIME_CONFIG__STATISTIC__ARCHIVE__FILE, statisticArchiveFile);
+    }
+
+    if (statisticSampleRate != null) {
+      runTimeDistributionConfigAttributes.put(
+          CliStrings.ALTER_RUNTIME_CONFIG__STATISTIC__SAMPLE__RATE, statisticSampleRate.toString());
+    }
+
+    if (statisticSamplingEnabled != null) {
+      runTimeDistributionConfigAttributes.put(STATISTIC_SAMPLING_ENABLED,
+          statisticSamplingEnabled.toString());
+    }
+
+
+    // Attributes that are set on the cache.
+    if (setCopyOnRead != null) {
+      rumTimeCacheAttributes.put(CliStrings.ALTER_RUNTIME_CONFIG__COPY__ON__READ,
+          setCopyOnRead.toString());
+    }
+
+    if (lockLease != null && lockLease > 0 && lockLease < Integer.MAX_VALUE) {
+      rumTimeCacheAttributes.put(CliStrings.ALTER_RUNTIME_CONFIG__LOCK__LEASE,
+          lockLease.toString());
+    }
+
+    if (lockTimeout != null && lockTimeout > 0 && lockTimeout < Integer.MAX_VALUE) {
+      rumTimeCacheAttributes.put(CliStrings.ALTER_RUNTIME_CONFIG__LOCK__TIMEOUT,
+          lockTimeout.toString());
+    }
+
+    if (messageSyncInterval != null && messageSyncInterval > 0
+        && messageSyncInterval < Integer.MAX_VALUE) {
+      rumTimeCacheAttributes.put(CliStrings.ALTER_RUNTIME_CONFIG__MESSAGE__SYNC__INTERVAL,
+          messageSyncInterval.toString());
+    }
+
+    if (searchTimeout != null && searchTimeout > 0 && searchTimeout < Integer.MAX_VALUE) {
+      rumTimeCacheAttributes.put(CliStrings.ALTER_RUNTIME_CONFIG__SEARCH__TIMEOUT,
+          searchTimeout.toString());
+    }
+
+    if (runTimeDistributionConfigAttributes.isEmpty() && rumTimeCacheAttributes.isEmpty()) {
+      return ResultBuilder
+          .createUserErrorResult(CliStrings.ALTER_RUNTIME_CONFIG__RELEVANT__OPTION__MESSAGE);
+    }
+
+    Map<String, String> allRunTimeAttributes = new HashMap<>();
+    allRunTimeAttributes.putAll(runTimeDistributionConfigAttributes);
+    allRunTimeAttributes.putAll(rumTimeCacheAttributes);
+
+    ResultCollector<?, ?> rc =
+        CliUtil.executeFunction(alterRunTimeConfigFunction, allRunTimeAttributes, targetMembers);
+    List<CliFunctionResult> results = CliFunctionResult.cleanResults((List<?>) rc.getResult());
+    Set<String> successfulMembers = new TreeSet<>();
+    Set<String> errorMessages = new TreeSet<>();
+
+    for (CliFunctionResult result : results) {
+      if (result.getThrowable() != null) {
+        logger.info("Function failed: " + result.getThrowable());
+        errorMessages.add(result.getThrowable().getMessage());
+      } else {
+        successfulMembers.add(result.getMemberIdOrName());
+      }
+    }
+    final String lineSeparator = System.getProperty("line.separator");
+    if (!successfulMembers.isEmpty()) {
+      StringBuilder successMessageBuilder = new StringBuilder();
+
+      successMessageBuilder.append(CliStrings.ALTER_RUNTIME_CONFIG__SUCCESS__MESSAGE);
+      successMessageBuilder.append(lineSeparator);
+
+      for (String member : successfulMembers) {
+        successMessageBuilder.append(member);
+        successMessageBuilder.append(lineSeparator);
+      }
+
+      Properties properties = new Properties();
+      properties.putAll(runTimeDistributionConfigAttributes);
+
+      Result result = ResultBuilder.createInfoResult(successMessageBuilder.toString());
+
+      // Set the Cache attributes to be modified
+      final XmlEntity xmlEntity = XmlEntity.builder().withType(CacheXml.CACHE)
+          .withAttributes(rumTimeCacheAttributes).build();
+      persistClusterConfiguration(result,
+          () -> getSharedConfiguration().modifyXmlAndProperties(properties, xmlEntity, group));
+      return result;
+    } else {
+      StringBuilder errorMessageBuilder = new StringBuilder();
+      errorMessageBuilder.append("Following errors occurred while altering runtime config");
+      errorMessageBuilder.append(lineSeparator);
+
+      for (String errorMessage : errorMessages) {
+        errorMessageBuilder.append(errorMessage);
+        errorMessageBuilder.append(lineSeparator);
+      }
+      return ResultBuilder.createUserErrorResult(errorMessageBuilder.toString());
+    }
+  }
+
+  public static class AlterRuntimeInterceptor extends AbstractCliAroundInterceptor {
+    @Override
+    public Result preExecution(GfshParseResult parseResult) {
+      Map<String, String> arguments = parseResult.getParamValueStrings();
+      // validate log level
+      String logLevel = arguments.get("log-level");
+      if (StringUtils.isNotBlank(logLevel) && (LogLevel.getLevel(logLevel) == null)) {
+        return ResultBuilder.createUserErrorResult("Invalid log level: " + logLevel);
+      }
+      return ResultBuilder.createInfoResult("");
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/3bfe7a20/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ConfigCommands.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ConfigCommands.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ConfigCommands.java
deleted file mode 100644
index a8afa7d..0000000
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ConfigCommands.java
+++ /dev/null
@@ -1,490 +0,0 @@
-/*
- * 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.geode.management.internal.cli.commands;
-
-import static org.apache.geode.distributed.ConfigurationProperties.STATISTIC_SAMPLING_ENABLED;
-
-import org.apache.commons.lang.StringUtils;
-import org.apache.geode.SystemFailure;
-import org.apache.geode.cache.execute.FunctionInvocationTargetException;
-import org.apache.geode.cache.execute.ResultCollector;
-import org.apache.geode.distributed.DistributedMember;
-import org.apache.geode.internal.cache.xmlcache.CacheXml;
-import org.apache.geode.internal.logging.LogService;
-import org.apache.geode.internal.logging.log4j.LogLevel;
-import org.apache.geode.management.cli.CliMetaData;
-import org.apache.geode.management.cli.ConverterHint;
-import org.apache.geode.management.cli.Result;
-import org.apache.geode.management.internal.cli.AbstractCliAroundInterceptor;
-import org.apache.geode.management.internal.cli.CliUtil;
-import org.apache.geode.management.internal.cli.GfshParseResult;
-import org.apache.geode.management.internal.cli.domain.MemberConfigurationInfo;
-import org.apache.geode.management.internal.cli.functions.AlterRuntimeConfigFunction;
-import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
-import org.apache.geode.management.internal.cli.functions.ExportConfigFunction;
-import org.apache.geode.management.internal.cli.functions.GetMemberConfigInformationFunction;
-import org.apache.geode.management.internal.cli.i18n.CliStrings;
-import org.apache.geode.management.internal.cli.result.CommandResultException;
-import org.apache.geode.management.internal.cli.result.CompositeResultData;
-import org.apache.geode.management.internal.cli.result.CompositeResultData.SectionResultData;
-import org.apache.geode.management.internal.cli.result.ErrorResultData;
-import org.apache.geode.management.internal.cli.result.InfoResultData;
-import org.apache.geode.management.internal.cli.result.ResultBuilder;
-import org.apache.geode.management.internal.cli.result.TabularResultData;
-import org.apache.geode.management.internal.cli.shell.Gfsh;
-import org.apache.geode.management.internal.configuration.domain.XmlEntity;
-import org.apache.geode.management.internal.security.ResourceOperation;
-import org.apache.geode.security.ResourcePermission.Operation;
-import org.apache.geode.security.ResourcePermission.Resource;
-import org.apache.logging.log4j.Logger;
-import org.springframework.shell.core.annotation.CliAvailabilityIndicator;
-import org.springframework.shell.core.annotation.CliCommand;
-import org.springframework.shell.core.annotation.CliOption;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-import java.util.TreeSet;
-
-/****
- * @since GemFire 7.0
- *
- */
-public class ConfigCommands implements GfshCommand {
-  private final ExportConfigFunction exportConfigFunction = new ExportConfigFunction();
-  private final GetMemberConfigInformationFunction getMemberConfigFunction =
-      new GetMemberConfigInformationFunction();
-  private final AlterRuntimeConfigFunction alterRunTimeConfigFunction =
-      new AlterRuntimeConfigFunction();
-  private static Logger logger = LogService.getLogger();
-
-  @CliCommand(value = {CliStrings.DESCRIBE_CONFIG}, help = CliStrings.DESCRIBE_CONFIG__HELP)
-  @CliMetaData(relatedTopic = {CliStrings.TOPIC_GEODE_CONFIG})
-  @ResourceOperation(resource = Resource.CLUSTER, operation = Operation.READ)
-  public Result describeConfig(
-      @CliOption(key = CliStrings.MEMBER, optionContext = ConverterHint.ALL_MEMBER_IDNAME,
-          help = CliStrings.DESCRIBE_CONFIG__MEMBER__HELP, mandatory = true) String memberNameOrId,
-      @CliOption(key = CliStrings.DESCRIBE_CONFIG__HIDE__DEFAULTS,
-          help = CliStrings.DESCRIBE_CONFIG__HIDE__DEFAULTS__HELP, unspecifiedDefaultValue = "true",
-          specifiedDefaultValue = "true") boolean hideDefaults) {
-
-    Result result = null;
-    try {
-      DistributedMember targetMember = null;
-
-      if (memberNameOrId != null && !memberNameOrId.isEmpty()) {
-        targetMember = CliUtil.getDistributedMemberByNameOrId(memberNameOrId);
-      }
-      if (targetMember != null) {
-        ResultCollector<?, ?> rc = CliUtil.executeFunction(getMemberConfigFunction,
-            new Boolean(hideDefaults), targetMember);
-        ArrayList<?> output = (ArrayList<?>) rc.getResult();
-        Object obj = output.get(0);
-
-        if (obj != null && obj instanceof MemberConfigurationInfo) {
-          MemberConfigurationInfo memberConfigInfo = (MemberConfigurationInfo) obj;
-
-          CompositeResultData crd = ResultBuilder.createCompositeResultData();
-          crd.setHeader(
-              CliStrings.format(CliStrings.DESCRIBE_CONFIG__HEADER__TEXT, memberNameOrId));
-
-          List<String> jvmArgsList = memberConfigInfo.getJvmInputArguments();
-          TabularResultData jvmInputArgs = crd.addSection().addSection().addTable();
-
-          for (String jvmArg : jvmArgsList) {
-            jvmInputArgs.accumulate("JVM command line arguments", jvmArg);
-          }
-
-          addSection(crd, memberConfigInfo.getGfePropsSetUsingApi(),
-              "GemFire properties defined using the API");
-          addSection(crd, memberConfigInfo.getGfePropsRuntime(),
-              "GemFire properties defined at the runtime");
-          addSection(crd, memberConfigInfo.getGfePropsSetFromFile(),
-              "GemFire properties defined with the property file");
-          addSection(crd, memberConfigInfo.getGfePropsSetWithDefaults(),
-              "GemFire properties using default values");
-          addSection(crd, memberConfigInfo.getCacheAttributes(), "Cache attributes");
-
-          List<Map<String, String>> cacheServerAttributesList =
-              memberConfigInfo.getCacheServerAttributes();
-
-          if (cacheServerAttributesList != null && !cacheServerAttributesList.isEmpty()) {
-            SectionResultData cacheServerSection = crd.addSection();
-            cacheServerSection.setHeader("Cache-server attributes");
-
-            for (Map<String, String> cacheServerAttributes : cacheServerAttributesList) {
-              addSubSection(cacheServerSection, cacheServerAttributes, "");
-            }
-          }
-          result = ResultBuilder.buildResult(crd);
-        }
-
-      } else {
-        ErrorResultData erd = ResultBuilder.createErrorResultData();
-        erd.addLine(CliStrings.format(CliStrings.DESCRIBE_CONFIG__MEMBER__NOT__FOUND,
-            new Object[] {memberNameOrId}));
-        result = ResultBuilder.buildResult(erd);
-      }
-    } catch (FunctionInvocationTargetException e) {
-      result = ResultBuilder.createGemFireErrorResult(CliStrings
-          .format(CliStrings.COULD_NOT_EXECUTE_COMMAND_TRY_AGAIN, CliStrings.DESCRIBE_CONFIG));
-    } catch (Exception e) {
-      ErrorResultData erd = ResultBuilder.createErrorResultData();
-      erd.addLine(e.getMessage());
-      result = ResultBuilder.buildResult(erd);
-    }
-    return result;
-  }
-
-
-  private void addSection(CompositeResultData crd, Map<String, String> attrMap, String headerText) {
-    if (attrMap != null && !attrMap.isEmpty()) {
-      SectionResultData section = crd.addSection();
-      section.setHeader(headerText);
-      section.addSeparator('.');
-      Set<String> attributes = new TreeSet<>(attrMap.keySet());
-
-      for (String attribute : attributes) {
-        String attributeValue = attrMap.get(attribute);
-        section.addData(attribute, attributeValue);
-      }
-    }
-  }
-
-  private void addSubSection(SectionResultData section, Map<String, String> attrMap,
-      String headerText) {
-    if (!attrMap.isEmpty()) {
-      SectionResultData subSection = section.addSection();
-      Set<String> attributes = new TreeSet<>(attrMap.keySet());
-      subSection.setHeader(headerText);
-
-      for (String attribute : attributes) {
-        String attributeValue = attrMap.get(attribute);
-        subSection.addData(attribute, attributeValue);
-      }
-    }
-  }
-
-  /**
-   * Export the cache configuration in XML format.
-   *
-   * @param member Member for which to write the configuration
-   * @param group Group or groups for which to write the configuration
-   * @return Results of the attempt to write the configuration
-   */
-  @CliCommand(value = {CliStrings.EXPORT_CONFIG}, help = CliStrings.EXPORT_CONFIG__HELP)
-  @CliMetaData(
-      interceptor = "org.apache.geode.management.internal.cli.commands.ConfigCommands$Interceptor",
-      relatedTopic = {CliStrings.TOPIC_GEODE_CONFIG})
-  @ResourceOperation(resource = Resource.CLUSTER, operation = Operation.READ)
-  public Result exportConfig(
-      @CliOption(key = {CliStrings.MEMBER, CliStrings.MEMBERS},
-          optionContext = ConverterHint.ALL_MEMBER_IDNAME,
-          help = CliStrings.EXPORT_CONFIG__MEMBER__HELP) String[] member,
-      @CliOption(key = {CliStrings.GROUP, CliStrings.GROUPS},
-          optionContext = ConverterHint.MEMBERGROUP,
-          help = CliStrings.EXPORT_CONFIG__GROUP__HELP) String[] group,
-      @CliOption(key = {CliStrings.EXPORT_CONFIG__DIR},
-          help = CliStrings.EXPORT_CONFIG__DIR__HELP) String dir) {
-    InfoResultData infoData = ResultBuilder.createInfoResultData();
-
-    Set<DistributedMember> targetMembers = CliUtil.findMembers(group, member);
-    if (targetMembers.isEmpty()) {
-      return ResultBuilder.createUserErrorResult(CliStrings.NO_MEMBERS_FOUND_MESSAGE);
-    }
-
-    try {
-      ResultCollector<?, ?> rc =
-          CliUtil.executeFunction(this.exportConfigFunction, null, targetMembers);
-      List<CliFunctionResult> results = CliFunctionResult.cleanResults((List<?>) rc.getResult());
-
-      for (CliFunctionResult result : results) {
-        if (result.getThrowable() != null) {
-          infoData.addLine(CliStrings.format(CliStrings.EXPORT_CONFIG__MSG__EXCEPTION,
-              result.getMemberIdOrName(), result.getThrowable()));
-        } else if (result.isSuccessful()) {
-          String cacheFileName = result.getMemberIdOrName() + "-cache.xml";
-          String propsFileName = result.getMemberIdOrName() + "-gf.properties";
-          String[] fileContent = (String[]) result.getSerializables();
-          infoData.addAsFile(cacheFileName, fileContent[0], "Downloading Cache XML file: {0}",
-              false);
-          infoData.addAsFile(propsFileName, fileContent[1], "Downloading properties file: {0}",
-              false);
-        }
-      }
-      return ResultBuilder.buildResult(infoData);
-    } catch (VirtualMachineError e) {
-      SystemFailure.initiateFailure(e);
-      throw e;
-    } catch (Throwable th) {
-      SystemFailure.checkFailure();
-      th.printStackTrace(System.err);
-      return ResultBuilder
-          .createGemFireErrorResult(CliStrings.format(CliStrings.EXPORT_CONFIG__MSG__EXCEPTION,
-              th.getClass().getName() + ": " + th.getMessage()));
-    }
-  }
-
-
-  @CliCommand(value = {CliStrings.ALTER_RUNTIME_CONFIG},
-      help = CliStrings.ALTER_RUNTIME_CONFIG__HELP)
-  @CliMetaData(relatedTopic = {CliStrings.TOPIC_GEODE_CONFIG},
-      interceptor = "org.apache.geode.management.internal.cli.commands.ConfigCommands$AlterRuntimeInterceptor")
-  @ResourceOperation(resource = Resource.CLUSTER, operation = Operation.MANAGE)
-  public Result alterRuntimeConfig(
-      @CliOption(key = {CliStrings.MEMBER, CliStrings.MEMBERS},
-          optionContext = ConverterHint.ALL_MEMBER_IDNAME,
-          help = CliStrings.ALTER_RUNTIME_CONFIG__MEMBER__HELP) String[] memberNameOrId,
-      @CliOption(key = {CliStrings.GROUP, CliStrings.GROUPS},
-          optionContext = ConverterHint.MEMBERGROUP,
-          help = CliStrings.ALTER_RUNTIME_CONFIG__MEMBER__HELP) String[] group,
-      @CliOption(key = {CliStrings.ALTER_RUNTIME_CONFIG__ARCHIVE__DISK__SPACE__LIMIT},
-          help = CliStrings.ALTER_RUNTIME_CONFIG__ARCHIVE__DISK__SPACE__LIMIT__HELP) Integer archiveDiskSpaceLimit,
-      @CliOption(key = {CliStrings.ALTER_RUNTIME_CONFIG__ARCHIVE__FILE__SIZE__LIMIT},
-          help = CliStrings.ALTER_RUNTIME_CONFIG__ARCHIVE__FILE__SIZE__LIMIT__HELP) Integer archiveFileSizeLimit,
-      @CliOption(key = {CliStrings.ALTER_RUNTIME_CONFIG__LOG__DISK__SPACE__LIMIT},
-          help = CliStrings.ALTER_RUNTIME_CONFIG__LOG__DISK__SPACE__LIMIT__HELP) Integer logDiskSpaceLimit,
-      @CliOption(key = {CliStrings.ALTER_RUNTIME_CONFIG__LOG__FILE__SIZE__LIMIT},
-          help = CliStrings.ALTER_RUNTIME_CONFIG__LOG__FILE__SIZE__LIMIT__HELP) Integer logFileSizeLimit,
-      @CliOption(key = {CliStrings.ALTER_RUNTIME_CONFIG__LOG__LEVEL},
-          optionContext = ConverterHint.LOG_LEVEL,
-          help = CliStrings.ALTER_RUNTIME_CONFIG__LOG__LEVEL__HELP) String logLevel,
-      @CliOption(key = {CliStrings.ALTER_RUNTIME_CONFIG__STATISTIC__ARCHIVE__FILE},
-          help = CliStrings.ALTER_RUNTIME_CONFIG__STATISTIC__ARCHIVE__FILE__HELP) String statisticArchiveFile,
-      @CliOption(key = {CliStrings.ALTER_RUNTIME_CONFIG__STATISTIC__SAMPLE__RATE},
-          help = CliStrings.ALTER_RUNTIME_CONFIG__STATISTIC__SAMPLE__RATE__HELP) Integer statisticSampleRate,
-      @CliOption(key = {CliStrings.ALTER_RUNTIME_CONFIG__STATISTIC__SAMPLING__ENABLED},
-          help = CliStrings.ALTER_RUNTIME_CONFIG__STATISTIC__SAMPLING__ENABLED__HELP) Boolean statisticSamplingEnabled,
-      @CliOption(key = {CliStrings.ALTER_RUNTIME_CONFIG__COPY__ON__READ},
-          specifiedDefaultValue = "false",
-          help = CliStrings.ALTER_RUNTIME_CONFIG__COPY__ON__READ__HELP) Boolean setCopyOnRead,
-      @CliOption(key = {CliStrings.ALTER_RUNTIME_CONFIG__LOCK__LEASE},
-          help = CliStrings.ALTER_RUNTIME_CONFIG__LOCK__LEASE__HELP) Integer lockLease,
-      @CliOption(key = {CliStrings.ALTER_RUNTIME_CONFIG__LOCK__TIMEOUT},
-          help = CliStrings.ALTER_RUNTIME_CONFIG__LOCK__TIMEOUT__HELP) Integer lockTimeout,
-      @CliOption(key = {CliStrings.ALTER_RUNTIME_CONFIG__MESSAGE__SYNC__INTERVAL},
-          help = CliStrings.ALTER_RUNTIME_CONFIG__MESSAGE__SYNC__INTERVAL__HELP) Integer messageSyncInterval,
-      @CliOption(key = {CliStrings.ALTER_RUNTIME_CONFIG__SEARCH__TIMEOUT},
-          help = CliStrings.ALTER_RUNTIME_CONFIG__SEARCH__TIMEOUT__HELP) Integer searchTimeout) {
-
-    Map<String, String> runTimeDistributionConfigAttributes = new HashMap<>();
-    Map<String, String> rumTimeCacheAttributes = new HashMap<>();
-    Set<DistributedMember> targetMembers = CliUtil.findMembers(group, memberNameOrId);
-
-    if (targetMembers.isEmpty()) {
-      return ResultBuilder.createUserErrorResult(CliStrings.NO_MEMBERS_FOUND_MESSAGE);
-    }
-
-    if (archiveDiskSpaceLimit != null) {
-      runTimeDistributionConfigAttributes.put(
-          CliStrings.ALTER_RUNTIME_CONFIG__ARCHIVE__DISK__SPACE__LIMIT,
-          archiveDiskSpaceLimit.toString());
-    }
-
-    if (archiveFileSizeLimit != null) {
-      runTimeDistributionConfigAttributes.put(
-          CliStrings.ALTER_RUNTIME_CONFIG__ARCHIVE__FILE__SIZE__LIMIT,
-          archiveFileSizeLimit.toString());
-    }
-
-    if (logDiskSpaceLimit != null) {
-      runTimeDistributionConfigAttributes.put(
-          CliStrings.ALTER_RUNTIME_CONFIG__LOG__DISK__SPACE__LIMIT, logDiskSpaceLimit.toString());
-    }
-
-    if (logFileSizeLimit != null) {
-      runTimeDistributionConfigAttributes.put(
-          CliStrings.ALTER_RUNTIME_CONFIG__LOG__FILE__SIZE__LIMIT, logFileSizeLimit.toString());
-    }
-
-    if (logLevel != null && !logLevel.isEmpty()) {
-      runTimeDistributionConfigAttributes.put(CliStrings.ALTER_RUNTIME_CONFIG__LOG__LEVEL,
-          logLevel);
-    }
-
-    if (statisticArchiveFile != null && !statisticArchiveFile.isEmpty()) {
-      runTimeDistributionConfigAttributes
-          .put(CliStrings.ALTER_RUNTIME_CONFIG__STATISTIC__ARCHIVE__FILE, statisticArchiveFile);
-    }
-
-    if (statisticSampleRate != null) {
-      runTimeDistributionConfigAttributes.put(
-          CliStrings.ALTER_RUNTIME_CONFIG__STATISTIC__SAMPLE__RATE, statisticSampleRate.toString());
-    }
-
-    if (statisticSamplingEnabled != null) {
-      runTimeDistributionConfigAttributes.put(STATISTIC_SAMPLING_ENABLED,
-          statisticSamplingEnabled.toString());
-    }
-
-
-    // Attributes that are set on the cache.
-    if (setCopyOnRead != null) {
-      rumTimeCacheAttributes.put(CliStrings.ALTER_RUNTIME_CONFIG__COPY__ON__READ,
-          setCopyOnRead.toString());
-    }
-
-    if (lockLease != null && lockLease > 0 && lockLease < Integer.MAX_VALUE) {
-      rumTimeCacheAttributes.put(CliStrings.ALTER_RUNTIME_CONFIG__LOCK__LEASE,
-          lockLease.toString());
-    }
-
-    if (lockTimeout != null && lockTimeout > 0 && lockTimeout < Integer.MAX_VALUE) {
-      rumTimeCacheAttributes.put(CliStrings.ALTER_RUNTIME_CONFIG__LOCK__TIMEOUT,
-          lockTimeout.toString());
-    }
-
-    if (messageSyncInterval != null && messageSyncInterval > 0
-        && messageSyncInterval < Integer.MAX_VALUE) {
-      rumTimeCacheAttributes.put(CliStrings.ALTER_RUNTIME_CONFIG__MESSAGE__SYNC__INTERVAL,
-          messageSyncInterval.toString());
-    }
-
-    if (searchTimeout != null && searchTimeout > 0 && searchTimeout < Integer.MAX_VALUE) {
-      rumTimeCacheAttributes.put(CliStrings.ALTER_RUNTIME_CONFIG__SEARCH__TIMEOUT,
-          searchTimeout.toString());
-    }
-
-    if (runTimeDistributionConfigAttributes.isEmpty() && rumTimeCacheAttributes.isEmpty()) {
-      return ResultBuilder
-          .createUserErrorResult(CliStrings.ALTER_RUNTIME_CONFIG__RELEVANT__OPTION__MESSAGE);
-    }
-
-    Map<String, String> allRunTimeAttributes = new HashMap<>();
-    allRunTimeAttributes.putAll(runTimeDistributionConfigAttributes);
-    allRunTimeAttributes.putAll(rumTimeCacheAttributes);
-
-    ResultCollector<?, ?> rc =
-        CliUtil.executeFunction(alterRunTimeConfigFunction, allRunTimeAttributes, targetMembers);
-    List<CliFunctionResult> results = CliFunctionResult.cleanResults((List<?>) rc.getResult());
-    Set<String> successfulMembers = new TreeSet<>();
-    Set<String> errorMessages = new TreeSet<>();
-
-    for (CliFunctionResult result : results) {
-      if (result.getThrowable() != null) {
-        logger.info("Function failed: " + result.getThrowable());
-        errorMessages.add(result.getThrowable().getMessage());
-      } else {
-        successfulMembers.add(result.getMemberIdOrName());
-      }
-    }
-    final String lineSeparator = System.getProperty("line.separator");
-    if (!successfulMembers.isEmpty()) {
-      StringBuilder successMessageBuilder = new StringBuilder();
-
-      successMessageBuilder.append(CliStrings.ALTER_RUNTIME_CONFIG__SUCCESS__MESSAGE);
-      successMessageBuilder.append(lineSeparator);
-
-      for (String member : successfulMembers) {
-        successMessageBuilder.append(member);
-        successMessageBuilder.append(lineSeparator);
-      }
-
-      Properties properties = new Properties();
-      properties.putAll(runTimeDistributionConfigAttributes);
-
-      Result result = ResultBuilder.createInfoResult(successMessageBuilder.toString());
-
-      // Set the Cache attributes to be modified
-      final XmlEntity xmlEntity = XmlEntity.builder().withType(CacheXml.CACHE)
-          .withAttributes(rumTimeCacheAttributes).build();
-      persistClusterConfiguration(result,
-          () -> getSharedConfiguration().modifyXmlAndProperties(properties, xmlEntity, group));
-      return result;
-    } else {
-      StringBuilder errorMessageBuilder = new StringBuilder();
-      errorMessageBuilder.append("Following errors occurred while altering runtime config");
-      errorMessageBuilder.append(lineSeparator);
-
-      for (String errorMessage : errorMessages) {
-        errorMessageBuilder.append(errorMessage);
-        errorMessageBuilder.append(lineSeparator);
-      }
-      return ResultBuilder.createUserErrorResult(errorMessageBuilder.toString());
-    }
-  }
-
-  public static class AlterRuntimeInterceptor extends AbstractCliAroundInterceptor {
-    @Override
-    public Result preExecution(GfshParseResult parseResult) {
-      Map<String, String> arguments = parseResult.getParamValueStrings();
-      // validate log level
-      String logLevel = arguments.get("log-level");
-      if (StringUtils.isNotBlank(logLevel) && (LogLevel.getLevel(logLevel) == null)) {
-        return ResultBuilder.createUserErrorResult("Invalid log level: " + logLevel);
-      }
-
-      return ResultBuilder.createInfoResult("");
-    }
-  }
-
-  /**
-   * Interceptor used by gfsh to intercept execution of export config command at "shell".
-   */
-  public static class Interceptor extends AbstractCliAroundInterceptor {
-    private String saveDirString;
-
-    @Override
-    public Result preExecution(GfshParseResult parseResult) {
-      Map<String, String> paramValueMap = parseResult.getParamValueStrings();
-      String dir = paramValueMap.get("dir");
-      dir = (dir == null) ? null : dir.trim();
-
-      File saveDirFile = new File(".");
-      if (dir != null && !dir.isEmpty()) {
-        saveDirFile = new File(dir);
-        if (saveDirFile.exists()) {
-          if (!saveDirFile.isDirectory())
-            return ResultBuilder.createGemFireErrorResult(
-                CliStrings.format(CliStrings.EXPORT_CONFIG__MSG__NOT_A_DIRECTORY, dir));
-        } else if (!saveDirFile.mkdirs()) {
-          return ResultBuilder.createGemFireErrorResult(
-              CliStrings.format(CliStrings.EXPORT_CONFIG__MSG__CANNOT_CREATE_DIR, dir));
-        }
-      }
-      try {
-        if (!saveDirFile.canWrite()) {
-          return ResultBuilder.createGemFireErrorResult(CliStrings.format(
-              CliStrings.EXPORT_CONFIG__MSG__NOT_WRITEABLE, saveDirFile.getCanonicalPath()));
-        }
-      } catch (IOException ioex) {
-        return ResultBuilder.createGemFireErrorResult(
-            CliStrings.format(CliStrings.EXPORT_CONFIG__MSG__NOT_WRITEABLE, saveDirFile.getName()));
-      }
-
-      saveDirString = saveDirFile.getAbsolutePath();
-      return ResultBuilder.createInfoResult("OK");
-    }
-
-    @Override
-    public Result postExecution(GfshParseResult parseResult, Result commandResult, Path tempFile) {
-      if (commandResult.hasIncomingFiles()) {
-        try {
-          commandResult.saveIncomingFiles(saveDirString);
-        } catch (IOException ioex) {
-          Gfsh.getCurrentInstance().logSevere("Unable to export config", ioex);
-        }
-      }
-
-      return commandResult;
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/geode/blob/3bfe7a20/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DescribeConfigCommand.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DescribeConfigCommand.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DescribeConfigCommand.java
new file mode 100644
index 0000000..824063a
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DescribeConfigCommand.java
@@ -0,0 +1,153 @@
+/*
+ * 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.geode.management.internal.cli.commands;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.springframework.shell.core.annotation.CliCommand;
+import org.springframework.shell.core.annotation.CliOption;
+
+import org.apache.geode.cache.execute.FunctionInvocationTargetException;
+import org.apache.geode.cache.execute.ResultCollector;
+import org.apache.geode.distributed.DistributedMember;
+import org.apache.geode.management.cli.CliMetaData;
+import org.apache.geode.management.cli.ConverterHint;
+import org.apache.geode.management.cli.Result;
+import org.apache.geode.management.internal.cli.CliUtil;
+import org.apache.geode.management.internal.cli.domain.MemberConfigurationInfo;
+import org.apache.geode.management.internal.cli.functions.GetMemberConfigInformationFunction;
+import org.apache.geode.management.internal.cli.i18n.CliStrings;
+import org.apache.geode.management.internal.cli.result.CompositeResultData;
+import org.apache.geode.management.internal.cli.result.ErrorResultData;
+import org.apache.geode.management.internal.cli.result.ResultBuilder;
+import org.apache.geode.management.internal.cli.result.TabularResultData;
+import org.apache.geode.management.internal.security.ResourceOperation;
+import org.apache.geode.security.ResourcePermission;
+
+public class DescribeConfigCommand implements GfshCommand {
+  private final GetMemberConfigInformationFunction getMemberConfigFunction =
+      new GetMemberConfigInformationFunction();
+
+  @CliCommand(value = {CliStrings.DESCRIBE_CONFIG}, help = CliStrings.DESCRIBE_CONFIG__HELP)
+  @CliMetaData(relatedTopic = {CliStrings.TOPIC_GEODE_CONFIG})
+  @ResourceOperation(resource = ResourcePermission.Resource.CLUSTER,
+      operation = ResourcePermission.Operation.READ)
+  public Result describeConfig(
+      @CliOption(key = CliStrings.MEMBER, optionContext = ConverterHint.ALL_MEMBER_IDNAME,
+          help = CliStrings.DESCRIBE_CONFIG__MEMBER__HELP, mandatory = true) String memberNameOrId,
+      @CliOption(key = CliStrings.DESCRIBE_CONFIG__HIDE__DEFAULTS,
+          help = CliStrings.DESCRIBE_CONFIG__HIDE__DEFAULTS__HELP, unspecifiedDefaultValue = "true",
+          specifiedDefaultValue = "true") boolean hideDefaults) {
+
+    Result result = null;
+    try {
+      DistributedMember targetMember = null;
+
+      if (memberNameOrId != null && !memberNameOrId.isEmpty()) {
+        targetMember = CliUtil.getDistributedMemberByNameOrId(memberNameOrId);
+      }
+      if (targetMember != null) {
+        ResultCollector<?, ?> rc =
+            CliUtil.executeFunction(getMemberConfigFunction, hideDefaults, targetMember);
+        ArrayList<?> output = (ArrayList<?>) rc.getResult();
+        Object obj = output.get(0);
+
+        if (obj != null && obj instanceof MemberConfigurationInfo) {
+          MemberConfigurationInfo memberConfigInfo = (MemberConfigurationInfo) obj;
+
+          CompositeResultData crd = ResultBuilder.createCompositeResultData();
+          crd.setHeader(
+              CliStrings.format(CliStrings.DESCRIBE_CONFIG__HEADER__TEXT, memberNameOrId));
+
+          List<String> jvmArgsList = memberConfigInfo.getJvmInputArguments();
+          TabularResultData jvmInputArgs = crd.addSection().addSection().addTable();
+
+          for (String jvmArg : jvmArgsList) {
+            jvmInputArgs.accumulate("JVM command line arguments", jvmArg);
+          }
+
+          addSection(crd, memberConfigInfo.getGfePropsSetUsingApi(),
+              "GemFire properties defined using the API");
+          addSection(crd, memberConfigInfo.getGfePropsRuntime(),
+              "GemFire properties defined at the runtime");
+          addSection(crd, memberConfigInfo.getGfePropsSetFromFile(),
+              "GemFire properties defined with the property file");
+          addSection(crd, memberConfigInfo.getGfePropsSetWithDefaults(),
+              "GemFire properties using default values");
+          addSection(crd, memberConfigInfo.getCacheAttributes(), "Cache attributes");
+
+          List<Map<String, String>> cacheServerAttributesList =
+              memberConfigInfo.getCacheServerAttributes();
+
+          if (cacheServerAttributesList != null && !cacheServerAttributesList.isEmpty()) {
+            CompositeResultData.SectionResultData cacheServerSection = crd.addSection();
+            cacheServerSection.setHeader("Cache-server attributes");
+
+            for (Map<String, String> cacheServerAttributes : cacheServerAttributesList) {
+              addSubSection(cacheServerSection, cacheServerAttributes);
+            }
+          }
+          result = ResultBuilder.buildResult(crd);
+        }
+
+      } else {
+        ErrorResultData erd = ResultBuilder.createErrorResultData();
+        erd.addLine(CliStrings.format(CliStrings.DESCRIBE_CONFIG__MEMBER__NOT__FOUND,
+            new Object[] {memberNameOrId}));
+        result = ResultBuilder.buildResult(erd);
+      }
+    } catch (FunctionInvocationTargetException e) {
+      result = ResultBuilder.createGemFireErrorResult(CliStrings
+          .format(CliStrings.COULD_NOT_EXECUTE_COMMAND_TRY_AGAIN, CliStrings.DESCRIBE_CONFIG));
+    } catch (Exception e) {
+      ErrorResultData erd = ResultBuilder.createErrorResultData();
+      erd.addLine(e.getMessage());
+      result = ResultBuilder.buildResult(erd);
+    }
+    return result;
+  }
+
+  private void addSection(CompositeResultData crd, Map<String, String> attrMap, String headerText) {
+    if (attrMap != null && !attrMap.isEmpty()) {
+      CompositeResultData.SectionResultData section = crd.addSection();
+      section.setHeader(headerText);
+      section.addSeparator('.');
+      Set<String> attributes = new TreeSet<>(attrMap.keySet());
+
+      for (String attribute : attributes) {
+        String attributeValue = attrMap.get(attribute);
+        section.addData(attribute, attributeValue);
+      }
+    }
+  }
+
+  private void addSubSection(CompositeResultData.SectionResultData section,
+      Map<String, String> attrMap) {
+    if (!attrMap.isEmpty()) {
+      CompositeResultData.SectionResultData subSection = section.addSection();
+      Set<String> attributes = new TreeSet<>(attrMap.keySet());
+      subSection.setHeader("");
+
+      for (String attribute : attributes) {
+        String attributeValue = attrMap.get(attribute);
+        subSection.addData(attribute, attributeValue);
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/3bfe7a20/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportConfigCommand.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportConfigCommand.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportConfigCommand.java
new file mode 100644
index 0000000..672ec88
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportConfigCommand.java
@@ -0,0 +1,159 @@
+/*
+ * 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.geode.management.internal.cli.commands;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.springframework.shell.core.annotation.CliCommand;
+import org.springframework.shell.core.annotation.CliOption;
+
+import org.apache.geode.SystemFailure;
+import org.apache.geode.cache.execute.ResultCollector;
+import org.apache.geode.distributed.DistributedMember;
+import org.apache.geode.management.cli.CliMetaData;
+import org.apache.geode.management.cli.ConverterHint;
+import org.apache.geode.management.cli.Result;
+import org.apache.geode.management.internal.cli.AbstractCliAroundInterceptor;
+import org.apache.geode.management.internal.cli.CliUtil;
+import org.apache.geode.management.internal.cli.GfshParseResult;
+import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
+import org.apache.geode.management.internal.cli.functions.ExportConfigFunction;
+import org.apache.geode.management.internal.cli.i18n.CliStrings;
+import org.apache.geode.management.internal.cli.result.InfoResultData;
+import org.apache.geode.management.internal.cli.result.ResultBuilder;
+import org.apache.geode.management.internal.cli.shell.Gfsh;
+import org.apache.geode.management.internal.security.ResourceOperation;
+import org.apache.geode.security.ResourcePermission;
+
+public class ExportConfigCommand implements GfshCommand {
+  private final ExportConfigFunction exportConfigFunction = new ExportConfigFunction();
+
+  /**
+   * Export the cache configuration in XML format.
+   *
+   * @param member Member for which to write the configuration
+   * @param group Group or groups for which to write the configuration
+   * @return Results of the attempt to write the configuration
+   */
+  @CliCommand(value = {CliStrings.EXPORT_CONFIG}, help = CliStrings.EXPORT_CONFIG__HELP)
+  @CliMetaData(
+      interceptor = "org.apache.geode.management.internal.cli.commands.ExportConfigCommand$Interceptor",
+      relatedTopic = {CliStrings.TOPIC_GEODE_CONFIG})
+  @ResourceOperation(resource = ResourcePermission.Resource.CLUSTER,
+      operation = ResourcePermission.Operation.READ)
+  public Result exportConfig(
+      @CliOption(key = {CliStrings.MEMBER, CliStrings.MEMBERS},
+          optionContext = ConverterHint.ALL_MEMBER_IDNAME,
+          help = CliStrings.EXPORT_CONFIG__MEMBER__HELP) String[] member,
+      @CliOption(key = {CliStrings.GROUP, CliStrings.GROUPS},
+          optionContext = ConverterHint.MEMBERGROUP,
+          help = CliStrings.EXPORT_CONFIG__GROUP__HELP) String[] group,
+      @CliOption(key = {CliStrings.EXPORT_CONFIG__DIR},
+          help = CliStrings.EXPORT_CONFIG__DIR__HELP) String dir) {
+    InfoResultData infoData = ResultBuilder.createInfoResultData();
+
+    Set<DistributedMember> targetMembers = CliUtil.findMembers(group, member);
+    if (targetMembers.isEmpty()) {
+      return ResultBuilder.createUserErrorResult(CliStrings.NO_MEMBERS_FOUND_MESSAGE);
+    }
+
+    try {
+      ResultCollector<?, ?> rc =
+          CliUtil.executeFunction(this.exportConfigFunction, null, targetMembers);
+      List<CliFunctionResult> results = CliFunctionResult.cleanResults((List<?>) rc.getResult());
+
+      for (CliFunctionResult result : results) {
+        if (result.getThrowable() != null) {
+          infoData.addLine(CliStrings.format(CliStrings.EXPORT_CONFIG__MSG__EXCEPTION,
+              result.getMemberIdOrName(), result.getThrowable()));
+        } else if (result.isSuccessful()) {
+          String cacheFileName = result.getMemberIdOrName() + "-cache.xml";
+          String propsFileName = result.getMemberIdOrName() + "-gf.properties";
+          String[] fileContent = (String[]) result.getSerializables();
+          infoData.addAsFile(cacheFileName, fileContent[0], "Downloading Cache XML file: {0}",
+              false);
+          infoData.addAsFile(propsFileName, fileContent[1], "Downloading properties file: {0}",
+              false);
+        }
+      }
+      return ResultBuilder.buildResult(infoData);
+    } catch (VirtualMachineError e) {
+      SystemFailure.initiateFailure(e);
+      throw e;
+    } catch (Throwable th) {
+      SystemFailure.checkFailure();
+      th.printStackTrace(System.err);
+      return ResultBuilder
+          .createGemFireErrorResult(CliStrings.format(CliStrings.EXPORT_CONFIG__MSG__EXCEPTION,
+              th.getClass().getName() + ": " + th.getMessage()));
+    }
+  }
+
+  /**
+   * Interceptor used by gfsh to intercept execution of export config command at "shell".
+   */
+  public static class Interceptor extends AbstractCliAroundInterceptor {
+    private String saveDirString;
+
+    @Override
+    public Result preExecution(GfshParseResult parseResult) {
+      Map<String, String> paramValueMap = parseResult.getParamValueStrings();
+      String dir = paramValueMap.get("dir");
+      dir = (dir == null) ? null : dir.trim();
+
+      File saveDirFile = new File(".");
+      if (dir != null && !dir.isEmpty()) {
+        saveDirFile = new File(dir);
+        if (saveDirFile.exists()) {
+          if (!saveDirFile.isDirectory())
+            return ResultBuilder.createGemFireErrorResult(
+                CliStrings.format(CliStrings.EXPORT_CONFIG__MSG__NOT_A_DIRECTORY, dir));
+        } else if (!saveDirFile.mkdirs()) {
+          return ResultBuilder.createGemFireErrorResult(
+              CliStrings.format(CliStrings.EXPORT_CONFIG__MSG__CANNOT_CREATE_DIR, dir));
+        }
+      }
+      try {
+        if (!saveDirFile.canWrite()) {
+          return ResultBuilder.createGemFireErrorResult(CliStrings.format(
+              CliStrings.EXPORT_CONFIG__MSG__NOT_WRITEABLE, saveDirFile.getCanonicalPath()));
+        }
+      } catch (IOException ioex) {
+        return ResultBuilder.createGemFireErrorResult(
+            CliStrings.format(CliStrings.EXPORT_CONFIG__MSG__NOT_WRITEABLE, saveDirFile.getName()));
+      }
+
+      saveDirString = saveDirFile.getAbsolutePath();
+      return ResultBuilder.createInfoResult("OK");
+    }
+
+    @Override
+    public Result postExecution(GfshParseResult parseResult, Result commandResult, Path tempFile) {
+      if (commandResult.hasIncomingFiles()) {
+        try {
+          commandResult.saveIncomingFiles(saveDirString);
+        } catch (IOException ioex) {
+          Gfsh.getCurrentInstance().logSevere("Unable to export config", ioex);
+        }
+      }
+      return commandResult;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/3bfe7a20/geode-core/src/main/java/org/apache/geode/management/internal/web/controllers/ConfigCommandsController.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/web/controllers/ConfigCommandsController.java b/geode-core/src/main/java/org/apache/geode/management/internal/web/controllers/ConfigCommandsController.java
index 9f06ea3..d223a9f 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/web/controllers/ConfigCommandsController.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/web/controllers/ConfigCommandsController.java
@@ -14,10 +14,9 @@
  */
 package org.apache.geode.management.internal.web.controllers;
 
-import org.apache.geode.internal.lang.StringUtils;
-import org.apache.geode.management.internal.cli.i18n.CliStrings;
-import org.apache.geode.management.internal.cli.util.CommandStringBuilder;
-import org.apache.geode.management.internal.web.util.ConvertUtils;
+import java.io.IOException;
+import java.util.concurrent.Callable;
+
 import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.PathVariable;
@@ -27,15 +26,19 @@ import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.ResponseBody;
 import org.springframework.web.multipart.MultipartFile;
 
-import java.io.IOException;
-import java.util.concurrent.Callable;
+import org.apache.geode.internal.lang.StringUtils;
+import org.apache.geode.management.internal.cli.i18n.CliStrings;
+import org.apache.geode.management.internal.cli.util.CommandStringBuilder;
+import org.apache.geode.management.internal.web.util.ConvertUtils;
 
 /**
  * The ConfigCommandsController class implements GemFire Management REST API web service endpoints
  * for the Gfsh Config Commands.
  * <p/>
  * 
- * @see org.apache.geode.management.internal.cli.commands.ConfigCommands
+ * @see org.apache.geode.management.internal.cli.commands.AlterRuntimeConfigCommand
+ * @see org.apache.geode.management.internal.cli.commands.DescribeConfigCommand
+ * @see org.apache.geode.management.internal.cli.commands.ExportConfigCommand
  * @see org.apache.geode.management.internal.web.controllers.AbstractMultiPartCommandsController
  * @see org.springframework.stereotype.Controller
  * @see org.springframework.web.bind.annotation.PathVariable

http://git-wip-us.apache.org/repos/asf/geode/blob/3bfe7a20/geode-core/src/main/java/org/apache/geode/management/internal/web/controllers/DeployCommandsController.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/web/controllers/DeployCommandsController.java b/geode-core/src/main/java/org/apache/geode/management/internal/web/controllers/DeployCommandsController.java
index 23c5083..f1cb1c7 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/web/controllers/DeployCommandsController.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/web/controllers/DeployCommandsController.java
@@ -14,10 +14,8 @@
  */
 package org.apache.geode.management.internal.web.controllers;
 
-import org.apache.geode.internal.lang.StringUtils;
-import org.apache.geode.management.internal.cli.i18n.CliStrings;
-import org.apache.geode.management.internal.cli.util.CommandStringBuilder;
-import org.apache.geode.management.internal.web.util.ConvertUtils;
+import java.io.IOException;
+
 import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
@@ -25,14 +23,19 @@ import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.ResponseBody;
 import org.springframework.web.multipart.MultipartFile;
 
-import java.io.IOException;
+import org.apache.geode.internal.lang.StringUtils;
+import org.apache.geode.management.internal.cli.i18n.CliStrings;
+import org.apache.geode.management.internal.cli.util.CommandStringBuilder;
+import org.apache.geode.management.internal.web.util.ConvertUtils;
 
 /**
  * The DeployCommandsController class implements the GemFire Management REST API web service
  * endpoints for the Gfsh Deploy Commands.
  * <p/>
- * 
- * @see org.apache.geode.management.internal.cli.commands.ConfigCommands
+ *
+ * @see org.apache.geode.management.internal.cli.commands.DeployCommand
+ * @see org.apache.geode.management.internal.cli.commands.UndeployCommand
+ * @see org.apache.geode.management.internal.cli.commands.ListDeployedCommand
  * @see org.apache.geode.management.internal.web.controllers.AbstractMultiPartCommandsController
  * @see org.springframework.stereotype.Controller
  * @see org.springframework.web.bind.annotation.RequestMapping
@@ -61,8 +64,6 @@ public class DeployCommandsController extends AbstractMultiPartCommandsControlle
 
   @RequestMapping(method = RequestMethod.POST, value = "/deployed")
   @ResponseBody
-  // final MultipartHttpServletRequest request
-  // @RequestPart(RESOURCES_REQUEST_PARAMETER) final Resource[] jarFileResources,
   public String deploy(
       @RequestParam(RESOURCES_REQUEST_PARAMETER) final MultipartFile[] jarFileResources,
       @RequestParam(value = CliStrings.GROUP, required = false) final String[] groups,

http://git-wip-us.apache.org/repos/asf/geode/blob/3bfe7a20/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/LogLevelInterceptorTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/LogLevelInterceptorTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/LogLevelInterceptorTest.java
index 9feac1a..dd9fd24 100644
--- a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/LogLevelInterceptorTest.java
+++ b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/LogLevelInterceptorTest.java
@@ -43,7 +43,7 @@ public class LogLevelInterceptorTest {
   @Before
   public void before() {
     interceptors.add(new ExportLogsInterceptor());
-    interceptors.add(new ConfigCommands.AlterRuntimeInterceptor());
+    interceptors.add(new AlterRuntimeConfigCommand.AlterRuntimeInterceptor());
     interceptors.add(new ChangeLogLevelCommand.ChangeLogLevelCommandInterceptor());
 
     parseResult = Mockito.mock(GfshParseResult.class);

http://git-wip-us.apache.org/repos/asf/geode/blob/3bfe7a20/geode-core/src/test/java/org/apache/geode/management/internal/security/TestCommand.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/security/TestCommand.java b/geode-core/src/test/java/org/apache/geode/management/internal/security/TestCommand.java
index 038e8cf..853853b 100644
--- a/geode-core/src/test/java/org/apache/geode/management/internal/security/TestCommand.java
+++ b/geode-core/src/test/java/org/apache/geode/management/internal/security/TestCommand.java
@@ -123,7 +123,7 @@ public class TestCommand {
     createTestCommand("list clients", clusterRead);
     createTestCommand("describe client --clientID=172.16.196.144", clusterRead);
 
-    // ConfigCommands
+    // AlterRuntimeConfigCommand, DescribeConfigCommand, ExportConfigCommand (config commands)
     createTestCommand("alter runtime", clusterManage);
     createTestCommand("describe config --member=Member1", clusterRead);
     createTestCommand("export config --member=member1", clusterRead);