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

eshu11 pushed a commit to branch feature/GEODE-8112
in repository https://gitbox.apache.org/repos/asf/geode.git


The following commit(s) were added to refs/heads/feature/GEODE-8112 by this 
push:
     new a751251  GEODE-8112: Add --member option in query command.
a751251 is described below

commit a75125115eaef071d0b537b40c69425aaca5e653
Author: Eric Shu <e...@pivotal.io>
AuthorDate: Tue May 12 14:29:50 2020 -0700

    GEODE-8112: Add --member option in query command.
---
 .../geode/management/internal/i18n/CliStrings.java |  2 +
 .../cli/commands/QueryCommandDUnitTestBase.java    | 49 +++++++++++++++
 .../commands/QueryCommandIntegrationTestBase.java  |  2 +-
 .../internal/cli/commands/QueryCommand.java        | 29 +++++++--
 .../internal/cli/commands/QueryCommandTest.java    | 72 ++++++++++++++++++++++
 5 files changed, 147 insertions(+), 7 deletions(-)

diff --git 
a/geode-core/src/main/java/org/apache/geode/management/internal/i18n/CliStrings.java
 
b/geode-core/src/main/java/org/apache/geode/management/internal/i18n/CliStrings.java
index bb669dd..f660664 100644
--- 
a/geode-core/src/main/java/org/apache/geode/management/internal/i18n/CliStrings.java
+++ 
b/geode-core/src/main/java/org/apache/geode/management/internal/i18n/CliStrings.java
@@ -1823,6 +1823,8 @@ public class CliStrings {
       "Cannot find regions <{0}> in any of the members";
   public static final String QUERY__MSG__NOT_SUPPORTED_ON_MEMBERS = 
CliStrings.QUERY
       + " command should be used only from shell. Use QueryService API for 
running query inside Geode VMs";
+  public static final String QUERY__MEMBER__HELP =
+      "Name/Id of a member which hosts the regions to be queried.";
 
   /* 'rebalance' command */
   public static final String REBALANCE = "rebalance";
diff --git 
a/geode-dunit/src/main/java/org/apache/geode/management/internal/cli/commands/QueryCommandDUnitTestBase.java
 
b/geode-dunit/src/main/java/org/apache/geode/management/internal/cli/commands/QueryCommandDUnitTestBase.java
index 919849f..b86e440 100644
--- 
a/geode-dunit/src/main/java/org/apache/geode/management/internal/cli/commands/QueryCommandDUnitTestBase.java
+++ 
b/geode-dunit/src/main/java/org/apache/geode/management/internal/cli/commands/QueryCommandDUnitTestBase.java
@@ -65,6 +65,10 @@ public class QueryCommandDUnitTestBase {
       SEPARATOR + DATA_REGION_WITH_EVICTION_NAME;
   private static final String DATA_PAR_REGION_NAME = 
"GemfireDataCommandsTestParRegion";
   private static final String DATA_PAR_REGION_NAME_PATH = SEPARATOR + 
DATA_PAR_REGION_NAME;
+  private static final String DATA_REGION_WITH_PROXY_NAME =
+      "GemfireDataCommandsTestRegionWithProxy";
+  private static final String DATA_REGION_WITH_PROXY_NAME_PATH =
+      SEPARATOR + DATA_REGION_WITH_PROXY_NAME;
 
   private static final String SERIALIZATION_FILTER =
       "org.apache.geode.management.internal.cli.dto.**";
@@ -256,6 +260,15 @@ public class QueryCommandDUnitTestBase {
     assertThat(dataRegion.getFullPath()).contains(regionName);
   }
 
+  private static void setupReplicatedProxyRegion(String regionName) {
+    InternalCache cache = ClusterStartupRule.getCache();
+    RegionFactory regionFactory = 
cache.createRegionFactory(RegionShortcut.REPLICATE_PROXY);
+
+    Region proxyRegion = regionFactory.create(regionName);
+    assertThat(proxyRegion).isNotNull();
+    assertThat(proxyRegion.getFullPath()).contains(regionName);
+  }
+
   private void validateSelectResult(CommandResult cmdResult, Boolean 
expectSuccess,
       Integer expectedRows, String[] cols) {
     ResultModel rd = cmdResult.getResultData();
@@ -310,4 +323,40 @@ public class QueryCommandDUnitTestBase {
       this.value1 = value1;
     }
   }
+
+  @Test
+  public void testSimpleQueryWithProxyRegion() {
+    server1.invoke(() -> 
setupReplicatedProxyRegion(DATA_REGION_WITH_PROXY_NAME));
+    server2.invoke(() -> setupReplicatedRegion(DATA_REGION_WITH_PROXY_NAME));
+    
locator.waitUntilRegionIsReadyOnExactlyThisManyServers(DATA_REGION_WITH_PROXY_NAME_PATH,
 2);
+
+    server1.invoke(() -> 
prepareDataForRegion(DATA_REGION_WITH_PROXY_NAME_PATH));
+
+    String member = getHostingMember();
+    Random random = new Random(System.nanoTime());
+    int randomInteger = random.nextInt(COUNT);
+    String query = "query --member=" + member
+        + " --query=\"select ID , status , createTime , pk, floatMinValue from 
"
+        + DATA_REGION_WITH_PROXY_NAME_PATH + " where ID <= " + randomInteger
+        + "\" --interactive=false";
+
+    CommandResult commandResult = gfsh.executeCommand(query);
+    validateSelectResult(commandResult, true, (randomInteger + 1),
+        new String[] {"ID", "status", "createTime", "pk", "floatMinValue"});
+  }
+
+  private String getHostingMember() {
+    String hostingMember = null;
+    String findMemberCommand = "describe region --name=" + 
DATA_REGION_WITH_PROXY_NAME;
+    CommandResult findMemberResult = gfsh.executeCommand(findMemberCommand);
+    while (findMemberResult.hasNextLine()) {
+      String s = findMemberResult.nextLine();
+      if (s.contains("Hosting Members :")) {
+        hostingMember = s.substring(s.lastIndexOf(":") + 1);
+        break;
+      }
+    }
+    assertThat(hostingMember).isNotNull();
+    return hostingMember.replaceAll("\\s", "");
+  }
 }
diff --git 
a/geode-dunit/src/main/java/org/apache/geode/management/internal/cli/commands/QueryCommandIntegrationTestBase.java
 
b/geode-dunit/src/main/java/org/apache/geode/management/internal/cli/commands/QueryCommandIntegrationTestBase.java
index 8036787..738a013 100644
--- 
a/geode-dunit/src/main/java/org/apache/geode/management/internal/cli/commands/QueryCommandIntegrationTestBase.java
+++ 
b/geode-dunit/src/main/java/org/apache/geode/management/internal/cli/commands/QueryCommandIntegrationTestBase.java
@@ -223,7 +223,7 @@ public class QueryCommandIntegrationTestBase {
   @Test
   public void queryGivesDescriptiveErrorMessageIfNoQueryIsSpecified() {
     gfsh.executeAndAssertThat("query").containsOutput(
-        "You should specify option (--query, --file, --interactive) for this 
command");
+        "You should specify option (--query, --file, --interactive, --member) 
for this command");
   }
 
   @Test
diff --git 
a/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/commands/QueryCommand.java
 
b/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/commands/QueryCommand.java
index 773adc98..482c75d 100644
--- 
a/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/commands/QueryCommand.java
+++ 
b/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/commands/QueryCommand.java
@@ -60,12 +60,17 @@ public class QueryCommand extends GfshCommand {
       @CliOption(key = "file", help = "File in which to output the results.",
           optionContext = ConverterHint.FILE) final File outputFile,
       @CliOption(key = CliStrings.QUERY__INTERACTIVE, unspecifiedDefaultValue 
= "false",
-          help = CliStrings.QUERY__INTERACTIVE__HELP) final boolean 
interactive) {
-    DataCommandResult dataResult = select(query);
+          help = CliStrings.QUERY__INTERACTIVE__HELP) final boolean 
interactive,
+      @CliOption(key = CliStrings.MEMBER,
+          optionContext = ConverterHint.MEMBERIDNAME,
+          help = CliStrings.QUERY__MEMBER__HELP) final String memberNameOrId) {
+
+    DistributedMember targetMember = memberNameOrId == null ? null : 
getMember(memberNameOrId);
+    DataCommandResult dataResult = select(query, targetMember);
     return dataResult.toSelectCommandResult();
   }
 
-  private DataCommandResult select(String query) {
+  DataCommandResult select(String query, DistributedMember targetMember) {
     Cache cache = getCache();
     DataCommandResult dataResult;
 
@@ -97,9 +102,8 @@ public class QueryCommand extends GfshCommand {
 
       regionsInQuery = Collections.unmodifiableSet(regions);
       if (regionsInQuery.size() > 0) {
-        Set<DistributedMember> members =
-            ManagementUtils
-                .getQueryRegionsAssociatedMembers(regionsInQuery, 
(InternalCache) cache, false);
+        Set<DistributedMember> members = getMembers(targetMember, 
(InternalCache) cache,
+            regionsInQuery);
         if (members != null && members.size() > 0) {
           DataCommandFunction function = new DataCommandFunction();
           DataCommandRequest request = new DataCommandRequest();
@@ -132,6 +136,19 @@ public class QueryCommand extends GfshCommand {
     }
   }
 
+  Set<DistributedMember> getMembers(DistributedMember targetMember, 
InternalCache cache,
+      Set<String> regionsInQuery) {
+    return targetMember == null
+        ? getQueryRegionsAssociatedMembers(cache, regionsInQuery)
+        : Collections.singleton(targetMember);
+  }
+
+  Set<DistributedMember> getQueryRegionsAssociatedMembers(InternalCache cache,
+      Set<String> regionsInQuery) {
+    return ManagementUtils
+        .getQueryRegionsAssociatedMembers(regionsInQuery, cache, false);
+  }
+
   public static DataCommandResult callFunctionForRegion(DataCommandRequest 
request,
       DataCommandFunction putfn, Set<DistributedMember> members) {
 
diff --git 
a/geode-gfsh/src/test/java/org/apache/geode/management/internal/cli/commands/QueryCommandTest.java
 
b/geode-gfsh/src/test/java/org/apache/geode/management/internal/cli/commands/QueryCommandTest.java
new file mode 100644
index 0000000..a64bdfc
--- /dev/null
+++ 
b/geode-gfsh/src/test/java/org/apache/geode/management/internal/cli/commands/QueryCommandTest.java
@@ -0,0 +1,72 @@
+/*
+ * 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.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.junit.Test;
+
+import org.apache.geode.distributed.DistributedMember;
+import org.apache.geode.internal.cache.InternalCache;
+import org.apache.geode.management.internal.cli.domain.DataCommandResult;
+
+public class QueryCommandTest {
+  private final QueryCommand command = new QueryCommand();
+
+  @Test
+  public void targetMemberIsNotSetIfMemberOptionsIsNotUsed() {
+    QueryCommand spyCommand = spy(command);
+    String query = "select query";
+    doReturn(mock(DataCommandResult.class)).when(spyCommand).select(query, 
null);
+
+    spyCommand.query(query, null, false, null);
+
+    verify(spyCommand).select(query, null);
+  }
+
+  @Test
+  public void targetMemberIsSetIfMemberOptionsIsUsed() {
+    QueryCommand spyCommand = spy(command);
+    DistributedMember member = mock(DistributedMember.class);
+    String query = "select query";
+    String memberName = "member";
+    doReturn(member).when(spyCommand).getMember(memberName);
+    doReturn(mock(DataCommandResult.class)).when(spyCommand).select(query, 
member);
+
+    spyCommand.query(query, null, false, memberName);
+
+    verify(spyCommand).select(query, member);
+  }
+
+  @Test
+  public void getQueryRegionsAssociatedMembersInvokedIfNoTargetProvided() {
+    QueryCommand spyCommand = spy(command);
+    InternalCache cache = mock(InternalCache.class);
+    Set<String> regionsInQuery = new HashSet<>();
+    doReturn(new 
HashSet<>()).when(spyCommand).getQueryRegionsAssociatedMembers(cache,
+        regionsInQuery);
+
+    spyCommand.getMembers(null, cache, regionsInQuery);
+
+    verify(spyCommand).getQueryRegionsAssociatedMembers(cache, regionsInQuery);
+  }
+
+}

Reply via email to