This is an automated email from the ASF dual-hosted git repository.

sai_boorlagadda pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/geode.git


The following commit(s) were added to refs/heads/develop by this push:
     new a881a79  GEODE-5070: Support --member option for describe & list jdbc 
connecto… (#1798)
a881a79 is described below

commit a881a790da13c698a38a735d471df0871b552a7b
Author: Sai Boorlagadda <[email protected]>
AuthorDate: Tue Apr 17 18:33:01 2018 -0700

    GEODE-5070: Support --member option for describe & list jdbc connecto… 
(#1798)
    
        When cluster configuration service is disabled user
        have to provide --member option in-order to describe
        and list connections and mappings.
---
 .../internal/cli/DescribeConnectionCommand.java    |  36 ++++-
 .../internal/cli/DescribeConnectionFunction.java   |  33 ++++
 .../jdbc/internal/cli/DescribeMappingCommand.java  |  33 +++-
 .../jdbc/internal/cli/DescribeMappingFunction.java |  33 ++++
 .../jdbc/internal/cli/ListConnectionCommand.java   |  34 ++++-
 .../jdbc/internal/cli/ListConnectionFunction.java  |  35 +++++
 .../jdbc/internal/cli/ListMappingCommand.java      |  34 ++++-
 .../jdbc/internal/cli/ListMappingFunction.java     |  35 +++++
 .../sanctioned-geode-connectors-serializables.txt  |   4 +
 .../cli/DescribeConnectionCommandDUnitTest.java    |  56 ++++---
 .../cli/DescribeConnectionCommandTest.java         |  34 +++++
 .../cli/DescribeConnectionFunctionTest.java        | 138 +++++++++++++++++
 .../cli/DescribeMappingCommandDUnitTest.java       |  50 +++---
 .../internal/cli/DescribeMappingCommandTest.java   |  44 +++++-
 .../internal/cli/DescribeMappingFunctionTest.java  | 138 +++++++++++++++++
 .../cli/ListConnectionCommandDUnitTest.java        |  21 +++
 .../internal/cli/ListConnectionCommandTest.java    |  42 ++++-
 .../internal/cli/ListConnectionFunctionTest.java   | 169 ++++++++++++++++++++
 .../internal/cli/ListMappingCommandDUnitTest.java  |  24 +++
 .../jdbc/internal/cli/ListMappingCommandTest.java  |  48 ++++++
 .../jdbc/internal/cli/ListMappingFunctionTest.java | 170 +++++++++++++++++++++
 21 files changed, 1157 insertions(+), 54 deletions(-)

diff --git 
a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeConnectionCommand.java
 
b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeConnectionCommand.java
index 2c5190e..4b6751f 100644
--- 
a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeConnectionCommand.java
+++ 
b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeConnectionCommand.java
@@ -20,12 +20,18 @@ import static 
org.apache.geode.connectors.jdbc.internal.cli.CreateConnectionComm
 import static 
org.apache.geode.connectors.jdbc.internal.cli.CreateConnectionCommand.CREATE_CONNECTION__URL;
 import static 
org.apache.geode.connectors.jdbc.internal.cli.CreateConnectionCommand.CREATE_CONNECTION__USER;
 
+import java.util.List;
+
+import org.apache.logging.log4j.Logger;
 import org.springframework.shell.core.annotation.CliCommand;
 import org.springframework.shell.core.annotation.CliOption;
 
 import 
org.apache.geode.connectors.jdbc.internal.configuration.ConnectorService;
 import org.apache.geode.distributed.ClusterConfigurationService;
+import org.apache.geode.distributed.DistributedMember;
+import org.apache.geode.internal.logging.LogService;
 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.commands.InternalGfshCommand;
 import 
org.apache.geode.management.internal.cli.exceptions.EntityNotFoundException;
@@ -37,12 +43,15 @@ import 
org.apache.geode.management.internal.security.ResourceOperation;
 import org.apache.geode.security.ResourcePermission;
 
 public class DescribeConnectionCommand extends InternalGfshCommand {
+  private static Logger logger = LogService.getLogger();
   static final String DESCRIBE_CONNECTION = "describe jdbc-connection";
   static final String DESCRIBE_CONNECTION__HELP =
       "Describe the specified jdbc connection found in cluster configuration.";
   static final String DESCRIBE_CONNECTION__NAME = "name";
   static final String DESCRIBE_CONNECTION__NAME__HELP =
       "Name of the jdbc connection to be described.";
+  static final String DESCRIBE_CONNECTION_MEMBER__HELP =
+      "Member(s) from which the specified jdbc connections is retrieved.";
 
   static final String OBSCURED_PASSWORD = "********";
   static final String RESULT_SECTION_NAME = "ConnectionDescription";
@@ -51,12 +60,33 @@ public class DescribeConnectionCommand extends 
InternalGfshCommand {
   @CliMetaData(relatedTopic = CliStrings.DEFAULT_TOPIC_GEODE)
   @ResourceOperation(resource = ResourcePermission.Resource.CLUSTER,
       operation = ResourcePermission.Operation.MANAGE)
-  public Result describeConnection(@CliOption(key = DESCRIBE_CONNECTION__NAME, 
mandatory = true,
-      help = DESCRIBE_CONNECTION__NAME__HELP) String name) {
+  public Result describeConnection(
+      @CliOption(key = DESCRIBE_CONNECTION__NAME, mandatory = true,
+          help = DESCRIBE_CONNECTION__NAME__HELP) String name,
+      @CliOption(key = {CliStrings.MEMBER}, optionContext = 
ConverterHint.MEMBERIDNAME,
+          help = DESCRIBE_CONNECTION_MEMBER__HELP) String onMember) {
+
+    // when member is specified, we go to each member and describe what are on 
the members
+    if (onMember != null) {
+      DistributedMember member = getMember(onMember);
+      if (member == null) {
+        return 
ResultBuilder.createUserErrorResult(CliStrings.NO_MEMBERS_FOUND_MESSAGE);
+      }
+
+      List<?> result =
+          (List<?>) executeFunction(new DescribeConnectionFunction(), name, 
member).getResult();
+      ConnectorService.Connection connection = (ConnectorService.Connection) 
result.get(0);
+      CompositeResultData resultData = 
ResultBuilder.createCompositeResultData();
+      fillResultData(connection, resultData);
+
+      return ResultBuilder.buildResult(resultData);
+    }
 
+    // otherwise, use cluster configuration to describe the connections
     ClusterConfigurationService ccService = getConfigurationService();
     if (ccService == null) {
-      return ResultBuilder.createInfoResult("cluster configuration service is 
not running");
+      return ResultBuilder.createInfoResult(
+          "cluster configuration service is not running. Use --member option 
to describe connections on specific members.");
     }
     // search for the connection that has this id to see if it exists
     ConnectorService service =
diff --git 
a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeConnectionFunction.java
 
b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeConnectionFunction.java
new file mode 100644
index 0000000..d8f9def
--- /dev/null
+++ 
b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeConnectionFunction.java
@@ -0,0 +1,33 @@
+/*
+ * 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.connectors.jdbc.internal.cli;
+
+import org.apache.geode.cache.execute.FunctionContext;
+import org.apache.geode.connectors.jdbc.internal.JdbcConnectorService;
+import 
org.apache.geode.connectors.jdbc.internal.configuration.ConnectorService;
+
+public class DescribeConnectionFunction
+    extends JdbcCliFunction<String, ConnectorService.Connection> {
+
+  DescribeConnectionFunction() {
+    super();
+  }
+
+  @Override
+  ConnectorService.Connection getFunctionResult(JdbcConnectorService service,
+      FunctionContext<String> context) {
+    return service.getConnectionConfig(context.getArguments());
+  }
+}
diff --git 
a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeMappingCommand.java
 
b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeMappingCommand.java
index 224a832..b6948b2 100644
--- 
a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeMappingCommand.java
+++ 
b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeMappingCommand.java
@@ -20,12 +20,16 @@ import static 
org.apache.geode.connectors.jdbc.internal.cli.CreateMappingCommand
 import static 
org.apache.geode.connectors.jdbc.internal.cli.CreateMappingCommand.CREATE_MAPPING__TABLE_NAME;
 import static 
org.apache.geode.connectors.jdbc.internal.cli.CreateMappingCommand.CREATE_MAPPING__VALUE_CONTAINS_PRIMARY_KEY;
 
+import java.util.List;
+
 import org.springframework.shell.core.annotation.CliCommand;
 import org.springframework.shell.core.annotation.CliOption;
 
 import 
org.apache.geode.connectors.jdbc.internal.configuration.ConnectorService;
 import org.apache.geode.distributed.ClusterConfigurationService;
+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.commands.InternalGfshCommand;
 import 
org.apache.geode.management.internal.cli.exceptions.EntityNotFoundException;
@@ -42,6 +46,8 @@ public class DescribeMappingCommand extends 
InternalGfshCommand {
   static final String DESCRIBE_MAPPING__REGION_NAME = "region";
   static final String DESCRIBE_MAPPING__REGION_NAME__HELP =
       "Region name of the jdbc mapping to be described.";
+  static final String DESCRIBE_MAPPING_MEMBER__HELP =
+      "Member(s) from which the specified jdbc mapping is retrieved.";
 
   static final String RESULT_SECTION_NAME = "MappingDescription";
   static final String FIELD_TO_COLUMN_TABLE = "fieldToColumnTable";
@@ -50,12 +56,33 @@ public class DescribeMappingCommand extends 
InternalGfshCommand {
   @CliMetaData(relatedTopic = CliStrings.DEFAULT_TOPIC_GEODE)
   @ResourceOperation(resource = ResourcePermission.Resource.CLUSTER,
       operation = ResourcePermission.Operation.MANAGE)
-  public Result describeMapping(@CliOption(key = 
DESCRIBE_MAPPING__REGION_NAME, mandatory = true,
-      help = DESCRIBE_MAPPING__REGION_NAME__HELP) String regionName) {
+  public Result describeMapping(
+      @CliOption(key = DESCRIBE_MAPPING__REGION_NAME, mandatory = true,
+          help = DESCRIBE_MAPPING__REGION_NAME__HELP) String regionName,
+      @CliOption(key = {CliStrings.MEMBER}, optionContext = 
ConverterHint.MEMBERIDNAME,
+          help = DESCRIBE_MAPPING_MEMBER__HELP) String onMember) {
+
+    // when member is specified, we go to each member and describe what are on 
the members
+    if (onMember != null) {
+      DistributedMember member = getMember(onMember);
+      if (member == null) {
+        return 
ResultBuilder.createUserErrorResult(CliStrings.NO_MEMBERS_FOUND_MESSAGE);
+      }
+
+      List<?> result =
+          (List<?>) executeFunction(new DescribeMappingFunction(), regionName, 
member).getResult();
+      ConnectorService.RegionMapping mapping = 
(ConnectorService.RegionMapping) result.get(0);
+      CompositeResultData resultData = 
ResultBuilder.createCompositeResultData();
+      fillResultData(mapping, resultData);
+
+      return ResultBuilder.buildResult(resultData);
+    }
 
+    // otherwise, use cluster configuration to describe the connections
     ClusterConfigurationService ccService = getConfigurationService();
     if (ccService == null) {
-      return ResultBuilder.createInfoResult("cluster configuration service is 
not running");
+      return ResultBuilder.createInfoResult(
+          "cluster configuration service is not running. Use --member option 
to describe mappings on specific members.");
     }
     // search for the connection that has this id to see if it exists
     ConnectorService service =
diff --git 
a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeMappingFunction.java
 
b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeMappingFunction.java
new file mode 100644
index 0000000..a35a9f2
--- /dev/null
+++ 
b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeMappingFunction.java
@@ -0,0 +1,33 @@
+/*
+ * 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.connectors.jdbc.internal.cli;
+
+import org.apache.geode.cache.execute.FunctionContext;
+import org.apache.geode.connectors.jdbc.internal.JdbcConnectorService;
+import 
org.apache.geode.connectors.jdbc.internal.configuration.ConnectorService;
+
+public class DescribeMappingFunction
+    extends JdbcCliFunction<String, ConnectorService.RegionMapping> {
+
+  DescribeMappingFunction() {
+    super();
+  }
+
+  @Override
+  ConnectorService.RegionMapping getFunctionResult(JdbcConnectorService 
service,
+      FunctionContext<String> context) {
+    return service.getMappingForRegion(context.getArguments());
+  }
+}
diff --git 
a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/ListConnectionCommand.java
 
b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/ListConnectionCommand.java
index 39e32d8..79a2756 100644
--- 
a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/ListConnectionCommand.java
+++ 
b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/ListConnectionCommand.java
@@ -14,13 +14,18 @@
  */
 package org.apache.geode.connectors.jdbc.internal.cli;
 
+import java.util.Collection;
 import java.util.List;
+import java.util.Set;
 
 import org.springframework.shell.core.annotation.CliCommand;
+import org.springframework.shell.core.annotation.CliOption;
 
 import 
org.apache.geode.connectors.jdbc.internal.configuration.ConnectorService;
 import org.apache.geode.distributed.ClusterConfigurationService;
+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.commands.InternalGfshCommand;
 import org.apache.geode.management.internal.cli.i18n.CliStrings;
@@ -36,16 +41,39 @@ public class ListConnectionCommand extends 
InternalGfshCommand {
 
   static final String LIST_OF_CONNECTIONS = "List of connections";
   static final String NO_CONNECTIONS_FOUND = "No connections found";
+  static final String LIST_CONNECTION_MEMBER__HELP =
+      "Member from which the jdbc connections are retrieved.";
 
   @CliCommand(value = LIST_JDBC_CONNECTION, help = LIST_JDBC_CONNECTION__HELP)
   @CliMetaData(relatedTopic = CliStrings.DEFAULT_TOPIC_GEODE)
   @ResourceOperation(resource = ResourcePermission.Resource.CLUSTER,
       operation = ResourcePermission.Operation.MANAGE)
-  public Result listConnection() {
+  public Result listConnection(
+      @CliOption(key = {CliStrings.MEMBER}, optionContext = 
ConverterHint.MEMBERIDNAME,
+          help = LIST_CONNECTION_MEMBER__HELP) String onMember) {
 
+    // when member is specified, we go to each member and describe what are on 
the members
+    if (onMember != null) {
+      DistributedMember member = getMember(onMember);
+      if (member == null) {
+        return 
ResultBuilder.createUserErrorResult(CliStrings.NO_MEMBERS_FOUND_MESSAGE);
+      }
+
+      List<?> result =
+          (List<?>) executeFunction(new ListConnectionFunction(), null, 
member).getResult();
+      Set<ConnectorService.Connection> connections =
+          (Set<ConnectorService.Connection>) result.get(0);
+      TabularResultData tabularResultData = 
ResultBuilder.createTabularResultData();
+      boolean connectionsExist = fillTabularResultData(connections, 
tabularResultData);
+
+      return createResult(tabularResultData, connectionsExist);
+    }
+
+    // otherwise, use cluster configuration to describe the connections
     ClusterConfigurationService ccService = getConfigurationService();
     if (ccService == null) {
-      return ResultBuilder.createInfoResult("cluster configuration service is 
not running");
+      return ResultBuilder.createInfoResult(
+          "cluster configuration service is not running. Use --member option 
to describe connections on specific members.");
     }
 
     ConnectorService service =
@@ -71,7 +99,7 @@ public class ListConnectionCommand extends 
InternalGfshCommand {
   /**
    * Returns true if any connections exist
    */
-  private boolean fillTabularResultData(List<ConnectorService.Connection> 
connections,
+  private boolean 
fillTabularResultData(Collection<ConnectorService.Connection> connections,
       TabularResultData tabularResultData) {
     for (ConnectorService.Connection connectionConfig : connections) {
       tabularResultData.accumulate(LIST_OF_CONNECTIONS, 
connectionConfig.getName());
diff --git 
a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/ListConnectionFunction.java
 
b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/ListConnectionFunction.java
new file mode 100644
index 0000000..9625ca1
--- /dev/null
+++ 
b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/ListConnectionFunction.java
@@ -0,0 +1,35 @@
+/*
+ * 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.connectors.jdbc.internal.cli;
+
+import java.util.Set;
+
+import org.apache.geode.cache.execute.FunctionContext;
+import org.apache.geode.connectors.jdbc.internal.JdbcConnectorService;
+import 
org.apache.geode.connectors.jdbc.internal.configuration.ConnectorService;
+
+public class ListConnectionFunction
+    extends JdbcCliFunction<Void, Set<ConnectorService.Connection>> {
+
+  ListConnectionFunction() {
+    super();
+  }
+
+  @Override
+  Set<ConnectorService.Connection> getFunctionResult(JdbcConnectorService 
service,
+      FunctionContext<Void> context) {
+    return service.getConnectionConfigs();
+  }
+}
diff --git 
a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/ListMappingCommand.java
 
b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/ListMappingCommand.java
index 0c01c9b..a24ef67 100644
--- 
a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/ListMappingCommand.java
+++ 
b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/ListMappingCommand.java
@@ -14,13 +14,18 @@
  */
 package org.apache.geode.connectors.jdbc.internal.cli;
 
+import java.util.Collection;
 import java.util.List;
+import java.util.Set;
 
 import org.springframework.shell.core.annotation.CliCommand;
+import org.springframework.shell.core.annotation.CliOption;
 
 import 
org.apache.geode.connectors.jdbc.internal.configuration.ConnectorService;
 import org.apache.geode.distributed.ClusterConfigurationService;
+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.commands.InternalGfshCommand;
 import org.apache.geode.management.internal.cli.i18n.CliStrings;
@@ -36,16 +41,39 @@ public class ListMappingCommand extends InternalGfshCommand 
{
 
   static final String LIST_OF_MAPPINGS = "List of mappings";
   static final String NO_MAPPINGS_FOUND = "No mappings found";
+  static final String LIST_MAPPINGS_MEMBER__HELP =
+      "Member from which the jdbc mappings are retrieved.";
 
   @CliCommand(value = LIST_MAPPING, help = LIST_MAPPING__HELP)
   @CliMetaData(relatedTopic = CliStrings.DEFAULT_TOPIC_GEODE)
   @ResourceOperation(resource = ResourcePermission.Resource.CLUSTER,
       operation = ResourcePermission.Operation.MANAGE)
-  public Result listMapping() {
+  public Result listMapping(
+      @CliOption(key = {CliStrings.MEMBER}, optionContext = 
ConverterHint.MEMBERIDNAME,
+          help = LIST_MAPPINGS_MEMBER__HELP) String onMember) {
 
+    // when member is specified, we go to each member and describe what are on 
the members
+    if (onMember != null) {
+      DistributedMember member = getMember(onMember);
+      if (member == null) {
+        return 
ResultBuilder.createUserErrorResult(CliStrings.NO_MEMBERS_FOUND_MESSAGE);
+      }
+
+      List<?> result =
+          (List<?>) executeFunction(new ListMappingFunction(), null, 
member).getResult();
+      Set<ConnectorService.RegionMapping> mappings =
+          (Set<ConnectorService.RegionMapping>) result.get(0);
+      TabularResultData tabularResultData = 
ResultBuilder.createTabularResultData();
+      boolean connectionsExist = fillTabularResultData(mappings, 
tabularResultData);
+
+      return createResult(tabularResultData, connectionsExist);
+    }
+
+    // otherwise, use cluster configuration to describe the connections
     ClusterConfigurationService ccService = getConfigurationService();
     if (ccService == null) {
-      return ResultBuilder.createInfoResult("cluster configuration service is 
not running");
+      return ResultBuilder.createInfoResult(
+          "cluster configuration service is not running. Use --member option 
to describe mappings on specific members.");
     }
 
     ConnectorService service =
@@ -71,7 +99,7 @@ public class ListMappingCommand extends InternalGfshCommand {
   /**
    * Returns true if any connections exist
    */
-  private boolean fillTabularResultData(List<ConnectorService.RegionMapping> 
mappings,
+  private boolean 
fillTabularResultData(Collection<ConnectorService.RegionMapping> mappings,
       TabularResultData tabularResultData) {
     for (ConnectorService.RegionMapping mapping : mappings) {
       tabularResultData.accumulate(LIST_OF_MAPPINGS, mapping.getRegionName());
diff --git 
a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/ListMappingFunction.java
 
b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/ListMappingFunction.java
new file mode 100644
index 0000000..8996307
--- /dev/null
+++ 
b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/ListMappingFunction.java
@@ -0,0 +1,35 @@
+/*
+ * 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.connectors.jdbc.internal.cli;
+
+import java.util.Set;
+
+import org.apache.geode.cache.execute.FunctionContext;
+import org.apache.geode.connectors.jdbc.internal.JdbcConnectorService;
+import 
org.apache.geode.connectors.jdbc.internal.configuration.ConnectorService;
+
+public class ListMappingFunction
+    extends JdbcCliFunction<Void, Set<ConnectorService.RegionMapping>> {
+
+  ListMappingFunction() {
+    super();
+  }
+
+  @Override
+  Set<ConnectorService.RegionMapping> getFunctionResult(JdbcConnectorService 
service,
+      FunctionContext<Void> context) {
+    return service.getRegionMappings();
+  }
+}
diff --git 
a/geode-connectors/src/main/resources/org/apache/geode/internal/sanctioned-geode-connectors-serializables.txt
 
b/geode-connectors/src/main/resources/org/apache/geode/internal/sanctioned-geode-connectors-serializables.txt
index dc3081c..39512f3 100755
--- 
a/geode-connectors/src/main/resources/org/apache/geode/internal/sanctioned-geode-connectors-serializables.txt
+++ 
b/geode-connectors/src/main/resources/org/apache/geode/internal/sanctioned-geode-connectors-serializables.txt
@@ -7,9 +7,13 @@ 
org/apache/geode/connectors/jdbc/internal/cli/AlterConnectionFunction,false
 org/apache/geode/connectors/jdbc/internal/cli/AlterMappingFunction,false
 org/apache/geode/connectors/jdbc/internal/cli/CreateConnectionFunction,false
 org/apache/geode/connectors/jdbc/internal/cli/CreateMappingFunction,false
+org/apache/geode/connectors/jdbc/internal/cli/DescribeConnectionFunction,false
+org/apache/geode/connectors/jdbc/internal/cli/DescribeMappingFunction,false
 org/apache/geode/connectors/jdbc/internal/cli/DestroyConnectionFunction,false
 org/apache/geode/connectors/jdbc/internal/cli/DestroyMappingFunction,false
 org/apache/geode/connectors/jdbc/internal/cli/JdbcCliFunction,false
+org/apache/geode/connectors/jdbc/internal/cli/ListConnectionFunction,false
+org/apache/geode/connectors/jdbc/internal/cli/ListMappingFunction,false
 
org/apache/geode/connectors/jdbc/internal/configuration/ConnectorService,false,connection:java/util/List,name:java/lang/String,regionMapping:java/util/List
 
org/apache/geode/connectors/jdbc/internal/configuration/ConnectorService$Connection,false,name:java/lang/String,parameterMap:java/util/Map,parameters:java/lang/String,password:java/lang/String,url:java/lang/String,user:java/lang/String
 
org/apache/geode/connectors/jdbc/internal/configuration/ConnectorService$RegionMapping,false,connectionConfigName:java/lang/String,fieldMapping:java/util/List,fieldMappingModified:boolean,pdxClassName:java/lang/String,primaryKeyInValue:java/lang/Boolean,regionName:java/lang/String,tableName:java/lang/String
diff --git 
a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeConnectionCommandDUnitTest.java
 
b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeConnectionCommandDUnitTest.java
index 6b5fcdf..85a13da 100644
--- 
a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeConnectionCommandDUnitTest.java
+++ 
b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeConnectionCommandDUnitTest.java
@@ -23,10 +23,8 @@ import static 
org.apache.geode.connectors.jdbc.internal.cli.CreateConnectionComm
 import static 
org.apache.geode.connectors.jdbc.internal.cli.DescribeConnectionCommand.DESCRIBE_CONNECTION;
 import static 
org.apache.geode.connectors.jdbc.internal.cli.DescribeConnectionCommand.DESCRIBE_CONNECTION__NAME;
 
-import java.io.Serializable;
-
-import org.junit.Before;
-import org.junit.Rule;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 
@@ -36,34 +34,27 @@ import org.apache.geode.test.dunit.rules.MemberVM;
 import org.apache.geode.test.junit.assertions.CommandResultAssert;
 import org.apache.geode.test.junit.categories.DistributedTest;
 import org.apache.geode.test.junit.rules.GfshCommandRule;
-import org.apache.geode.test.junit.rules.serializable.SerializableTestName;
 
 @Category(DistributedTest.class)
-public class DescribeConnectionCommandDUnitTest implements Serializable {
+public class DescribeConnectionCommandDUnitTest {
 
   private static final String CONNECTION_NAME = "connectionName";
 
-  @Rule
-  public transient GfshCommandRule gfsh = new GfshCommandRule();
-
-  @Rule
-  public ClusterStartupRule startupRule = new ClusterStartupRule();
+  @ClassRule
+  public static GfshCommandRule gfsh = new GfshCommandRule();
 
-  @Rule
-  public SerializableTestName testName = new SerializableTestName();
+  @ClassRule
+  public static ClusterStartupRule startupRule = new ClusterStartupRule();
 
-  private MemberVM server;
+  private static MemberVM locator, server;
 
-  @Before
-  public void before() throws Exception {
-    MemberVM locator = startupRule.startLocatorVM(0);
+  @BeforeClass
+  public static void before() throws Exception {
+    locator = startupRule.startLocatorVM(0);
     server = startupRule.startServerVM(1, locator.getPort());
 
     gfsh.connectAndVerify(locator);
-  }
 
-  @Test
-  public void describesExistingConnection() {
     CommandStringBuilder csb = new CommandStringBuilder(CREATE_CONNECTION);
     csb.addOption(CREATE_CONNECTION__NAME, CONNECTION_NAME);
     csb.addOption(CREATE_CONNECTION__URL, "myUrl");
@@ -72,9 +63,12 @@ public class DescribeConnectionCommandDUnitTest implements 
Serializable {
     csb.addOption(CREATE_CONNECTION__PARAMS, "key1:value1,key2:value2");
 
     gfsh.executeAndAssertThat(csb.toString()).statusIsSuccess();
+  }
 
-    csb = new 
CommandStringBuilder(DESCRIBE_CONNECTION).addOption(DESCRIBE_CONNECTION__NAME,
-        CONNECTION_NAME);
+  @Test
+  public void describesExistingConnection() {
+    CommandStringBuilder csb = new CommandStringBuilder(DESCRIBE_CONNECTION)
+        .addOption(DESCRIBE_CONNECTION__NAME, CONNECTION_NAME);
 
     CommandResultAssert commandResultAssert = 
gfsh.executeAndAssertThat(csb.toString());
 
@@ -100,4 +94,22 @@ public class DescribeConnectionCommandDUnitTest implements 
Serializable {
     commandResultAssert.statusIsError();
     commandResultAssert.containsOutput(String.format("connection named 
'nonExisting' not found"));
   }
+
+  @Test
+  public void reportConfigurationFoundOnMember() {
+    CommandResultAssert commandResultAssert = gfsh
+        .executeAndAssertThat(
+            DESCRIBE_CONNECTION + " --name=" + CONNECTION_NAME + " 
--member=server-1")
+        .statusIsSuccess();
+
+    commandResultAssert.statusIsSuccess();
+    commandResultAssert.containsKeyValuePair("name", CONNECTION_NAME);
+    commandResultAssert.containsKeyValuePair("url", "myUrl");
+    commandResultAssert.containsKeyValuePair("user", "username");
+    commandResultAssert.containsKeyValuePair("password", 
"\\*\\*\\*\\*\\*\\*\\*\\*");
+    commandResultAssert.containsOutput("key1");
+    commandResultAssert.containsOutput("value1");
+    commandResultAssert.containsOutput("key2");
+    commandResultAssert.containsOutput("value2");
+  }
 }
diff --git 
a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeConnectionCommandTest.java
 
b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeConnectionCommandTest.java
index d1cba15..1b99234 100644
--- 
a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeConnectionCommandTest.java
+++ 
b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeConnectionCommandTest.java
@@ -20,13 +20,17 @@ import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
+import java.util.Collections;
+
 import org.junit.Before;
 import org.junit.ClassRule;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 
+import org.apache.geode.cache.execute.ResultCollector;
 import 
org.apache.geode.connectors.jdbc.internal.configuration.ConnectorService;
 import org.apache.geode.distributed.ClusterConfigurationService;
+import org.apache.geode.distributed.DistributedMember;
 import 
org.apache.geode.distributed.internal.InternalClusterConfigurationService;
 import org.apache.geode.test.junit.categories.UnitTest;
 import org.apache.geode.test.junit.rules.GfshParserRule;
@@ -89,4 +93,34 @@ public class DescribeConnectionCommandTest {
         .containsOutput("password", "********").containsOutput("param1", 
"value1")
         .containsOutput("param2", "value2");
   }
+
+  @Test
+  public void whenCCIsNotAvailableAndMemberIsNotSpecified() {
+    doReturn(null).when(command).getConfigurationService();
+    gfsh.executeAndAssertThat(command, COMMAND).statusIsSuccess()
+        .containsOutput("Use --member option to describe connections");
+  }
+
+  @Test
+  public void whenNonExistingMemberIsSpecified() {
+    doReturn(null).when(command).getMember(any());
+    gfsh.executeAndAssertThat(command, COMMAND + " 
--member=member1").statusIsError()
+        .containsOutput("No Members Found");
+  }
+
+  @Test
+  public void whenExistingMemberIsSpecified() {
+    doReturn(mock(DistributedMember.class)).when(command).getMember(any());
+
+    ConnectorService.Connection connection =
+        new ConnectorService.Connection("name", "url1", "user1", "password1", 
"p1:v1,p2:v2");
+    ResultCollector rc = mock(ResultCollector.class);
+    doReturn(rc).when(command).executeFunction(any(), any(), 
any(DistributedMember.class));
+    when(rc.getResult()).thenReturn(Collections.singletonList(connection));
+
+    gfsh.executeAndAssertThat(command, COMMAND + " 
--member=member1").statusIsSuccess()
+        .containsOutput("name", "name").containsOutput("url", "url1")
+        .containsOutput("user", "user1").containsOutput("password", "********")
+        .containsOutput("p1", "v1").containsOutput("p2", "v2");
+  }
 }
diff --git 
a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeConnectionFunctionTest.java
 
b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeConnectionFunctionTest.java
new file mode 100644
index 0000000..1bf804f
--- /dev/null
+++ 
b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeConnectionFunctionTest.java
@@ -0,0 +1,138 @@
+/*
+ * 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.connectors.jdbc.internal.cli;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.Serializable;
+
+import org.apache.commons.lang.SerializationUtils;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.mockito.ArgumentCaptor;
+
+import org.apache.geode.cache.execute.FunctionContext;
+import org.apache.geode.cache.execute.ResultSender;
+import org.apache.geode.connectors.jdbc.internal.JdbcConnectorService;
+import 
org.apache.geode.connectors.jdbc.internal.configuration.ConnectorService;
+import org.apache.geode.distributed.DistributedMember;
+import org.apache.geode.distributed.DistributedSystem;
+import org.apache.geode.internal.cache.InternalCache;
+import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
+import org.apache.geode.test.junit.categories.UnitTest;
+
+@Category(UnitTest.class)
+public class DescribeConnectionFunctionTest {
+
+  private static final String EXISTING_CONFIG = "existingConfig";
+
+  private DescribeConnectionFunction function;
+  private JdbcConnectorService service;
+  private FunctionContext<String> context;
+  private ConnectorService.Connection connectionConfig;
+  private ResultSender<Object> resultSender;
+
+  @Before
+  public void setUp() {
+    function = new DescribeConnectionFunction();
+
+    InternalCache cache = mock(InternalCache.class);
+    context = mock(FunctionContext.class);
+    service = mock(JdbcConnectorService.class);
+    connectionConfig = mock(ConnectorService.Connection.class);
+    resultSender = mock(ResultSender.class);
+
+    DistributedMember member = mock(DistributedMember.class);
+    DistributedSystem system = mock(DistributedSystem.class);
+
+    when(context.getResultSender()).thenReturn(resultSender);
+    when(context.getCache()).thenReturn(cache);
+    when(cache.getService(eq(JdbcConnectorService.class))).thenReturn(service);
+    
when(service.getConnectionConfig(EXISTING_CONFIG)).thenReturn(connectionConfig);
+    when(cache.getDistributedSystem()).thenReturn(system);
+    when(system.getDistributedMember()).thenReturn(member);
+  }
+
+  @Test
+  public void isHAReturnsFalse() {
+    assertThat(function.isHA()).isFalse();
+  }
+
+  @Test
+  public void getIdReturnsNameOfClass() {
+    assertThat(function.getId()).isEqualTo(function.getClass().getName());
+  }
+
+  @Test
+  public void serializes() {
+    Serializable original = function;
+    Object copy = SerializationUtils.clone(original);
+    
assertThat(copy).isNotSameAs(original).isInstanceOf(DescribeConnectionFunction.class);
+  }
+
+  @Test
+  public void returnsResultWithCorrectConfig() {
+    when(context.getArguments()).thenReturn(EXISTING_CONFIG);
+
+    function.execute(context);
+
+    ArgumentCaptor<Object> argument = ArgumentCaptor.forClass(Object.class);
+    verify(resultSender, times(1)).lastResult(argument.capture());
+    assertThat(argument.getValue()).isSameAs(connectionConfig);
+  }
+
+  @Test
+  public void returnNullWithNonExistingConfig() {
+    when(context.getArguments()).thenReturn("non existing");
+
+    function.execute(context);
+
+    ArgumentCaptor<Object> argument = ArgumentCaptor.forClass(Object.class);
+    verify(resultSender, times(1)).lastResult(argument.capture());
+    assertThat(argument.getValue()).isNull();
+
+  }
+
+  @Test
+  public void executeReturnsResultForExceptionWithoutMessage() {
+    when(service.getConnectionConfig(any())).thenThrow(new 
NullPointerException());
+
+    function.execute(context);
+
+    ArgumentCaptor<CliFunctionResult> argument = 
ArgumentCaptor.forClass(CliFunctionResult.class);
+    verify(resultSender, times(1)).lastResult(argument.capture());
+    
assertThat(argument.getValue().getMessage()).contains(NullPointerException.class.getName());
+  }
+
+  @Test
+  public void executeReturnsResultForExceptionWithMessage() {
+    when(service.getConnectionConfig(any()))
+        .thenThrow(new IllegalArgumentException("some message"));
+
+    function.execute(context);
+
+    ArgumentCaptor<CliFunctionResult> argument = 
ArgumentCaptor.forClass(CliFunctionResult.class);
+    verify(resultSender, times(1)).lastResult(argument.capture());
+    assertThat(argument.getValue().getMessage()).contains("some message")
+        .doesNotContain(IllegalArgumentException.class.getName());
+  }
+}
diff --git 
a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeMappingCommandDUnitTest.java
 
b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeMappingCommandDUnitTest.java
index fe3da4b..7234164 100644
--- 
a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeMappingCommandDUnitTest.java
+++ 
b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeMappingCommandDUnitTest.java
@@ -24,9 +24,8 @@ import static 
org.apache.geode.connectors.jdbc.internal.cli.CreateMappingCommand
 import static 
org.apache.geode.connectors.jdbc.internal.cli.DescribeMappingCommand.DESCRIBE_MAPPING;
 import static 
org.apache.geode.connectors.jdbc.internal.cli.DescribeMappingCommand.DESCRIBE_MAPPING__REGION_NAME;
 
-import java.io.Serializable;
-
-import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
@@ -40,31 +39,28 @@ import org.apache.geode.test.junit.rules.GfshCommandRule;
 import org.apache.geode.test.junit.rules.serializable.SerializableTestName;
 
 @Category(DistributedTest.class)
-public class DescribeMappingCommandDUnitTest implements Serializable {
+public class DescribeMappingCommandDUnitTest {
 
   private static final String REGION_NAME = "testRegion";
 
-  @Rule
-  public transient GfshCommandRule gfsh = new GfshCommandRule();
+  @ClassRule
+  public static GfshCommandRule gfsh = new GfshCommandRule();
 
-  @Rule
-  public ClusterStartupRule startupRule = new ClusterStartupRule();
+  @ClassRule
+  public static ClusterStartupRule startupRule = new ClusterStartupRule();
 
   @Rule
   public SerializableTestName testName = new SerializableTestName();
 
-  private MemberVM server;
+  private static MemberVM locator, server;
 
-  @Before
-  public void before() throws Exception {
-    MemberVM locator = startupRule.startLocatorVM(0);
+  @BeforeClass
+  public static void before() throws Exception {
+    locator = startupRule.startLocatorVM(0);
     server = startupRule.startServerVM(1, locator.getPort());
 
     gfsh.connectAndVerify(locator);
-  }
 
-  @Test
-  public void describesExistingMapping() {
     CommandStringBuilder csb = new CommandStringBuilder(CREATE_MAPPING);
     csb.addOption(CREATE_MAPPING__REGION_NAME, "testRegion");
     csb.addOption(CREATE_MAPPING__CONNECTION_NAME, "connection");
@@ -74,9 +70,12 @@ public class DescribeMappingCommandDUnitTest implements 
Serializable {
     csb.addOption(CREATE_MAPPING__FIELD_MAPPING, 
"field1:column1,field2:column2");
 
     gfsh.executeAndAssertThat(csb.toString()).statusIsSuccess();
+  }
 
-    csb = new 
CommandStringBuilder(DESCRIBE_MAPPING).addOption(DESCRIBE_MAPPING__REGION_NAME,
-        REGION_NAME);
+  @Test
+  public void describesExistingMapping() {
+    CommandStringBuilder csb = new CommandStringBuilder(DESCRIBE_MAPPING)
+        .addOption(DESCRIBE_MAPPING__REGION_NAME, REGION_NAME);
 
     CommandResultAssert commandResultAssert = 
gfsh.executeAndAssertThat(csb.toString());
 
@@ -102,4 +101,21 @@ public class DescribeMappingCommandDUnitTest implements 
Serializable {
     commandResultAssert.statusIsError();
     commandResultAssert.containsOutput(String.format("mapping for region 
'nonExisting' not found"));
   }
+
+  @Test
+  public void reportConfigurationFoundOnMember() {
+    CommandResultAssert commandResultAssert = gfsh
+        .executeAndAssertThat(DESCRIBE_MAPPING + " --region=" + REGION_NAME + 
" --member=server-1")
+        .statusIsSuccess();
+
+    commandResultAssert.containsKeyValuePair(CREATE_MAPPING__REGION_NAME, 
REGION_NAME);
+    commandResultAssert.containsKeyValuePair(CREATE_MAPPING__CONNECTION_NAME, 
"connection");
+    commandResultAssert.containsKeyValuePair(CREATE_MAPPING__TABLE_NAME, 
"testTable");
+    commandResultAssert.containsKeyValuePair(CREATE_MAPPING__PDX_CLASS_NAME, 
"myPdxClass");
+    
commandResultAssert.containsKeyValuePair(CREATE_MAPPING__VALUE_CONTAINS_PRIMARY_KEY,
 "true");
+    commandResultAssert.containsOutput("field1");
+    commandResultAssert.containsOutput("field2");
+    commandResultAssert.containsOutput("column1");
+    commandResultAssert.containsOutput("column2");
+  }
 }
diff --git 
a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeMappingCommandTest.java
 
b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeMappingCommandTest.java
index d5fcb5d..3acdd32 100644
--- 
a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeMappingCommandTest.java
+++ 
b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeMappingCommandTest.java
@@ -20,13 +20,17 @@ import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
+import java.util.Collections;
+
 import org.junit.Before;
 import org.junit.ClassRule;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 
+import org.apache.geode.cache.execute.ResultCollector;
 import 
org.apache.geode.connectors.jdbc.internal.configuration.ConnectorService;
 import org.apache.geode.distributed.ClusterConfigurationService;
+import org.apache.geode.distributed.DistributedMember;
 import 
org.apache.geode.distributed.internal.InternalClusterConfigurationService;
 import org.apache.geode.test.junit.categories.UnitTest;
 import org.apache.geode.test.junit.rules.GfshParserRule;
@@ -79,7 +83,7 @@ public class DescribeMappingCommandTest {
   public void successfulResult() {
     // mapping found in CC
     ConnectorService.RegionMapping mapping =
-        new ConnectorService.RegionMapping("region1", "class1", "table1", 
"name1", true);
+        new ConnectorService.RegionMapping("region", "class1", "table1", 
"name1", true);
     mapping.getFieldMapping()
         .add(new ConnectorService.RegionMapping.FieldMapping("field1", 
"value1"));
     mapping.getFieldMapping()
@@ -89,8 +93,44 @@ public class DescribeMappingCommandTest {
     when(ccService.getCustomCacheElement(any(), any(), 
any())).thenReturn(connectorService);
     when(ccService.findIdentifiable(any(), any())).thenReturn(mapping);
 
+    gfsh.executeAndAssertThat(command, 
COMMAND).statusIsSuccess().containsOutput("region", "region")
+        .containsOutput("connection", "name1").containsOutput("table", 
"table1")
+        .containsOutput("pdx-class-name", "class1")
+        .containsOutput("value-contains-primary-key", 
"true").containsOutput("field1", "value1")
+        .containsOutput("field2", "value2");
+  }
+
+  @Test
+  public void whenCCIsNotAvailableAndMemberIsNotSpecified() {
+    doReturn(null).when(command).getConfigurationService();
     gfsh.executeAndAssertThat(command, COMMAND).statusIsSuccess()
-        .containsOutput("region", "region1").containsOutput("connection", 
"name1")
+        .containsOutput("Use --member option to describe mappings");
+  }
+
+  @Test
+  public void whenNonExistingMemberIsSpecified() {
+    doReturn(null).when(command).getMember(any());
+    gfsh.executeAndAssertThat(command, COMMAND + " 
--member=member1").statusIsError()
+        .containsOutput("No Members Found");
+  }
+
+  @Test
+  public void whenExistingMemberIsSpecified() {
+    doReturn(mock(DistributedMember.class)).when(command).getMember(any());
+
+    ConnectorService.RegionMapping mapping =
+        new ConnectorService.RegionMapping("region", "class1", "table1", 
"name1", true);
+    mapping.getFieldMapping()
+        .add(new ConnectorService.RegionMapping.FieldMapping("field1", 
"value1"));
+    mapping.getFieldMapping()
+        .add(new ConnectorService.RegionMapping.FieldMapping("field2", 
"value2"));
+
+    ResultCollector rc = mock(ResultCollector.class);
+    doReturn(rc).when(command).executeFunction(any(), any(), 
any(DistributedMember.class));
+    when(rc.getResult()).thenReturn(Collections.singletonList(mapping));
+
+    gfsh.executeAndAssertThat(command, COMMAND + " 
--member=member1").statusIsSuccess()
+        .containsOutput("region", "region").containsOutput("connection", 
"name1")
         .containsOutput("table", "table1").containsOutput("pdx-class-name", 
"class1")
         .containsOutput("value-contains-primary-key", 
"true").containsOutput("field1", "value1")
         .containsOutput("field2", "value2");
diff --git 
a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeMappingFunctionTest.java
 
b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeMappingFunctionTest.java
new file mode 100644
index 0000000..0487c7d
--- /dev/null
+++ 
b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeMappingFunctionTest.java
@@ -0,0 +1,138 @@
+/*
+ * 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.connectors.jdbc.internal.cli;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.Serializable;
+
+import org.apache.commons.lang.SerializationUtils;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.mockito.ArgumentCaptor;
+
+import org.apache.geode.cache.execute.FunctionContext;
+import org.apache.geode.cache.execute.ResultSender;
+import org.apache.geode.connectors.jdbc.internal.JdbcConnectorService;
+import 
org.apache.geode.connectors.jdbc.internal.configuration.ConnectorService;
+import org.apache.geode.distributed.DistributedMember;
+import org.apache.geode.distributed.DistributedSystem;
+import org.apache.geode.internal.cache.InternalCache;
+import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
+import org.apache.geode.test.junit.categories.UnitTest;
+
+@Category(UnitTest.class)
+public class DescribeMappingFunctionTest {
+
+  private static final String EXISTING_MAPPING = "existingMapping";
+
+  private DescribeMappingFunction function;
+  private JdbcConnectorService service;
+  private FunctionContext<String> context;
+  private ConnectorService.RegionMapping regionMapping;
+  private ResultSender<Object> resultSender;
+
+  @Before
+  public void setUp() {
+    function = new DescribeMappingFunction();
+
+    InternalCache cache = mock(InternalCache.class);
+    context = mock(FunctionContext.class);
+    service = mock(JdbcConnectorService.class);
+    regionMapping = mock(ConnectorService.RegionMapping.class);
+    resultSender = mock(ResultSender.class);
+
+    DistributedMember member = mock(DistributedMember.class);
+    DistributedSystem system = mock(DistributedSystem.class);
+
+    when(context.getResultSender()).thenReturn(resultSender);
+    when(context.getCache()).thenReturn(cache);
+    when(cache.getService(eq(JdbcConnectorService.class))).thenReturn(service);
+    
when(service.getMappingForRegion(EXISTING_MAPPING)).thenReturn(regionMapping);
+    when(cache.getDistributedSystem()).thenReturn(system);
+    when(system.getDistributedMember()).thenReturn(member);
+  }
+
+  @Test
+  public void isHAReturnsFalse() {
+    assertThat(function.isHA()).isFalse();
+  }
+
+  @Test
+  public void getIdReturnsNameOfClass() {
+    assertThat(function.getId()).isEqualTo(function.getClass().getName());
+  }
+
+  @Test
+  public void serializes() {
+    Serializable original = function;
+    Object copy = SerializationUtils.clone(original);
+    
assertThat(copy).isNotSameAs(original).isInstanceOf(DescribeMappingFunction.class);
+  }
+
+  @Test
+  public void returnsResultWithCorrectConfig() {
+    when(context.getArguments()).thenReturn(EXISTING_MAPPING);
+
+    function.execute(context);
+
+    ArgumentCaptor<Object> argument = ArgumentCaptor.forClass(Object.class);
+    verify(resultSender, times(1)).lastResult(argument.capture());
+    assertThat(argument.getValue()).isSameAs(regionMapping);
+  }
+
+  @Test
+  public void returnNullWithNonExistingConfig() {
+    when(context.getArguments()).thenReturn("non existing");
+
+    function.execute(context);
+
+    ArgumentCaptor<Object> argument = ArgumentCaptor.forClass(Object.class);
+    verify(resultSender, times(1)).lastResult(argument.capture());
+    assertThat(argument.getValue()).isNull();
+
+  }
+
+  @Test
+  public void executeReturnsResultForExceptionWithoutMessage() {
+    when(service.getMappingForRegion(any())).thenThrow(new 
NullPointerException());
+
+    function.execute(context);
+
+    ArgumentCaptor<CliFunctionResult> argument = 
ArgumentCaptor.forClass(CliFunctionResult.class);
+    verify(resultSender, times(1)).lastResult(argument.capture());
+    
assertThat(argument.getValue().getMessage()).contains(NullPointerException.class.getName());
+  }
+
+  @Test
+  public void executeReturnsResultForExceptionWithMessage() {
+    when(service.getMappingForRegion(any()))
+        .thenThrow(new IllegalArgumentException("some message"));
+
+    function.execute(context);
+
+    ArgumentCaptor<CliFunctionResult> argument = 
ArgumentCaptor.forClass(CliFunctionResult.class);
+    verify(resultSender, times(1)).lastResult(argument.capture());
+    assertThat(argument.getValue().getMessage()).contains("some message")
+        .doesNotContain(IllegalArgumentException.class.getName());
+  }
+}
diff --git 
a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/ListConnectionCommandDUnitTest.java
 
b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/ListConnectionCommandDUnitTest.java
index d38aa1e..faf97c2 100644
--- 
a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/ListConnectionCommandDUnitTest.java
+++ 
b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/ListConnectionCommandDUnitTest.java
@@ -95,6 +95,27 @@ public class ListConnectionCommandDUnitTest implements 
Serializable {
   }
 
   @Test
+  public void listsConnectionsFromMember() {
+    String conn1 =
+        "create jdbc-connection --name=name-1 --url=url --user=user 
--password=pass --params=param1:value1,param2:value2";
+    gfsh.executeAndAssertThat(conn1).statusIsSuccess();
+    String conn2 =
+        "create jdbc-connection --name=name-2 --url=url --user=user 
--password=pass --params=param1:value1,param2:value2";
+    gfsh.executeAndAssertThat(conn2).statusIsSuccess();
+    String conn3 =
+        "create jdbc-connection --name=name-3 --url=url --user=user 
--password=pass --params=param1:value1,param2:value2";
+    gfsh.executeAndAssertThat(conn3).statusIsSuccess();
+
+    CommandResultAssert commandResultAssert =
+        gfsh.executeAndAssertThat(LIST_JDBC_CONNECTION + " 
--member=server-1").statusIsSuccess();
+
+    commandResultAssert.statusIsSuccess();
+    commandResultAssert.tableHasRowCount(LIST_OF_CONNECTIONS, 3);
+    commandResultAssert.tableHasColumnOnlyWithValues(LIST_OF_CONNECTIONS, 
connectionName + "-1",
+        connectionName + "-2", connectionName + "-3");
+  }
+
+  @Test
   public void reportsNoConnectionsFound() {
     CommandStringBuilder csb = new CommandStringBuilder(LIST_JDBC_CONNECTION);
 
diff --git 
a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/ListConnectionCommandTest.java
 
b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/ListConnectionCommandTest.java
index f61a4c2..d69f22d 100644
--- 
a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/ListConnectionCommandTest.java
+++ 
b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/ListConnectionCommandTest.java
@@ -14,19 +14,25 @@
  */
 package org.apache.geode.connectors.jdbc.internal.cli;
 
+import static java.util.stream.Collectors.toSet;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
+import java.util.Collections;
+import java.util.stream.Stream;
+
 import org.junit.Before;
 import org.junit.ClassRule;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 
+import org.apache.geode.cache.execute.ResultCollector;
 import 
org.apache.geode.connectors.jdbc.internal.configuration.ConnectorService;
 import org.apache.geode.distributed.ClusterConfigurationService;
+import org.apache.geode.distributed.DistributedMember;
 import 
org.apache.geode.distributed.internal.InternalClusterConfigurationService;
 import org.apache.geode.test.junit.categories.UnitTest;
 import org.apache.geode.test.junit.rules.GfshParserRule;
@@ -34,7 +40,7 @@ import org.apache.geode.test.junit.rules.GfshParserRule;
 @Category(UnitTest.class)
 
 public class ListConnectionCommandTest {
-  public static final String COMMAND = "list jdbc-connection";
+  public static final String COMMAND = "list jdbc-connections ";
   private ListConnectionCommand command;
   private ClusterConfigurationService ccService;
 
@@ -89,4 +95,38 @@ public class ListConnectionCommandTest {
     gfsh.executeAndAssertThat(command, 
COMMAND).statusIsSuccess().containsOutput("name1", "name2",
         "name3");
   }
+
+  @Test
+  public void whenCCIsNotAvailableAndMemberIsNotSpecified() {
+    doReturn(null).when(command).getConfigurationService();
+    gfsh.executeAndAssertThat(command, COMMAND).statusIsSuccess()
+        .containsOutput("Use --member option to describe connections");
+  }
+
+  @Test
+  public void whenNonExistingMemberIsSpecified() {
+    doReturn(null).when(command).getMember(any());
+    gfsh.executeAndAssertThat(command, COMMAND + " 
--member=member1").statusIsError()
+        .containsOutput("No Members Found");
+  }
+
+  @Test
+  public void whenExistingMemberIsSpecified() {
+    doReturn(mock(DistributedMember.class)).when(command).getMember(any());
+
+    ConnectorService.Connection connection1 =
+        new ConnectorService.Connection("name1", "url1", "user1", "password1", 
"p1:v1,p2:v2");
+    ConnectorService.Connection connection2 =
+        new ConnectorService.Connection("name2", "url2", "user2", "password2", 
"p3:v3,p4:v4");
+    ConnectorService.Connection connection3 =
+        new ConnectorService.Connection("name3", "url3", "user3", "password3", 
"p5:v5,p6:v6");
+
+    ResultCollector rc = mock(ResultCollector.class);
+    doReturn(rc).when(command).executeFunction(any(), any(), 
any(DistributedMember.class));
+    when(rc.getResult()).thenReturn(Collections
+        .singletonList(Stream.of(connection1, connection2, 
connection3).collect(toSet())));
+
+    gfsh.executeAndAssertThat(command, COMMAND + " 
--member=member1").statusIsSuccess()
+        .containsOutput("name1", "name2", "name3");
+  }
 }
diff --git 
a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/ListConnectionFunctionTest.java
 
b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/ListConnectionFunctionTest.java
new file mode 100644
index 0000000..e8de75f
--- /dev/null
+++ 
b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/ListConnectionFunctionTest.java
@@ -0,0 +1,169 @@
+/*
+ * 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.connectors.jdbc.internal.cli;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.commons.lang.SerializationUtils;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.mockito.ArgumentCaptor;
+
+import org.apache.geode.cache.execute.FunctionContext;
+import org.apache.geode.cache.execute.ResultSender;
+import org.apache.geode.connectors.jdbc.internal.JdbcConnectorService;
+import 
org.apache.geode.connectors.jdbc.internal.configuration.ConnectorService;
+import org.apache.geode.distributed.DistributedMember;
+import org.apache.geode.distributed.DistributedSystem;
+import org.apache.geode.internal.cache.InternalCache;
+import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
+import org.apache.geode.test.junit.categories.UnitTest;
+
+@Category(UnitTest.class)
+public class ListConnectionFunctionTest {
+
+  private FunctionContext<Void> context;
+  private ResultSender<Object> resultSender;
+  private JdbcConnectorService service;
+
+  private ConnectorService.Connection connectionConfig1;
+  private ConnectorService.Connection connectionConfig2;
+  private ConnectorService.Connection connectionConfig3;
+
+  private Set<ConnectorService.Connection> expected;
+
+  private ListConnectionFunction function;
+
+  @Before
+  public void setUp() {
+    InternalCache cache = mock(InternalCache.class);
+    context = mock(FunctionContext.class);
+    DistributedMember member = mock(DistributedMember.class);
+    resultSender = mock(ResultSender.class);
+    service = mock(JdbcConnectorService.class);
+    DistributedSystem system = mock(DistributedSystem.class);
+
+    connectionConfig1 = mock(ConnectorService.Connection.class);
+    connectionConfig2 = mock(ConnectorService.Connection.class);
+    connectionConfig3 = mock(ConnectorService.Connection.class);
+
+    expected = new HashSet<>();
+
+    when(context.getResultSender()).thenReturn(resultSender);
+    when(context.getCache()).thenReturn(cache);
+    when(cache.getDistributedSystem()).thenReturn(system);
+    when(system.getDistributedMember()).thenReturn(member);
+    when(cache.getService(eq(JdbcConnectorService.class))).thenReturn(service);
+    when(service.getConnectionConfigs()).thenReturn(expected);
+
+    function = new ListConnectionFunction();
+  }
+
+  @Test
+  public void isHAReturnsFalse() {
+    assertThat(function.isHA()).isFalse();
+  }
+
+  @Test
+  public void getIdReturnsNameOfClass() {
+    assertThat(function.getId()).isEqualTo(function.getClass().getName());
+  }
+
+  @Test
+  public void serializes() {
+    Serializable original = function;
+
+    Object copy = SerializationUtils.clone(original);
+
+    
assertThat(copy).isNotSameAs(original).isInstanceOf(ListConnectionFunction.class);
+  }
+
+  @Test
+  public void getConnectionConfigsReturnsMultiple() {
+    expected.add(connectionConfig1);
+    expected.add(connectionConfig2);
+    expected.add(connectionConfig3);
+
+    Set<ConnectorService.Connection> actual =
+        function.getFunctionResult(service, mock(FunctionContext.class));
+
+    assertThat(actual).containsExactlyInAnyOrder(connectionConfig1, 
connectionConfig2,
+        connectionConfig3);
+  }
+
+  @Test
+  public void getConnectionConfigsReturnsEmpty() {
+    Set<ConnectorService.Connection> actual =
+        function.getFunctionResult(service, mock(FunctionContext.class));
+
+    assertThat(actual).isEmpty();
+  }
+
+  @Test
+  public void executeReturnsResultWithAllConfigs() {
+    expected.add(connectionConfig1);
+    expected.add(connectionConfig2);
+    expected.add(connectionConfig3);
+
+    function.execute(context);
+
+    ArgumentCaptor<Set<ConnectorService.Connection>> argument = 
ArgumentCaptor.forClass(Set.class);
+    verify(resultSender, times(1)).lastResult(argument.capture());
+    
assertThat(argument.getValue()).containsExactlyInAnyOrder(connectionConfig1, 
connectionConfig2,
+        connectionConfig3);
+  }
+
+  @Test
+  public void executeReturnsEmptyResultForNoConfigs() {
+    function.execute(context);
+
+    ArgumentCaptor<Set<ConnectorService.Connection>> argument = 
ArgumentCaptor.forClass(Set.class);
+    verify(resultSender, times(1)).lastResult(argument.capture());
+    assertThat(argument.getValue()).isEmpty();
+  }
+
+  @Test
+  public void executeReturnsResultForExceptionWithoutMessage() {
+    when(service.getConnectionConfigs()).thenThrow(new NullPointerException());
+
+    function.execute(context);
+
+    ArgumentCaptor<CliFunctionResult> argument = 
ArgumentCaptor.forClass(CliFunctionResult.class);
+    verify(resultSender, times(1)).lastResult(argument.capture());
+    
assertThat(argument.getValue().getStatus()).contains(NullPointerException.class.getName());
+  }
+
+  @Test
+  public void executeReturnsResultForExceptionWithMessage() {
+    when(service.getConnectionConfigs()).thenThrow(new 
IllegalArgumentException("some message"));
+
+    function.execute(context);
+
+    ArgumentCaptor<CliFunctionResult> argument = 
ArgumentCaptor.forClass(CliFunctionResult.class);
+    verify(resultSender, times(1)).lastResult(argument.capture());
+    assertThat(argument.getValue().getStatus()).contains("some message")
+        .doesNotContain(IllegalArgumentException.class.getName());
+  }
+}
diff --git 
a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/ListMappingCommandDUnitTest.java
 
b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/ListMappingCommandDUnitTest.java
index e027db5..3aa1be1 100644
--- 
a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/ListMappingCommandDUnitTest.java
+++ 
b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/ListMappingCommandDUnitTest.java
@@ -99,6 +99,30 @@ public class ListMappingCommandDUnitTest implements 
Serializable {
   }
 
   @Test
+  public void listsMultipleRegionMappingsFromMember() {
+    String mapping1 = "create jdbc-mapping --region=testRegion-1 
--connection=connection "
+        + "--table=myTable --pdx-class-name=myPdxClass 
--value-contains-primary-key=true "
+        + "--field-mapping=field1:column1,field2:column2";
+    gfsh.executeAndAssertThat(mapping1).statusIsSuccess();
+    String mapping2 = "create jdbc-mapping --region=testRegion-2 
--connection=connection "
+        + "--table=myTable --pdx-class-name=myPdxClass 
--value-contains-primary-key=true "
+        + "--field-mapping=field1:column1,field2:column2";
+    gfsh.executeAndAssertThat(mapping2).statusIsSuccess();
+    String mapping3 = "create jdbc-mapping --region=testRegion-3 
--connection=connection "
+        + "--table=myTable --pdx-class-name=myPdxClass 
--value-contains-primary-key=true "
+        + "--field-mapping=field1:column1,field2:column2";
+    gfsh.executeAndAssertThat(mapping3).statusIsSuccess();
+
+    CommandResultAssert commandResultAssert =
+        gfsh.executeAndAssertThat(LIST_MAPPING + " 
--member=server-1").statusIsSuccess();
+
+    commandResultAssert.statusIsSuccess();
+    commandResultAssert.tableHasRowCount(LIST_OF_MAPPINGS, 3);
+    commandResultAssert.tableHasColumnOnlyWithValues(LIST_OF_MAPPINGS, 
regionName + "-1",
+        regionName + "-2", regionName + "-3");
+  }
+
+  @Test
   public void reportsNoRegionMappingsFound() {
     CommandStringBuilder csb = new CommandStringBuilder(LIST_MAPPING);
 
diff --git 
a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/ListMappingCommandTest.java
 
b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/ListMappingCommandTest.java
index 29fe9e4..640d186 100644
--- 
a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/ListMappingCommandTest.java
+++ 
b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/ListMappingCommandTest.java
@@ -14,19 +14,25 @@
  */
 package org.apache.geode.connectors.jdbc.internal.cli;
 
+import static java.util.stream.Collectors.toSet;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
+import java.util.Collections;
+import java.util.stream.Stream;
+
 import org.junit.Before;
 import org.junit.ClassRule;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 
+import org.apache.geode.cache.execute.ResultCollector;
 import 
org.apache.geode.connectors.jdbc.internal.configuration.ConnectorService;
 import org.apache.geode.distributed.ClusterConfigurationService;
+import org.apache.geode.distributed.DistributedMember;
 import 
org.apache.geode.distributed.internal.InternalClusterConfigurationService;
 import org.apache.geode.test.junit.categories.UnitTest;
 import org.apache.geode.test.junit.rules.GfshParserRule;
@@ -90,4 +96,46 @@ public class ListMappingCommandTest {
     gfsh.executeAndAssertThat(command, 
COMMAND).statusIsSuccess().containsOutput("region1",
         "region2");
   }
+
+  @Test
+  public void whenCCIsNotAvailableAndMemberIsNotSpecified() {
+    doReturn(null).when(command).getConfigurationService();
+    gfsh.executeAndAssertThat(command, COMMAND).statusIsSuccess()
+        .containsOutput("Use --member option to describe mappings");
+  }
+
+  @Test
+  public void whenNonExistingMemberIsSpecified() {
+    doReturn(null).when(command).getMember(any());
+    gfsh.executeAndAssertThat(command, COMMAND + " 
--member=member1").statusIsError()
+        .containsOutput("No Members Found");
+  }
+
+  @Test
+  public void whenExistingMemberIsSpecified() {
+    doReturn(mock(DistributedMember.class)).when(command).getMember(any());
+
+    ConnectorService.RegionMapping mapping1 =
+        new ConnectorService.RegionMapping("region1", "class1", "table1", 
"name1", true);
+    mapping1.getFieldMapping()
+        .add(new ConnectorService.RegionMapping.FieldMapping("field1", 
"value1"));
+    mapping1.getFieldMapping()
+        .add(new ConnectorService.RegionMapping.FieldMapping("field2", 
"value2"));
+
+    ConnectorService.RegionMapping mapping2 =
+        new ConnectorService.RegionMapping("region2", "class2", "table2", 
"name2", true);
+    mapping2.getFieldMapping()
+        .add(new ConnectorService.RegionMapping.FieldMapping("field3", 
"value3"));
+    mapping2.getFieldMapping()
+        .add(new ConnectorService.RegionMapping.FieldMapping("field4", 
"value4"));
+
+    ResultCollector rc = mock(ResultCollector.class);
+    doReturn(rc).when(command).executeFunction(any(), any(), 
any(DistributedMember.class));
+    when(rc.getResult())
+        .thenReturn(Collections.singletonList(Stream.of(mapping1, 
mapping2).collect(toSet())));
+
+    gfsh.executeAndAssertThat(command, COMMAND + " 
--member=member1").statusIsSuccess()
+        .containsOutput("region1", "region2");
+  }
+
 }
diff --git 
a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/ListMappingFunctionTest.java
 
b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/ListMappingFunctionTest.java
new file mode 100644
index 0000000..aef645e
--- /dev/null
+++ 
b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/ListMappingFunctionTest.java
@@ -0,0 +1,170 @@
+/*
+ * 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.connectors.jdbc.internal.cli;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.commons.lang.SerializationUtils;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.mockito.ArgumentCaptor;
+
+import org.apache.geode.cache.execute.FunctionContext;
+import org.apache.geode.cache.execute.ResultSender;
+import org.apache.geode.connectors.jdbc.internal.JdbcConnectorService;
+import 
org.apache.geode.connectors.jdbc.internal.configuration.ConnectorService;
+import org.apache.geode.distributed.DistributedMember;
+import org.apache.geode.distributed.DistributedSystem;
+import org.apache.geode.internal.cache.InternalCache;
+import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
+import org.apache.geode.test.junit.categories.UnitTest;
+
+@Category(UnitTest.class)
+public class ListMappingFunctionTest {
+
+  private FunctionContext<Void> context;
+  private ResultSender<Object> resultSender;
+  private JdbcConnectorService service;
+
+  private ConnectorService.RegionMapping regionMapping1;
+  private ConnectorService.RegionMapping regionMapping2;
+  private ConnectorService.RegionMapping regionMapping3;
+
+  private Set<ConnectorService.RegionMapping> expected;
+
+  private ListMappingFunction function;
+
+  @Before
+  public void setUp() {
+    InternalCache cache = mock(InternalCache.class);
+    context = mock(FunctionContext.class);
+    DistributedMember member = mock(DistributedMember.class);
+    resultSender = mock(ResultSender.class);
+    service = mock(JdbcConnectorService.class);
+    DistributedSystem system = mock(DistributedSystem.class);
+
+    regionMapping1 = mock(ConnectorService.RegionMapping.class);
+    regionMapping2 = mock(ConnectorService.RegionMapping.class);
+    regionMapping3 = mock(ConnectorService.RegionMapping.class);
+
+    expected = new HashSet<>();
+
+    when(context.getResultSender()).thenReturn(resultSender);
+    when(context.getCache()).thenReturn(cache);
+    when(cache.getDistributedSystem()).thenReturn(system);
+    when(system.getDistributedMember()).thenReturn(member);
+    when(cache.getService(eq(JdbcConnectorService.class))).thenReturn(service);
+    when(service.getRegionMappings()).thenReturn(expected);
+
+    function = new ListMappingFunction();
+  }
+
+  @Test
+  public void isHAReturnsFalse() {
+    assertThat(function.isHA()).isFalse();
+  }
+
+  @Test
+  public void getIdReturnsNameOfClass() {
+    assertThat(function.getId()).isEqualTo(function.getClass().getName());
+  }
+
+  @Test
+  public void serializes() {
+    Serializable original = function;
+
+    Object copy = SerializationUtils.clone(original);
+
+    
assertThat(copy).isNotSameAs(original).isInstanceOf(ListMappingFunction.class);
+  }
+
+  @Test
+  public void getRegionMappingsReturnsMultiple() {
+    expected.add(regionMapping1);
+    expected.add(regionMapping2);
+    expected.add(regionMapping3);
+
+    Set<ConnectorService.RegionMapping> actual =
+        function.getFunctionResult(service, mock(FunctionContext.class));
+
+    assertThat(actual).containsExactlyInAnyOrder(regionMapping1, 
regionMapping2, regionMapping3);
+  }
+
+  @Test
+  public void getRegionMappingsReturnsEmpty() {
+    Set<ConnectorService.RegionMapping> actual =
+        function.getFunctionResult(service, mock(FunctionContext.class));
+
+    assertThat(actual).isEmpty();
+  }
+
+  @Test
+  public void executeReturnsResultWithAllRegionMappings() {
+    expected.add(regionMapping1);
+    expected.add(regionMapping2);
+    expected.add(regionMapping3);
+
+    function.execute(context);
+
+    ArgumentCaptor<Set<ConnectorService.RegionMapping>> argument =
+        ArgumentCaptor.forClass(Set.class);
+    verify(resultSender, times(1)).lastResult(argument.capture());
+    assertThat(argument.getValue()).containsExactlyInAnyOrder(regionMapping1, 
regionMapping2,
+        regionMapping3);
+  }
+
+  @Test
+  public void executeReturnsEmptyResultForNoRegionMappings() {
+    function.execute(context);
+
+    ArgumentCaptor<Set<ConnectorService.RegionMapping>> argument =
+        ArgumentCaptor.forClass(Set.class);
+    verify(resultSender, times(1)).lastResult(argument.capture());
+    assertThat(argument.getValue()).isEmpty();
+  }
+
+  @Test
+  public void executeReturnsResultForExceptionWithoutMessage() {
+    when(service.getRegionMappings()).thenThrow(new NullPointerException());
+
+    function.execute(context);
+
+    ArgumentCaptor<CliFunctionResult> argument = 
ArgumentCaptor.forClass(CliFunctionResult.class);
+    verify(resultSender, times(1)).lastResult(argument.capture());
+    
assertThat(argument.getValue().getStatus()).contains(NullPointerException.class.getName());
+  }
+
+  @Test
+  public void executeReturnsResultForExceptionWithMessage() {
+    when(service.getRegionMappings()).thenThrow(new 
IllegalArgumentException("some message"));
+
+    function.execute(context);
+
+    ArgumentCaptor<CliFunctionResult> argument = 
ArgumentCaptor.forClass(CliFunctionResult.class);
+    verify(resultSender, times(1)).lastResult(argument.capture());
+    assertThat(argument.getValue().getStatus()).contains("some message")
+        .doesNotContain(IllegalArgumentException.class.getName());
+  }
+}

-- 
To stop receiving notification emails like this one, please contact
[email protected].

Reply via email to