You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by ji...@apache.org on 2019/08/14 22:24:07 UTC

[geode] branch develop updated: GEODE-6945:geode-managment should create its own set of configuration… (#3923)

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

jinmeiliao 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 374eff7  GEODE-6945:geode-managment should create its own set of configuration… (#3923)
374eff7 is described below

commit 374eff722708947570eb9367fc626181a1c9f4ce
Author: Jinmei Liao <ji...@pivotal.io>
AuthorDate: Wed Aug 14 15:23:50 2019 -0700

    GEODE-6945:geode-managment should create its own set of configuration… (#3923)
    
    Co-authored-by: Darrel Schneider <ds...@pivotal.io>
    
    * remove regionName in Index configuration object, use regionPath to infer it.
    * support listing indexes for all regions
---
 .../rest/ListIndexManagementDUnitTest.java         |  90 +++++++++++-----
 .../geode/AssemblyContentsIntegrationTest.java     |   1 +
 .../integrationTest/resources/assembly_content.txt |   1 +
 .../api/LocatorClusterManagementService.java       |   3 +
 .../configuration/converters/IndexConverter.java   |  41 ++++++++
 .../configuration/mutators/IndexConfigManager.java |  69 +++++++++++++
 .../sanctioned-geode-management-serializables.txt  |   3 +-
 .../cache/configuration/RegionConfigTest.java      |  39 -------
 .../internal/cache/RegionNameValidationTest.java   |   5 +
 .../mutators/IndexConfigManagerTest.java           | 113 +++++++++++++++++++++
 .../geode/cache/configuration/RegionConfig.java    |  35 +------
 .../geode/management/configuration/Index.java      | 109 ++++++++++++++++++++
 .../configuration/CacheElementJsonMappingTest.java |   2 -
 .../geode/management/configuration/IndexTest.java  |  76 ++++++++++++++
 .../controllers/RegionManagementController.java    |  54 +++++-----
 15 files changed, 510 insertions(+), 131 deletions(-)

diff --git a/geode-assembly/src/distributedTest/java/org/apache/geode/management/internal/rest/ListIndexManagementDUnitTest.java b/geode-assembly/src/distributedTest/java/org/apache/geode/management/internal/rest/ListIndexManagementDUnitTest.java
index 0a1708a..f290e64 100644
--- a/geode-assembly/src/distributedTest/java/org/apache/geode/management/internal/rest/ListIndexManagementDUnitTest.java
+++ b/geode-assembly/src/distributedTest/java/org/apache/geode/management/internal/rest/ListIndexManagementDUnitTest.java
@@ -30,6 +30,7 @@ import org.apache.geode.cache.configuration.RegionType;
 import org.apache.geode.management.api.ClusterManagementListResult;
 import org.apache.geode.management.api.ClusterManagementService;
 import org.apache.geode.management.client.ClusterManagementServiceBuilder;
+import org.apache.geode.management.configuration.Index;
 import org.apache.geode.management.runtime.RuntimeInfo;
 import org.apache.geode.test.dunit.rules.ClusterStartupRule;
 import org.apache.geode.test.dunit.rules.MemberVM;
@@ -102,74 +103,109 @@ public class ListIndexManagementDUnitTest {
 
   @Test
   public void listIndexForOneRegion() {
-    RegionConfig.Index index = new RegionConfig.Index();
-    index.setRegionName("region1");
-    ClusterManagementListResult<RegionConfig.Index, RuntimeInfo> list = cms.list(index);
-    List<RegionConfig.Index> result = list.getConfigResult();
+    Index index = new Index();
+    index.setRegionPath("region1");
+    ClusterManagementListResult<Index, RuntimeInfo> list = cms.list(index);
+    List<Index> result = list.getConfigResult();
+    assertThat(result).hasSize(2);
+  }
+
+  @Test
+  public void listAllIndex() throws Exception {
+    Index index = new Index();
+    ClusterManagementListResult<Index, RuntimeInfo> list = cms.list(index);
+    List<Index> result = list.getConfigResult();
     assertThat(result).hasSize(2);
   }
 
   @Test
   public void getIndex() {
-    RegionConfig.Index index = new RegionConfig.Index();
-    index.setRegionName("region1");
+    Index index = new Index();
+    index.setRegionPath("region1");
     index.setName("index1");
-    ClusterManagementListResult<RegionConfig.Index, RuntimeInfo> list = cms.get(index);
-    List<RegionConfig.Index> result = list.getConfigResult();
+    ClusterManagementListResult<Index, RuntimeInfo> list = cms.get(index);
+    List<Index> result = list.getConfigResult();
     assertThat(result).hasSize(1);
-    RegionConfig.Index runtimeIndex = result.get(0);
+    Index runtimeIndex = result.get(0);
     assertThat(runtimeIndex.getRegionName()).isEqualTo("region1");
     assertThat(runtimeIndex.getName()).isEqualTo("index1");
-    assertThat(runtimeIndex.getFromClause()).isEqualTo("/region1");
+    assertThat(runtimeIndex.getRegionPath()).isEqualTo("/region1");
     assertThat(runtimeIndex.getExpression()).isEqualTo("id");
   }
 
   @Test
   public void getIndexWithoutIndexId() {
-    RegionConfig.Index index = new RegionConfig.Index();
-    index.setRegionName("region1");
+    Index index = new Index();
+    index.setRegionPath("region1");
     assertThatThrownBy(() -> cms.get(index)).isInstanceOf(IllegalArgumentException.class)
         .hasMessageContaining("unable to construct the uri ");
   }
 
   @Test
-  public void getIndexWithoutRegionName() {
-    RegionConfig.Index index = new RegionConfig.Index();
-    index.setName("index1");
+  public void getIndexWithoutRegionNameAndIndexId() {
+    Index index = new Index();
     assertThatThrownBy(() -> cms.get(index)).isInstanceOf(IllegalArgumentException.class)
         .hasMessageContaining("unable to construct the uri ");
   }
 
   @Test
+  public void getIndexWithoutRegionName() {
+    Index index = new Index();
+    index.setName("index1");
+    ClusterManagementListResult<Index, RuntimeInfo> list = cms.list(index);
+    List<Index> result = list.getConfigResult();
+    assertThat(result).hasSize(1);
+    Index runtimeIndex = result.get(0);
+    assertThat(runtimeIndex.getRegionName()).isEqualTo("region1");
+    assertThat(runtimeIndex.getName()).isEqualTo("index1");
+    assertThat(runtimeIndex.getRegionPath()).isEqualTo("/region1");
+    assertThat(runtimeIndex.getExpression()).isEqualTo("id");
+  }
+
+  @Test
+  public void listIndexWithoutRegionName() {
+    Index index = new Index();
+    index.setName("index1");
+    ClusterManagementListResult<Index, RuntimeInfo> list = cms.list(index);
+    List<Index> result = list.getConfigResult();
+    assertThat(result).hasSize(1);
+    Index runtimeIndex = result.get(0);
+    assertThat(runtimeIndex.getRegionName()).isEqualTo("region1");
+    assertThat(runtimeIndex.getName()).isEqualTo("index1");
+    assertThat(runtimeIndex.getRegionPath()).isEqualTo("/region1");
+    assertThat(runtimeIndex.getExpression()).isEqualTo("id");
+  }
+
+  @Test
   public void listIndexesWithIdFilter() {
-    RegionConfig.Index index = new RegionConfig.Index();
-    index.setRegionName("region1");
+    Index index = new Index();
+    index.setRegionPath("region1");
     index.setName("index1");
-    ClusterManagementListResult<RegionConfig.Index, RuntimeInfo> list = cms.list(index);
-    List<RegionConfig.Index> result = list.getConfigResult();
+    ClusterManagementListResult<Index, RuntimeInfo> list = cms.list(index);
+    List<Index> result = list.getConfigResult();
     assertThat(result).hasSize(1);
-    RegionConfig.Index runtimeIndex = result.get(0);
+    Index runtimeIndex = result.get(0);
     assertThat(runtimeIndex.getRegionName()).isEqualTo("region1");
     assertThat(runtimeIndex.getName()).isEqualTo("index1");
-    assertThat(runtimeIndex.getFromClause()).isEqualTo("/region1");
+    assertThat(runtimeIndex.getRegionPath()).isEqualTo("/region1");
     assertThat(runtimeIndex.getExpression()).isEqualTo("id");
   }
 
   @Test
   public void getNonExistingIndex() {
-    RegionConfig.Index index = new RegionConfig.Index();
-    index.setRegionName("region1");
+    Index index = new Index();
+    index.setRegionPath("region1");
     index.setName("index333");
     assertThatThrownBy(() -> cms.get(index)).hasMessageContaining("ENTITY_NOT_FOUND");
   }
 
   @Test
   public void listNonExistingIndexesWithIdFilter() {
-    RegionConfig.Index index = new RegionConfig.Index();
-    index.setRegionName("region1");
+    Index index = new Index();
+    index.setRegionPath("region1");
     index.setName("index333");
-    ClusterManagementListResult<RegionConfig.Index, RuntimeInfo> list = cms.list(index);
-    List<RegionConfig.Index> result = list.getConfigResult();
+    ClusterManagementListResult<Index, RuntimeInfo> list = cms.list(index);
+    List<Index> result = list.getConfigResult();
     assertThat(result).hasSize(0);
     assertThat(list.isSuccessful()).isTrue();
   }
diff --git a/geode-assembly/src/integrationTest/java/org/apache/geode/AssemblyContentsIntegrationTest.java b/geode-assembly/src/integrationTest/java/org/apache/geode/AssemblyContentsIntegrationTest.java
index 1e8632e..7803c01 100644
--- a/geode-assembly/src/integrationTest/java/org/apache/geode/AssemblyContentsIntegrationTest.java
+++ b/geode-assembly/src/integrationTest/java/org/apache/geode/AssemblyContentsIntegrationTest.java
@@ -67,6 +67,7 @@ public class AssemblyContentsIntegrationTest {
         .containsExactlyElementsOf(expectedAssemblyContent);
   }
 
+
   /**
    * Find all of the jars bundled with the project. Key is the name of the jar, value is the path.
    */
diff --git a/geode-assembly/src/integrationTest/resources/assembly_content.txt b/geode-assembly/src/integrationTest/resources/assembly_content.txt
index 538fefd..0e79c85 100644
--- a/geode-assembly/src/integrationTest/resources/assembly_content.txt
+++ b/geode-assembly/src/integrationTest/resources/assembly_content.txt
@@ -726,6 +726,7 @@ javadoc/org/apache/geode/management/client/package-summary.html
 javadoc/org/apache/geode/management/client/package-tree.html
 javadoc/org/apache/geode/management/configuration/ClassName.html
 javadoc/org/apache/geode/management/configuration/GatewayReceiver.html
+javadoc/org/apache/geode/management/configuration/Index.html
 javadoc/org/apache/geode/management/configuration/MemberConfig.html
 javadoc/org/apache/geode/management/configuration/Pdx.html
 javadoc/org/apache/geode/management/configuration/package-frame.html
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/api/LocatorClusterManagementService.java b/geode-core/src/main/java/org/apache/geode/management/internal/api/LocatorClusterManagementService.java
index 116376c..1c39b69 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/api/LocatorClusterManagementService.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/api/LocatorClusterManagementService.java
@@ -61,6 +61,7 @@ import org.apache.geode.management.api.CorrespondWith;
 import org.apache.geode.management.api.RealizationResult;
 import org.apache.geode.management.api.RestfulEndpoint;
 import org.apache.geode.management.configuration.GatewayReceiver;
+import org.apache.geode.management.configuration.Index;
 import org.apache.geode.management.configuration.MemberConfig;
 import org.apache.geode.management.configuration.Pdx;
 import org.apache.geode.management.internal.CacheElementOperation;
@@ -68,6 +69,7 @@ import org.apache.geode.management.internal.ClusterManagementOperationStatusResu
 import org.apache.geode.management.internal.cli.functions.CacheRealizationFunction;
 import org.apache.geode.management.internal.configuration.mutators.ConfigurationManager;
 import org.apache.geode.management.internal.configuration.mutators.GatewayReceiverConfigManager;
+import org.apache.geode.management.internal.configuration.mutators.IndexConfigManager;
 import org.apache.geode.management.internal.configuration.mutators.PdxManager;
 import org.apache.geode.management.internal.configuration.mutators.RegionConfigManager;
 import org.apache.geode.management.internal.configuration.validators.CacheElementValidator;
@@ -101,6 +103,7 @@ public class LocatorClusterManagementService implements ClusterManagementService
     managers.put(RegionConfig.class, new RegionConfigManager());
     managers.put(Pdx.class, new PdxManager());
     managers.put(GatewayReceiver.class, new GatewayReceiverConfigManager());
+    managers.put(Index.class, new IndexConfigManager());
 
     // initialize the list of validators
     validators.put(RegionConfig.class, new RegionConfigValidator(cache));
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/configuration/converters/IndexConverter.java b/geode-core/src/main/java/org/apache/geode/management/internal/configuration/converters/IndexConverter.java
new file mode 100644
index 0000000..0ad5588
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/configuration/converters/IndexConverter.java
@@ -0,0 +1,41 @@
+/*
+ * 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.configuration.converters;
+
+import org.apache.geode.cache.configuration.RegionConfig;
+import org.apache.geode.management.configuration.Index;
+
+public class IndexConverter extends ConfigurationConverter<Index, RegionConfig.Index> {
+  @Override
+  protected Index fromNonNullXmlObject(RegionConfig.Index xmlObject) {
+    Index index = new Index();
+    index.setName(xmlObject.getName());
+    index.setExpression(xmlObject.getExpression());
+    index.setRegionPath(xmlObject.getFromClause());
+    index.setKeyIndex(xmlObject.isKeyIndex());
+    return index;
+  }
+
+  @Override
+  protected RegionConfig.Index fromNonNullConfigObject(Index configObject) {
+    RegionConfig.Index index = new RegionConfig.Index();
+    index.setName(configObject.getName());
+    index.setFromClause(configObject.getRegionPath());
+    index.setExpression(configObject.getExpression());
+    index.setKeyIndex(configObject.getKeyIndex());
+    return index;
+  }
+}
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/configuration/mutators/IndexConfigManager.java b/geode-core/src/main/java/org/apache/geode/management/internal/configuration/mutators/IndexConfigManager.java
new file mode 100644
index 0000000..fc09e49
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/configuration/mutators/IndexConfigManager.java
@@ -0,0 +1,69 @@
+/*
+ * 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.configuration.mutators;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.lang3.NotImplementedException;
+
+import org.apache.geode.cache.configuration.CacheConfig;
+import org.apache.geode.cache.configuration.RegionConfig;
+import org.apache.geode.management.configuration.Index;
+import org.apache.geode.management.internal.configuration.converters.IndexConverter;
+
+public class IndexConfigManager implements ConfigurationManager<Index> {
+  private final IndexConverter converter = new IndexConverter();
+
+  @Override
+  public void add(Index config, CacheConfig existing) {
+    throw new NotImplementedException("Not implemented yet");
+  }
+
+  @Override
+  public void update(Index config, CacheConfig existing) {
+    throw new NotImplementedException("Not implemented yet");
+  }
+
+  @Override
+  public void delete(Index config, CacheConfig existing) {
+    throw new NotImplementedException("Not implemented yet");
+  }
+
+  @Override
+  public List<Index> list(Index filterConfig, CacheConfig existing) {
+    List<Index> result = new ArrayList<>();
+    for (RegionConfig region : existing.getRegions()) {
+      if (filterConfig.getRegionName() != null
+          && !region.getName().equals(filterConfig.getRegionName())) {
+        continue;
+      }
+      for (RegionConfig.Index index : region.getIndexes()) {
+        if (filterConfig.getName() != null && !index.getName().equals(filterConfig.getName())) {
+          continue;
+        }
+        Index matchingIndex = converter.fromXmlObject(index);
+        result.add(matchingIndex);
+      }
+    }
+    return result;
+  }
+
+  @Override
+  public Index get(String id, CacheConfig existing) {
+    throw new NotImplementedException("Not implemented yet");
+  }
+}
diff --git a/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-management-serializables.txt b/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-management-serializables.txt
index 9cc6fba..ec30170 100644
--- a/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-management-serializables.txt
+++ b/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-management-serializables.txt
@@ -28,12 +28,13 @@ org/apache/geode/cache/configuration/RegionAttributesType$PartitionAttributes,fa
 org/apache/geode/cache/configuration/RegionAttributesType$SubscriptionAttributes,false,interestPolicy:java/lang/String
 org/apache/geode/cache/configuration/RegionConfig,false,entries:java/util/List,indexes:java/util/List,name:java/lang/String,regionAttributes:org/apache/geode/cache/configuration/RegionAttributesType,regionElements:java/util/List,regions:java/util/List,type:java/lang/String
 org/apache/geode/cache/configuration/RegionConfig$Entry,false,key:org/apache/geode/cache/configuration/ObjectType,value:org/apache/geode/cache/configuration/ObjectType
-org/apache/geode/cache/configuration/RegionConfig$Index,false,expression:java/lang/String,fromClause:java/lang/String,imports:java/lang/String,keyIndex:java/lang/Boolean,name:java/lang/String,regionName:java/lang/String,type:java/lang/String
+org/apache/geode/cache/configuration/RegionConfig$Index,false,expression:java/lang/String,fromClause:java/lang/String,imports:java/lang/String,keyIndex:java/lang/Boolean,name:java/lang/String,type:java/lang/String
 org/apache/geode/cache/configuration/RegionType,false
 org/apache/geode/management/api/ClusterManagementResult$StatusCode,false
 org/apache/geode/management/api/RealizationResult,false,memberName:java/lang/String,message:java/lang/String,success:boolean
 org/apache/geode/management/configuration/ClassName,true,1,className:java/lang/String,initProperties:java/util/Properties
 org/apache/geode/management/configuration/GatewayReceiver,false,endPort:java/lang/Integer,gatewayTransportFilters:java/util/List,manualStart:java/lang/Boolean,maximumTimeBetweenPings:java/lang/Integer,socketBufferSize:java/lang/Integer,startPort:java/lang/Integer
+org/apache/geode/management/configuration/Index,false,expression:java/lang/String,keyIndex:java/lang/Boolean,name:java/lang/String,regionPath:java/lang/String
 org/apache/geode/management/configuration/MemberConfig,false,id:java/lang/String
 org/apache/geode/management/configuration/Pdx,false,diskStoreName:java/lang/String,ignoreUnreadFields:java/lang/Boolean,pdxSerializer:org/apache/geode/management/configuration/ClassName,persistent:java/lang/Boolean,readSerialized:java/lang/Boolean
 org/apache/geode/management/runtime/CacheServerInfo,true,1,bindAddress:java/lang/String,isRunning:boolean,maxConnections:int,maxThreads:int,port:int
diff --git a/geode-core/src/test/java/org/apache/geode/cache/configuration/RegionConfigTest.java b/geode-core/src/test/java/org/apache/geode/cache/configuration/RegionConfigTest.java
index d2a641d..c2a806e 100644
--- a/geode-core/src/test/java/org/apache/geode/cache/configuration/RegionConfigTest.java
+++ b/geode-core/src/test/java/org/apache/geode/cache/configuration/RegionConfigTest.java
@@ -32,7 +32,6 @@ import org.apache.geode.internal.config.JAXBService;
 import org.apache.geode.management.api.RestfulEndpoint;
 import org.apache.geode.management.internal.CacheElementOperation;
 import org.apache.geode.management.internal.configuration.validators.RegionConfigValidator;
-import org.apache.geode.management.runtime.RuntimeInfo;
 import org.apache.geode.management.runtime.RuntimeRegionInfo;
 import org.apache.geode.util.internal.GeodeJsonMapper;
 
@@ -155,37 +154,6 @@ public class RegionConfigTest {
   }
 
   @Test
-  public void invalidRegionName() throws Exception {
-    RegionConfig.Index index = new RegionConfig.Index();
-    index.setExpression("id");
-    index.setName("index1");
-    index.setFromClause("/regionA");
-
-    assertThatThrownBy(() -> index.setRegionName("regionB"))
-        .isInstanceOf(IllegalArgumentException.class);
-  }
-
-  @Test
-  public void fromClauseInferredByRegionName() throws Exception {
-    RegionConfig.Index index = new RegionConfig.Index();
-    index.setExpression("id");
-    index.setName("index1");
-    index.setRegionName("regionA");
-
-    assertThat(index.getFromClause()).isEqualTo("/regionA");
-
-    CacheConfig cacheConfig = new CacheConfig();
-    regionConfig.getIndexes().clear();
-    regionConfig.getIndexes().add(index);
-    cacheConfig.getRegions().add(regionConfig);
-
-    // the end xml should not have "type" attribute in index definition
-    String newXml = service.marshall(cacheConfig);
-    System.out.println(newXml);
-    assertThat(newXml).contains("from-clause=");
-  }
-
-  @Test
   public void diskDirTypeInXml() throws Exception {
     CacheConfig cacheConfig = new CacheConfig();
     DiskStoreType diskStore = new DiskStoreType();
@@ -277,11 +245,4 @@ public class RegionConfigTest {
     assertThat(config.getRuntimeClass()).isEqualTo(RuntimeRegionInfo.class);
     assertThat(config.hasRuntimeInfo()).isTrue();
   }
-
-  @Test
-  public void getIndexRuntimeClass() throws Exception {
-    RegionConfig.Index index = new RegionConfig.Index();
-    assertThat(index.getRuntimeClass()).isEqualTo(RuntimeInfo.class);
-    assertThat(index.hasRuntimeInfo()).isFalse();
-  }
 }
diff --git a/geode-core/src/test/java/org/apache/geode/internal/cache/RegionNameValidationTest.java b/geode-core/src/test/java/org/apache/geode/internal/cache/RegionNameValidationTest.java
index c7ccf19..58b1ca8 100644
--- a/geode-core/src/test/java/org/apache/geode/internal/cache/RegionNameValidationTest.java
+++ b/geode-core/src/test/java/org/apache/geode/internal/cache/RegionNameValidationTest.java
@@ -137,6 +137,11 @@ public class RegionNameValidationTest {
   }
 
   @Test
+  public void nameWithDot() throws Exception {
+    validate("valid.valid");
+  }
+
+  @Test
   public void endingWithDoubleHyphenIsOk() {
     validate("validRegionName--");
   }
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/configuration/mutators/IndexConfigManagerTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/configuration/mutators/IndexConfigManagerTest.java
new file mode 100644
index 0000000..91a1f78
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/management/internal/configuration/mutators/IndexConfigManagerTest.java
@@ -0,0 +1,113 @@
+/*
+ * 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.configuration.mutators;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.geode.cache.configuration.CacheConfig;
+import org.apache.geode.cache.configuration.RegionConfig;
+import org.apache.geode.management.configuration.Index;
+
+public class IndexConfigManagerTest {
+
+  private CacheConfig cacheConfig;
+  private Index index;
+  private IndexConfigManager manager;
+
+  @Before
+  public void before() throws Exception {
+    cacheConfig = new CacheConfig();
+    index = new Index();
+    manager = new IndexConfigManager();
+  }
+
+  @Test
+  public void emptyConfig() throws Exception {
+    assertThat(manager.list(index, cacheConfig)).isEmpty();
+  }
+
+  @Test
+  public void listWithoutFilter() throws Exception {
+    setupCacheConfig();
+    List<Index> list = manager.list(index, cacheConfig);
+    assertThat(list).hasSize(2)
+        .extracting(i -> i.getName())
+        .containsExactlyInAnyOrder("index1", "index2");
+    assertThat(list).extracting(i -> i.getRegionName())
+        .containsExactlyInAnyOrder("region1", "region2");
+  }
+
+  @Test
+  public void listWithRegionName() throws Exception {
+    setupCacheConfig();
+    index.setRegionPath("region1");
+    List<Index> list = manager.list(index, cacheConfig);
+    assertThat(list).hasSize(1);
+    assertThat(list.get(0).getName()).isEqualTo("index1");
+    assertThat(list.get(0).getRegionName()).isEqualTo("region1");
+  }
+
+  @Test
+  public void listWithIndexName() throws Exception {
+    setupCacheConfig();
+    index.setName("index2");
+    List<Index> list = manager.list(index, cacheConfig);
+    assertThat(list).hasSize(1);
+    assertThat(list.get(0).getName()).isEqualTo("index2");
+    assertThat(list.get(0).getRegionName()).isEqualTo("region2");
+  }
+
+  @Test
+  public void listWithUnMatchingFilter() throws Exception {
+    setupCacheConfig();
+    index.setName("index1");
+    index.setRegionPath("region2");
+    List<Index> list = manager.list(index, cacheConfig);
+    assertThat(list).hasSize(0);
+  }
+
+  @Test
+  public void listWithRegionNameAndIndexName() throws Exception {
+    setupCacheConfig();
+    index.setName("index2");
+    index.setRegionPath("region2");
+    List<Index> list = manager.list(index, cacheConfig);
+    assertThat(list).hasSize(1);
+    assertThat(list.get(0).getName()).isEqualTo("index2");
+    assertThat(list.get(0).getRegionName()).isEqualTo("region2");
+  }
+
+  private void setupCacheConfig() {
+    RegionConfig region1 = new RegionConfig("region1", "REPLICATE");
+    RegionConfig.Index index1 = new RegionConfig.Index();
+    index1.setName("index1");
+    index1.setFromClause("/region1");
+    region1.getIndexes().add(index1);
+
+    RegionConfig region2 = new RegionConfig("region2", "REPLICATE");
+    RegionConfig.Index index2 = new RegionConfig.Index();
+    index2.setName("index2");
+    index2.setFromClause("/region2");
+    region2.getIndexes().add(index2);
+    cacheConfig.getRegions().add(region1);
+    cacheConfig.getRegions().add(region2);
+  }
+}
diff --git a/geode-management/src/main/java/org/apache/geode/cache/configuration/RegionConfig.java b/geode-management/src/main/java/org/apache/geode/cache/configuration/RegionConfig.java
index a334527..2204f22 100644
--- a/geode-management/src/main/java/org/apache/geode/cache/configuration/RegionConfig.java
+++ b/geode-management/src/main/java/org/apache/geode/cache/configuration/RegionConfig.java
@@ -28,17 +28,15 @@ import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlAnyElement;
 import javax.xml.bind.annotation.XmlAttribute;
 import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlTransient;
 import javax.xml.bind.annotation.XmlType;
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import io.swagger.annotations.ApiModelProperty;
-import org.apache.commons.lang3.StringUtils;
 
 import org.apache.geode.annotations.Experimental;
+import org.apache.geode.lang.Identifiable;
 import org.apache.geode.management.api.CorrespondWith;
 import org.apache.geode.management.api.RestfulEndpoint;
-import org.apache.geode.management.runtime.RuntimeInfo;
 import org.apache.geode.management.runtime.RuntimeRegionInfo;
 
 
@@ -540,8 +538,7 @@ public class RegionConfig extends CacheElement implements RestfulEndpoint,
    *
    */
   @XmlAccessorType(XmlAccessType.FIELD)
-  public static class Index extends CacheElement
-      implements RestfulEndpoint, CorrespondWith<RuntimeInfo> {
+  public static class Index implements Identifiable<String> {
     @XmlAttribute(name = "name", required = true)
     protected String name;
     @XmlAttribute(name = "expression")
@@ -554,8 +551,6 @@ public class RegionConfig extends CacheElement implements RestfulEndpoint,
     protected Boolean keyIndex;
     @XmlAttribute(name = "type")
     protected String type; // for non-key index type, range or hash
-    @XmlTransient
-    protected String regionName;
 
     public Index() {}
 
@@ -724,37 +719,11 @@ public class RegionConfig extends CacheElement implements RestfulEndpoint,
       }
     }
 
-    public String getRegionName() {
-      return regionName;
-    }
-
-    public void setRegionName(String regionName) {
-      this.regionName = regionName;
-      if (StringUtils.isBlank(regionName)) {
-        return;
-      }
-
-      if (fromClause == null) {
-        fromClause = "/" + regionName;
-      } else if (!fromClause.contains(regionName)) {
-        throw new IllegalArgumentException(
-            "Invalid regionName for this index with fromClause = " + fromClause);
-      }
-    }
-
     @Override
     @JsonIgnore
     public String getId() {
       return getName();
     }
-
-    @Override
-    public String getEndpoint() {
-      if (StringUtils.isBlank(regionName)) {
-        return null;
-      }
-      return RegionConfig.REGION_CONFIG_ENDPOINT + "/" + regionName + "/indexes";
-    }
   }
 
 }
diff --git a/geode-management/src/main/java/org/apache/geode/management/configuration/Index.java b/geode-management/src/main/java/org/apache/geode/management/configuration/Index.java
new file mode 100644
index 0000000..7fcf0b0
--- /dev/null
+++ b/geode-management/src/main/java/org/apache/geode/management/configuration/Index.java
@@ -0,0 +1,109 @@
+/*
+ * 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.configuration;
+
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import org.apache.commons.lang3.StringUtils;
+
+import org.apache.geode.cache.configuration.CacheElement;
+import org.apache.geode.cache.configuration.RegionConfig;
+import org.apache.geode.management.api.CorrespondWith;
+import org.apache.geode.management.api.RestfulEndpoint;
+import org.apache.geode.management.runtime.RuntimeInfo;
+
+public class Index extends CacheElement
+    implements RestfulEndpoint, CorrespondWith<RuntimeInfo> {
+
+  private String name;
+  private String expression;
+  private String regionPath;
+  private Boolean keyIndex;
+
+  public String getName() {
+    return name;
+  }
+
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  public String getExpression() {
+    return expression;
+  }
+
+  public void setExpression(String expression) {
+    this.expression = expression;
+  }
+
+  public String getRegionPath() {
+    return regionPath;
+  }
+
+  /**
+   * the regionPath can be in any of these forms, e.g.:
+   * 1. regionName
+   * 2. /regionName
+   * 3. /regionName alias
+   * 4. /regionName.entrySet()
+   * 5. /regionName.fieldName.entrySet() alias
+   */
+  public void setRegionPath(String regionPath) {
+    this.regionPath = regionPath;
+  }
+
+  public Boolean getKeyIndex() {
+    return keyIndex;
+  }
+
+  public void setKeyIndex(Boolean keyIndex) {
+    this.keyIndex = keyIndex;
+  }
+
+  /**
+   * @return the regionName specified in the regionPath.
+   *         Note this method assumes the regionName should not contain "."
+   */
+  @JsonIgnore
+  public String getRegionName() {
+    if (regionPath == null) {
+      return null;
+    }
+
+    String regionName = regionPath.trim().split(" ")[0];
+    regionName = StringUtils.removeStart(regionName, "/");
+    if (regionName.contains(".")) {
+      regionName = regionName.substring(0, regionName.indexOf('.'));
+    }
+
+    return regionName;
+  }
+
+  @Override
+  @JsonIgnore
+  public String getId() {
+    return getName();
+  }
+
+  @Override
+  public String getEndpoint() {
+    String regionName = getRegionName();
+    if (StringUtils.isBlank(regionName)) {
+      return "/indexes";
+    }
+    return RegionConfig.REGION_CONFIG_ENDPOINT + "/" + regionName + "/indexes";
+  }
+}
diff --git a/geode-management/src/test/java/org/apache/geode/cache/configuration/CacheElementJsonMappingTest.java b/geode-management/src/test/java/org/apache/geode/cache/configuration/CacheElementJsonMappingTest.java
index 1ed0fad..f42ecf5 100644
--- a/geode-management/src/test/java/org/apache/geode/cache/configuration/CacheElementJsonMappingTest.java
+++ b/geode-management/src/test/java/org/apache/geode/cache/configuration/CacheElementJsonMappingTest.java
@@ -140,7 +140,6 @@ public class CacheElementJsonMappingTest {
     RegionConfig.Index index = new RegionConfig.Index();
     index.setName("index1");
     index.setFromClause("/region1 r");
-    index.setRegionName("region1");
     index.setExpression("id");
     config.getIndexes().add(index);
     String json = mapper.writeValueAsString(config);
@@ -150,7 +149,6 @@ public class CacheElementJsonMappingTest {
     assertThat(config1.getGroups()).containsExactly("group1");
     List<RegionConfig.Index> indexes = config1.getIndexes();
     assertThat(indexes).hasSize(1);
-    assertThat(indexes.get(0).getRegionName()).isEqualTo("region1");
   }
 
   @Test
diff --git a/geode-management/src/test/java/org/apache/geode/management/configuration/IndexTest.java b/geode-management/src/test/java/org/apache/geode/management/configuration/IndexTest.java
new file mode 100644
index 0000000..42d7698
--- /dev/null
+++ b/geode-management/src/test/java/org/apache/geode/management/configuration/IndexTest.java
@@ -0,0 +1,76 @@
+/*
+ * 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.configuration;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.geode.management.runtime.RuntimeInfo;
+
+public class IndexTest {
+  private Index index;
+
+  @Before
+  public void before() throws Exception {
+    index = new Index();
+  }
+
+  @Test
+  public void getIndexRuntimeClass() throws Exception {
+    assertThat(index.getRuntimeClass()).isEqualTo(RuntimeInfo.class);
+    assertThat(index.hasRuntimeInfo()).isFalse();
+  }
+
+  @Test
+  public void getRegionName() throws Exception {
+    index.setRegionPath(null);
+    assertThat(index.getRegionName()).isNull();
+
+    index.setRegionPath("regionA");
+    assertThat(index.getRegionName()).isEqualTo("regionA");
+
+    index.setRegionPath("   regionA   ");
+    assertThat(index.getRegionName()).isEqualTo("regionA");
+
+    index.setRegionPath("/regionA");
+    assertThat(index.getRegionName()).isEqualTo("regionA");
+
+    index.setRegionPath("/regionA.method()");
+    assertThat(index.getRegionName()).isEqualTo("regionA");
+
+    index.setRegionPath("/regionA.method() a");
+    assertThat(index.getRegionName()).isEqualTo("regionA");
+
+    index.setRegionPath("/regionA.fieled.method() a");
+    assertThat(index.getRegionName()).isEqualTo("regionA");
+
+    index.setRegionPath("/regionA a");
+    assertThat(index.getRegionName()).isEqualTo("regionA");
+
+    index.setRegionPath("/regionA a, a.foo");
+    assertThat(index.getRegionName()).isEqualTo("regionA");
+  }
+
+  @Test
+  public void getEndPoint() throws Exception {
+    assertThat(index.getEndpoint()).isEqualTo("/indexes");
+
+    index.setRegionPath("/regionA");
+    assertThat(index.getEndpoint()).isEqualTo("/regions/regionA/indexes");
+  }
+}
diff --git a/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/controllers/RegionManagementController.java b/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/controllers/RegionManagementController.java
index 6fa9a1c..1c208da 100644
--- a/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/controllers/RegionManagementController.java
+++ b/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/controllers/RegionManagementController.java
@@ -18,10 +18,7 @@ package org.apache.geode.management.internal.rest.controllers;
 import static org.apache.geode.cache.configuration.RegionConfig.REGION_CONFIG_ENDPOINT;
 import static org.apache.geode.management.internal.rest.controllers.AbstractManagementController.MANAGEMENT_API_VERSION;
 
-import java.util.ArrayList;
 import java.util.List;
-import java.util.Objects;
-import java.util.stream.Collectors;
 
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiResponse;
@@ -44,6 +41,7 @@ import org.apache.geode.management.api.ClusterManagementListResult;
 import org.apache.geode.management.api.ClusterManagementResult;
 import org.apache.geode.management.api.ClusterManagementResult.StatusCode;
 import org.apache.geode.management.api.ConfigurationResult;
+import org.apache.geode.management.configuration.Index;
 import org.apache.geode.management.runtime.RuntimeInfo;
 import org.apache.geode.management.runtime.RuntimeRegionInfo;
 import org.apache.geode.security.ResourcePermission.Operation;
@@ -112,36 +110,34 @@ public class RegionManagementController extends AbstractManagementController {
     return clusterManagementService.delete(config);
   }
 
-  @ApiOperation(value = "list indexes")
+  @ApiOperation(value = "list region indexes")
   @RequestMapping(method = RequestMethod.GET,
       value = REGION_CONFIG_ENDPOINT + "/{regionName}/indexes")
   @ResponseBody
   @PreAuthorize("@securityService.authorize('CLUSTER', 'READ', 'QUERY')")
-  public ClusterManagementListResult<RegionConfig.Index, RuntimeInfo> listIndex(
+  public ClusterManagementListResult<Index, RuntimeInfo> listIndex(
       @PathVariable String regionName,
-      @RequestParam(required = false) String id) {
-
-    ClusterManagementListResult<RegionConfig, RuntimeRegionInfo> result0 = getRegion(regionName);
-    RegionConfig regionConfig = result0.getResult().get(0).getConfig();
-
-    // only send the index information back
-    List<RegionConfig.Index> indexList = regionConfig.getIndexes().stream().map(e -> {
-      if (StringUtils.isNotBlank(id) && !e.getId().equals(id)) {
-        return null;
-      }
-      e.setRegionName(regionName);
-      return e;
-    }).filter(Objects::nonNull).collect(Collectors.toList());
-
-    List<ConfigurationResult<RegionConfig.Index, RuntimeInfo>> responses = new ArrayList<>();
-    for (RegionConfig.Index index : indexList) {
-      responses.add(new ConfigurationResult<>(index));
+      @RequestParam(required = false, name = "id") String indexName) {
+
+    Index filter = new Index();
+    filter.setRegionPath(regionName);
+    if (StringUtils.isNotBlank(indexName)) {
+      filter.setName(indexName);
     }
+    return clusterManagementService.list(filter);
+  }
 
-    ClusterManagementListResult<RegionConfig.Index, RuntimeInfo> result =
-        new ClusterManagementListResult<>();
-    result.setResult(responses);
-    return result;
+  @ApiOperation(value = "list indexes")
+  @RequestMapping(method = RequestMethod.GET, value = "/indexes")
+  @ResponseBody
+  @PreAuthorize("@securityService.authorize('CLUSTER', 'READ', 'QUERY')")
+  public ClusterManagementListResult<Index, RuntimeInfo> listAllIndex(
+      @RequestParam(required = false, name = "id") String indexName) {
+    Index filter = new Index();
+    if (StringUtils.isNotBlank(indexName)) {
+      filter.setName(indexName);
+    }
+    return clusterManagementService.list(filter);
   }
 
   @ApiOperation(value = "get index")
@@ -149,11 +145,11 @@ public class RegionManagementController extends AbstractManagementController {
       value = REGION_CONFIG_ENDPOINT + "/{regionName}/indexes/{id}")
   @ResponseBody
   @PreAuthorize("@securityService.authorize('CLUSTER', 'READ', 'QUERY')")
-  public ClusterManagementListResult<RegionConfig.Index, RuntimeInfo> getIndex(
+  public ClusterManagementListResult<Index, RuntimeInfo> getIndex(
       @PathVariable String regionName,
       @PathVariable String id) {
-    ClusterManagementListResult<RegionConfig.Index, RuntimeInfo> result = listIndex(regionName, id);
-    List<ConfigurationResult<RegionConfig.Index, RuntimeInfo>> indexList = result.getResult();
+    ClusterManagementListResult<Index, RuntimeInfo> result = listIndex(regionName, id);
+    List<ConfigurationResult<Index, RuntimeInfo>> indexList = result.getResult();
 
     if (indexList.size() == 0) {
       throw new ClusterManagementException(new ClusterManagementResult(StatusCode.ENTITY_NOT_FOUND,