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 e50c5e3  GEODE-7425 delete index (#4503)
e50c5e3 is described below

commit e50c5e3a46b5c5501a091a68d9312fbf0e599b1c
Author: Darrel Schneider <[email protected]>
AuthorDate: Fri Dec 20 21:14:49 2019 -0800

    GEODE-7425 delete index (#4503)
    
    Co-authored-by: Joris Melchior <[email protected]>
    Co-authored-by: Jinmei Liao <[email protected]>
    Co-authored-by: Darrel Schneider <[email protected]>
---
 .../rest/ListIndexManagementDUnitTest.java         | 211 +++++++++++++++------
 .../configuration/mutators/IndexConfigManager.java |  21 +-
 .../configuration/realizers/IndexRealizer.java     |  43 ++++-
 .../configuration/validators/IndexValidator.java   |  57 +++---
 .../mutators/IndexConfigManagerTest.java           | 132 +++++++++++--
 .../configuration/realizers/IndexRealizerTest.java |  57 ++++++
 .../validators/IndexValidatorTest.java             |  22 ++-
 .../api/ClusterManagementRealizationResult.java    |   1 +
 ...usterManagementSecurityRestIntegrationTest.java |   7 +
 .../rest/RegionManagementControllerSpringTest.java |  20 ++
 .../rest/RegionManagementIntegrationTest.java      | 197 ++++++++++++++++---
 .../controllers/RegionManagementController.java    |  16 ++
 12 files changed, 648 insertions(+), 136 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 972c28a..c6af595 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
@@ -31,6 +31,7 @@ import org.junit.Test;
 import org.apache.geode.cache.query.QueryService;
 import org.apache.geode.management.api.ClusterManagementGetResult;
 import org.apache.geode.management.api.ClusterManagementListResult;
+import org.apache.geode.management.api.ClusterManagementRealizationResult;
 import org.apache.geode.management.api.ClusterManagementService;
 import org.apache.geode.management.api.ConfigurationResult;
 import org.apache.geode.management.client.ClusterManagementServiceBuilder;
@@ -46,18 +47,20 @@ import org.apache.geode.test.junit.rules.MemberStarterRule;
 public class ListIndexManagementDUnitTest {
 
   private Region regionConfig;
-  private Index index;
+  private Index indexConfig;
 
   @ClassRule
   public static ClusterStartupRule lsRule = new ClusterStartupRule();
 
   private static ClusterManagementService cms;
+  private static MemberVM locator;
 
   @BeforeClass
   public static void beforeClass() {
-    MemberVM locator = lsRule.startLocatorVM(0, 
MemberStarterRule::withHttpService);
+    locator = lsRule.startLocatorVM(0, MemberStarterRule::withHttpService);
     MemberVM server1 = lsRule.startServerVM(1, locator.getPort());
     MemberVM server2 = lsRule.startServerVM(2, locator.getPort());
+    MemberVM server3 = lsRule.startServerVM(3, "group1", locator.getPort());
 
     cms = ClusterManagementServiceBuilder.buildWithHostAddress()
         .setHostAddress("localhost", locator.getHttpPort())
@@ -67,7 +70,7 @@ public class ListIndexManagementDUnitTest {
     config.setName("region1");
     config.setType(RegionType.REPLICATE);
     cms.create(config);
-    locator.waitUntilRegionIsReadyOnExactlyThisManyServers("/region1", 2);
+    locator.waitUntilRegionIsReadyOnExactlyThisManyServers("/region1", 3);
 
     Index index1 = new Index();
     index1.setName("index1");
@@ -92,104 +95,110 @@ public class ListIndexManagementDUnitTest {
           .containsExactlyInAnyOrder("index1", "index2");
       assertThat(indexes.stream().findFirst()
           .filter(index -> 
index.getRegion().getName().equals("region1")).isPresent()).isTrue();
-    }, server1, server2);
+    }, server1, server2, server3);
   }
 
   @Before
   public void before() {
     regionConfig = new Region();
-    index = new Index();
+    indexConfig = new Index();
   }
 
   @Test
-  public void listRegion() {
+  public void listRegion_succeeds_with_empty_filter() {
     List<Region> result =
         cms.list(new Region()).getConfigResult();
     assertThat(result).hasSize(1);
   }
 
   @Test
-  public void getRegion() {
+  public void getRegion_succeeds_with_region_name_filter() {
     regionConfig.setName("region1");
     Region region = cms.get(regionConfig).getConfigResult();
     assertThat(region).isNotNull();
   }
 
   @Test
-  public void getNonExistRegion() {
+  public void getRegion_fails_with_non_existent_region_name_in_filter() {
     regionConfig.setName("notExist");
     assertThatThrownBy(() -> 
cms.get(regionConfig)).hasMessageContaining("ENTITY_NOT_FOUND");
   }
 
   @Test
-  public void listIndexForOneRegion() {
-    index.setRegionPath("region1");
-    ClusterManagementListResult<Index, IndexInfo> list = cms.list(index);
+  public void listIndex_succeeds_for_region_name_filter() {
+    indexConfig.setRegionPath("region1");
+    ClusterManagementListResult<Index, IndexInfo> list = cms.list(indexConfig);
     List<Index> result = list.getConfigResult();
     assertThat(result).hasSize(2);
   }
 
   @Test
-  public void listAllIndex() {
-    ClusterManagementListResult<Index, IndexInfo> list = cms.list(index);
+  public void listIndex_succeeds_for_all_indexes() {
+    ClusterManagementListResult<Index, IndexInfo> list = cms.list(indexConfig);
     List<Index> result = list.getConfigResult();
     assertThat(result).hasSize(2);
   }
 
   @Test
-  public void getIndex() {
-    index.setRegionPath("/region1");
-    index.setName("index1");
-    ClusterManagementGetResult<Index, IndexInfo> clusterManagementGetResult = 
cms.get(index);
+  public void getIndex_succeeds_with_index_name_and_region_name_filter() {
+    indexConfig.setRegionPath("/region1");
+    indexConfig.setName("index1");
+    ClusterManagementGetResult<Index, IndexInfo> clusterManagementGetResult = 
cms.get(indexConfig);
     Index indexConfig = clusterManagementGetResult.getConfigResult();
     List<IndexInfo> runtimeResult = 
clusterManagementGetResult.getRuntimeResult();
 
     assertSoftly(softly -> {
-      softly.assertThat(indexConfig.getRegionName()).isEqualTo("region1");
-      softly.assertThat(indexConfig.getName()).isEqualTo("index1");
-      softly.assertThat(indexConfig.getRegionPath()).isEqualTo("/region1");
-      softly.assertThat(indexConfig.getExpression()).isEqualTo("id");
-      ConfigurationResult<Index, IndexInfo> configurationResult = 
cms.get(index).getResult();
+      softly.assertThat(indexConfig.getRegionName()).as("get index: region 
name")
+          .isEqualTo("region1");
+      softly.assertThat(indexConfig.getName()).as("get index: index 
name").isEqualTo("index1");
+      softly.assertThat(indexConfig.getRegionPath()).as("get index: region 
path")
+          .isEqualTo("/region1");
+      softly.assertThat(indexConfig.getExpression()).as("get index: 
expression").isEqualTo("id");
+      ConfigurationResult<Index, IndexInfo> configurationResult =
+          cms.get(this.indexConfig).getResult();
       Index indexConfigTwo = configurationResult.getConfiguration();
-      
softly.assertThat(indexConfigTwo.getLinks().getLinks()).containsKey("region");
+      softly.assertThat(indexConfigTwo.getLinks().getLinks()).as("get index: 
links key")
+          .containsKey("region");
       softly.assertThat(indexConfigTwo.getLinks().getLinks().get("region"))
+          .as("get index: links value")
           .endsWith("regions/region1");
       softly.assertThat(runtimeResult).extracting(IndexInfo::getMemberName)
-          .containsExactlyInAnyOrder("server-1", "server-2");
+          .as("get index: runtime servers")
+          .containsExactlyInAnyOrder("server-1", "server-2", "server-3");
     });
   }
 
   @Test
-  public void getIndexWithoutIndexId() {
-    index.setRegionPath("region1");
-    assertThatThrownBy(() -> 
cms.get(index)).isInstanceOf(IllegalArgumentException.class)
+  public void getIndex_fails_with_region_name_only_filter() {
+    indexConfig.setRegionPath("region1");
+    assertThatThrownBy(() -> 
cms.get(indexConfig)).isInstanceOf(IllegalArgumentException.class)
         .hasMessageContaining("Unable to construct the URI ");
   }
 
   @Test
-  public void getIndexWithoutRegionNameAndIndexId() {
-    assertThatThrownBy(() -> 
cms.get(index)).isInstanceOf(IllegalArgumentException.class)
+  public void getIndex_fails_when_index_name_and_region_name_are_missing() {
+    assertThatThrownBy(() -> 
cms.get(indexConfig)).isInstanceOf(IllegalArgumentException.class)
         .hasMessageContaining("Unable to construct the URI ");
   }
 
   @Test
-  public void getIndexWithoutRegionName() {
-    index.setName("index1");
-    assertThatThrownBy(() -> cms.get(index))
+  public void getIndex_fails_when_region_name_is_missing_from_filter() {
+    indexConfig.setName("index1");
+    assertThatThrownBy(() -> cms.get(indexConfig))
         .hasMessageContaining("Error while extracting response for type");
   }
 
   @Test
-  public void listIndexWithoutRegionName() {
-    index.setName("index1");
-    assertListIndexResult(index);
+  public void listIndex_succeeds_with_index_name_only_filter() {
+    indexConfig.setName("index1");
+    assertListIndexResult(indexConfig);
   }
 
   @Test
-  public void listIndexesWithIdFilter() {
-    index.setRegionPath("region1");
-    index.setName("index1");
-    assertListIndexResult(index);
+  public void listIndex_succeeds_with_region_name_and_index_name_filter() {
+    indexConfig.setRegionPath("region1");
+    indexConfig.setName("index1");
+    assertListIndexResult(indexConfig);
   }
 
   private void assertListIndexResult(Index index) {
@@ -199,31 +208,125 @@ public class ListIndexManagementDUnitTest {
     assertSoftly(softly -> {
       softly.assertThat(result).hasSize(1);
       Index indexConfig = result.get(0);
-      softly.assertThat(indexConfig.getRegionName()).isEqualTo("region1");
-      softly.assertThat(indexConfig.getName()).isEqualTo("index1");
-      softly.assertThat(indexConfig.getRegionPath()).isEqualTo("/region1");
-      softly.assertThat(indexConfig.getExpression()).isEqualTo("id");
+      softly.assertThat(indexConfig.getRegionName()).as("list index: region 
name")
+          .isEqualTo("region1");
+      softly.assertThat(indexConfig.getName()).as("list index: index 
name").isEqualTo("index1");
+      softly.assertThat(indexConfig.getRegionPath()).as("list index: region 
path")
+          .isEqualTo("/region1");
+      softly.assertThat(indexConfig.getExpression()).as("list index: 
expression").isEqualTo("id");
       softly.assertThat(runtimeResult).extracting(IndexInfo::getMemberName)
-          .containsExactlyInAnyOrder("server-1", "server-2");
+          .as("list index: runtime servers")
+          .containsExactlyInAnyOrder("server-1", "server-2", "server-3");
     });
   }
 
   @Test
-  public void getNonExistingIndex() {
-    index.setRegionPath("region1");
-    index.setName("index333");
-    assertThatThrownBy(() -> 
cms.get(index)).hasMessageContaining("ENTITY_NOT_FOUND");
+  public void getIndex_fails_with_wrong_index_name_in_filter() {
+    indexConfig.setRegionPath("region1");
+    indexConfig.setName("index333");
+    assertThatThrownBy(() -> 
cms.get(indexConfig)).hasMessageContaining("ENTITY_NOT_FOUND");
   }
 
   @Test
-  public void listNonExistingIndexesWithIdFilter() {
-    index.setRegionPath("region1");
-    index.setName("index333");
-    ClusterManagementListResult<Index, IndexInfo> list = cms.list(index);
+  public void listIndex_fails_with_wrong_index_name_in_filter() {
+    indexConfig.setRegionPath("region1");
+    indexConfig.setName("index333");
+    ClusterManagementListResult<Index, IndexInfo> list = cms.list(indexConfig);
     List<Index> result = list.getConfigResult();
     assertSoftly(softly -> {
-      softly.assertThat(result).hasSize(0);
-      softly.assertThat(list.isSuccessful()).isTrue();
+      softly.assertThat(result).as("list non existing: result 
size").hasSize(0);
+      softly.assertThat(list.isSuccessful()).as("list non existing: 
success").isTrue();
+    });
+  }
+
+  @Test
+  public void createAndDeleteIndex_success_for_specific_group() {
+    Region region = new Region();
+    region.setName("region2");
+    region.setType(RegionType.REPLICATE);
+    region.setGroup("group1");
+    cms.create(region);
+    locator.waitUntilRegionIsReadyOnExactlyThisManyServers("/region2", 1);
+
+    Index index = new Index();
+    index.setName("index");
+    index.setExpression("key");
+    index.setRegionPath("/region2");
+    index.setGroup("group1");
+    index.setIndexType(IndexType.KEY);
+    cms.create(index);
+
+    ClusterManagementGetResult<Index, IndexInfo> indexResult = cms.get(index);
+    Index fetchedIndexConfig = indexResult.getConfigResult();
+    List<IndexInfo> runtimeResult = indexResult.getRuntimeResult();
+    assertSoftly(softly -> {
+      softly.assertThat(fetchedIndexConfig.getRegionName()).as("index create: 
region name")
+          .isEqualTo("region2");
+      softly.assertThat(fetchedIndexConfig.getName()).as("index create: index 
name")
+          .isEqualTo("index");
+      softly.assertThat(fetchedIndexConfig.getRegionPath()).as("index create: 
region path")
+          .isEqualTo("/region2");
+      softly.assertThat(fetchedIndexConfig.getExpression()).as("index create: 
expression")
+          .isEqualTo("key");
+      softly.assertThat(runtimeResult).extracting(IndexInfo::getMemberName)
+          .as("index create: runtime server")
+          .containsExactlyInAnyOrder("server-3");
+    });
+
+    ClusterManagementRealizationResult deleteIndexResult = cms.delete(index);
+    region.setGroup(null);
+    ClusterManagementRealizationResult deleteRegionResult = cms.delete(region);
+    assertSoftly(softly -> {
+      softly.assertThat(deleteIndexResult.isSuccessful()).isTrue();
+      softly.assertThatThrownBy(() -> cms.get(index)).as("delete index 
confirmation")
+          .hasMessageContaining("Index 'index' does not exist");
+      softly.assertThat(deleteRegionResult.isSuccessful()).isTrue();
+      softly.assertThatThrownBy(() -> cms.get(region)).as("delete region 
confirmation")
+          .hasMessageContaining("Region 'region2' does not exist");
+    });
+  }
+
+  @Test
+  public void createAndDeleteIndex_success_for_cluster() {
+    Region region = new Region();
+    region.setName("region2");
+    region.setType(RegionType.REPLICATE);
+    cms.create(region);
+    locator.waitUntilRegionIsReadyOnExactlyThisManyServers("/region2", 3);
+
+    Index index = new Index();
+    index.setName("index.1");
+    index.setExpression("key");
+    index.setRegionPath("/region2");
+    index.setIndexType(IndexType.KEY);
+    cms.create(index);
+
+    ClusterManagementGetResult<Index, IndexInfo> indexResult = cms.get(index);
+    Index fetchedIndexConfig = indexResult.getConfigResult();
+    List<IndexInfo> runtimeResult = indexResult.getRuntimeResult();
+    assertSoftly(softly -> {
+      softly.assertThat(fetchedIndexConfig.getRegionName()).as("index create: 
region name")
+          .isEqualTo("region2");
+      softly.assertThat(fetchedIndexConfig.getName()).as("index create: index 
name")
+          .isEqualTo("index.1");
+      softly.assertThat(fetchedIndexConfig.getRegionPath()).as("index create: 
index path")
+          .isEqualTo("/region2");
+      softly.assertThat(fetchedIndexConfig.getExpression()).as("index create: 
index expression")
+          .isEqualTo("key");
+      softly.assertThat(runtimeResult).as("index create: runtime servers")
+          .extracting(IndexInfo::getMemberName)
+          .containsExactlyInAnyOrder("server-1", "server-2", "server-3");
+    });
+
+    ClusterManagementRealizationResult deleteIndexResult = cms.delete(index);
+    ClusterManagementRealizationResult deleteRegionResult = cms.delete(region);
+    assertSoftly(softly -> {
+      softly.assertThat(deleteIndexResult.isSuccessful()).isTrue();
+      softly.assertThatThrownBy(() -> cms.get(index)).as("index delete 
confirmation")
+          .hasMessageContaining("Index 'index.1' does not exist");
+      softly.assertThat(deleteRegionResult.isSuccessful()).isTrue();
+      softly.assertThatThrownBy(() -> cms.get(region)).as("region delete 
confirmation")
+          .hasMessageContaining("Region 'region2' does not exist");
     });
   }
 }
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
index 5cce9e1..9c2a468 100644
--- 
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
@@ -36,13 +36,13 @@ public class IndexConfigManager extends 
CacheConfigurationManager<Index> {
 
   @Override
   public void add(Index config, CacheConfig existing) {
-    RegionConfig regionConfiguration = 
existing.findRegionConfiguration(config.getRegionName());
-    if (regionConfiguration == null) {
+    RegionConfig regionConfig = 
existing.findRegionConfiguration(config.getRegionName());
+    if (regionConfig == null) {
       throw new IllegalArgumentException(
           "Region provided does not exist: " + config.getRegionName());
     }
     RegionConfig.Index index = converter.fromConfigObject(config);
-    regionConfiguration.getIndexes().add(index);
+    regionConfig.getIndexes().add(index);
   }
 
   @Override
@@ -52,7 +52,20 @@ public class IndexConfigManager extends 
CacheConfigurationManager<Index> {
 
   @Override
   public void delete(Index config, CacheConfig existing) {
-    throw new NotImplementedException("Not implemented yet");
+    RegionConfig regionConfig = 
existing.findRegionConfiguration(config.getRegionName());
+    if (regionConfig == null) {
+      throw new IllegalArgumentException(
+          "Region provided does not exist: " + config.getRegionName());
+    }
+    RegionConfig.Index index = regionConfig.getIndexes().stream()
+        .filter(item -> item.getName().equals(config.getName()))
+        .findFirst()
+        .orElseThrow(() -> new IllegalArgumentException("Index provided does 
not exist on Region: "
+            + config.getRegionName()
+            + ", "
+            + config.getName()));
+
+    regionConfig.getIndexes().remove(index);
   }
 
   @Override
diff --git 
a/geode-core/src/main/java/org/apache/geode/management/internal/configuration/realizers/IndexRealizer.java
 
b/geode-core/src/main/java/org/apache/geode/management/internal/configuration/realizers/IndexRealizer.java
index 38dd39c..70741b7 100644
--- 
a/geode-core/src/main/java/org/apache/geode/management/internal/configuration/realizers/IndexRealizer.java
+++ 
b/geode-core/src/main/java/org/apache/geode/management/internal/configuration/realizers/IndexRealizer.java
@@ -20,7 +20,10 @@ import org.apache.logging.log4j.Logger;
 
 import org.apache.geode.annotations.Immutable;
 import org.apache.geode.cache.Region;
+import org.apache.geode.cache.query.IndexExistsException;
+import org.apache.geode.cache.query.IndexNameConflictException;
 import org.apache.geode.cache.query.QueryService;
+import org.apache.geode.cache.query.RegionNotFoundException;
 import org.apache.geode.internal.cache.InternalCache;
 import org.apache.geode.logging.internal.log4j.api.LogService;
 import org.apache.geode.management.api.RealizationResult;
@@ -48,10 +51,13 @@ public class IndexRealizer implements 
ConfigurationRealizer<Index, IndexInfo> {
       realizationResult.setSuccess(true);
       realizationResult.setMessage("Index " + indexName + " successfully 
created");
       return realizationResult;
-    } catch (Exception e) {
-      logger.error(e.getMessage(), e);
+    } catch (IndexNameConflictException | IndexExistsException | 
RegionNotFoundException e) {
       realizationResult.setSuccess(false);
       realizationResult.setMessage(e.getMessage());
+    } catch (RuntimeException r) {
+      logger.error(r.getMessage(), r);
+      realizationResult.setSuccess(false);
+      realizationResult.setMessage(r.getMessage());
     }
 
     return realizationResult;
@@ -84,6 +90,37 @@ public class IndexRealizer implements 
ConfigurationRealizer<Index, IndexInfo> {
 
   @Override
   public RealizationResult delete(Index config, InternalCache cache) {
-    return null;
+    QueryService queryService = cache.getQueryService();
+    RealizationResult realizationResult = new RealizationResult();
+    Region<Object, Object> region = cache.getRegion("/" + 
config.getRegionName());
+    if (region == null) {
+      realizationResult.setSuccess(false);
+      realizationResult.setMessage("Region for index not found: " + 
config.getRegionName());
+      return realizationResult;
+    }
+    org.apache.geode.cache.query.Index index = queryService.getIndex(region, 
config.getName());
+    if (index == null) {
+      realizationResult.setSuccess(false);
+      realizationResult.setMessage("Index not found for Region: "
+          + config.getRegionName()
+          + ", "
+          + config.getName());
+      return realizationResult;
+    }
+    try {
+      queryService.removeIndex(index);
+      realizationResult.setSuccess(true);
+      realizationResult.setMessage("Index "
+          + config.getName()
+          + " successfully removed from "
+          + config.getRegionName());
+      return realizationResult;
+    } catch (RuntimeException e) {
+      logger.error(e.getMessage(), e);
+      realizationResult.setSuccess(false);
+      realizationResult.setMessage(e.getMessage());
+    }
+
+    return realizationResult;
   }
 }
diff --git 
a/geode-core/src/main/java/org/apache/geode/management/internal/configuration/validators/IndexValidator.java
 
b/geode-core/src/main/java/org/apache/geode/management/internal/configuration/validators/IndexValidator.java
index 22f06ea..c4131d4 100644
--- 
a/geode-core/src/main/java/org/apache/geode/management/internal/configuration/validators/IndexValidator.java
+++ 
b/geode-core/src/main/java/org/apache/geode/management/internal/configuration/validators/IndexValidator.java
@@ -34,29 +34,40 @@ public class IndexValidator implements 
ConfigurationValidator<Index> {
   @Override
   public void validate(CacheElementOperation operation, Index config)
       throws IllegalArgumentException {
-    if (operation == CacheElementOperation.CREATE) {
-      if (config.getName() == null) {
-        throw new IllegalArgumentException("Name is required.");
-      }
-
-      if (config.getExpression() == null) {
-        throw new IllegalArgumentException("Expression is required.");
-      }
-
-      if (config.getRegionPath() == null) {
-        throw new IllegalArgumentException("RegionPath is required.");
-      }
-
-      if (config.getIndexType() == IndexType.HASH_DEPRECATED) {
-        throw new IllegalArgumentException("IndexType HASH is not allowed.");
-      }
-
-      CacheConfig existing = 
persistenceService.getCacheConfig(config.getGroup(), true);
-      RegionConfig regionConfiguration = 
existing.findRegionConfiguration(config.getRegionName());
-      if (regionConfiguration == null) {
-        throw new 
ClusterManagementException(ClusterManagementResult.StatusCode.ENTITY_NOT_FOUND,
-            "Region provided does not exist: " + config.getRegionName() + ".");
-      }
+    switch (operation) {
+      case CREATE:
+        if (config.getName() == null) {
+          throw new IllegalArgumentException("Name is required.");
+        }
+
+        if (config.getExpression() == null) {
+          throw new IllegalArgumentException("Expression is required.");
+        }
+
+        if (config.getRegionPath() == null) {
+          throw new IllegalArgumentException("RegionPath is required.");
+        }
+
+        if (config.getIndexType() == IndexType.HASH_DEPRECATED) {
+          throw new IllegalArgumentException("IndexType HASH is not allowed.");
+        }
+        break;
+      case DELETE:
+        if (config.getName() == null) {
+          throw new IllegalArgumentException("Name is required.");
+        }
+
+        if (config.getRegionPath() == null) {
+          throw new IllegalArgumentException("RegionPath is required.");
+        }
+        break;
+    }
+
+    CacheConfig existing = 
persistenceService.getCacheConfig(config.getGroup(), true);
+    RegionConfig regionConfiguration = 
existing.findRegionConfiguration(config.getRegionName());
+    if (regionConfiguration == null) {
+      throw new 
ClusterManagementException(ClusterManagementResult.StatusCode.ENTITY_NOT_FOUND,
+          "Region provided does not exist: " + config.getRegionName() + ".");
     }
   }
 }
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
index 6a676c9..c61cf8e 100644
--- 
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
@@ -16,15 +16,19 @@
 package org.apache.geode.management.internal.configuration.mutators;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.assertj.core.api.SoftAssertions.assertSoftly;
 
 import java.util.List;
 
+import org.apache.commons.lang3.NotImplementedException;
 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;
+import org.apache.geode.management.configuration.IndexType;
 
 public class IndexConfigManagerTest {
 
@@ -40,43 +44,49 @@ public class IndexConfigManagerTest {
   }
 
   @Test
-  public void emptyConfig() throws Exception {
+  public void emptyConfig() {
     assertThat(manager.list(index, cacheConfig)).isEmpty();
   }
 
   @Test
-  public void listWithoutFilter() throws Exception {
+  public void listWithoutFilter() {
     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");
+    assertSoftly(softly -> {
+      softly.assertThat(list).hasSize(2)
+          .extracting(Index::getName)
+          .containsExactlyInAnyOrder("index1", "index2");
+      softly.assertThat(list).extracting(Index::getRegionName)
+          .containsExactlyInAnyOrder("region1", "region2");
+    });
   }
 
   @Test
-  public void listWithRegionName() throws Exception {
+  public void listWithRegionName() {
     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");
+    assertSoftly(softly -> {
+      softly.assertThat(list).hasSize(1);
+      softly.assertThat(list.get(0).getName()).isEqualTo("index1");
+      softly.assertThat(list.get(0).getRegionName()).isEqualTo("region1");
+    });
   }
 
   @Test
-  public void listWithIndexName() throws Exception {
+  public void listWithIndexName() {
     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");
+    assertSoftly(softly -> {
+      softly.assertThat(list).hasSize(1);
+      softly.assertThat(list.get(0).getName()).isEqualTo("index2");
+      softly.assertThat(list.get(0).getRegionName()).isEqualTo("region2");
+    });
   }
 
   @Test
-  public void listWithUnMatchingFilter() throws Exception {
+  public void listWithUnMatchingFilter() {
     setupCacheConfig();
     index.setName("index1");
     index.setRegionPath("region2");
@@ -85,14 +95,96 @@ public class IndexConfigManagerTest {
   }
 
   @Test
-  public void listWithRegionNameAndIndexName() throws Exception {
+  public void listWithRegionNameAndIndexName() {
     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");
+    assertSoftly(softly -> {
+      softly.assertThat(list).hasSize(1);
+      softly.assertThat(list.get(0).getName()).isEqualTo("index2");
+      softly.assertThat(list.get(0).getRegionName()).isEqualTo("region2");
+    });
+
+  }
+
+  @Test
+  public void add_regionExists() {
+    setupCacheConfig();
+    index.setName("index3");
+    index.setIndexType(IndexType.RANGE);
+    index.setRegionPath("region1");
+
+    manager.add(index, cacheConfig);
+    List<Index> indices = manager.list(index, cacheConfig);
+
+    assertSoftly(softly -> {
+      softly.assertThat(indices).hasSize(1);
+      softly.assertThat(indices.get(0).getName()).isEqualTo("index3");
+      softly.assertThat(indices.get(0).getRegionName()).isEqualTo("region1");
+    });
+  }
+
+  @Test
+  public void add_regionNotFound() {
+    setupCacheConfig();
+    index.setName("index3");
+    index.setIndexType(IndexType.RANGE);
+    index.setRegionPath("region3");
+
+    assertThatThrownBy(() -> manager.add(index, cacheConfig))
+        .isInstanceOf(IllegalArgumentException.class)
+        .hasMessageContaining("Region provided does not exist: region3");
+  }
+
+  @Test
+  public void update_notImplemented() {
+    setupCacheConfig();
+    index.setName("index3");
+    index.setIndexType(IndexType.RANGE);
+    index.setRegionPath("region3");
+
+    assertThatThrownBy(() -> manager.update(index, cacheConfig))
+        .isInstanceOf(NotImplementedException.class)
+        .hasMessageContaining("Not implemented yet");
+  }
+
+  @Test
+  public void delete_regionNotFound() {
+    setupCacheConfig();
+    index.setName("index3");
+    index.setIndexType(IndexType.RANGE);
+    index.setRegionPath("region3");
+
+    assertThatThrownBy(() -> manager.delete(index, cacheConfig))
+        .isInstanceOf(IllegalArgumentException.class)
+        .hasMessageContaining("Region provided does not exist: region3");
+  }
+
+  @Test
+  public void delete_indexNotFound() {
+    setupCacheConfig();
+    index.setName("index3");
+    index.setIndexType(IndexType.RANGE);
+    index.setRegionPath("region2");
+
+    assertThatThrownBy(() -> manager.delete(index, cacheConfig))
+        .isInstanceOf(IllegalArgumentException.class)
+        .hasMessageContaining("Index provided does not exist on Region: 
region2, index3");
+  }
+
+  @Test
+  public void delete_indexDeleted() {
+    setupCacheConfig();
+    index.setName("index2");
+    index.setIndexType(IndexType.RANGE);
+    index.setRegionPath("region2");
+
+    assertSoftly(softly -> {
+      softly.assertThat(manager.list(index, cacheConfig)).hasSize(1);
+      manager.delete(index, cacheConfig);
+      softly.assertThat(manager.list(index, cacheConfig)).hasSize(0);
+    });
   }
 
   private void setupCacheConfig() {
diff --git 
a/geode-core/src/test/java/org/apache/geode/management/internal/configuration/realizers/IndexRealizerTest.java
 
b/geode-core/src/test/java/org/apache/geode/management/internal/configuration/realizers/IndexRealizerTest.java
index 4cb81fb..0959c41 100644
--- 
a/geode-core/src/test/java/org/apache/geode/management/internal/configuration/realizers/IndexRealizerTest.java
+++ 
b/geode-core/src/test/java/org/apache/geode/management/internal/configuration/realizers/IndexRealizerTest.java
@@ -24,6 +24,7 @@ import static org.mockito.Mockito.when;
 import org.junit.Before;
 import org.junit.Test;
 
+import org.apache.geode.cache.Region;
 import org.apache.geode.cache.query.internal.InternalQueryService;
 import org.apache.geode.internal.cache.InternalCache;
 import org.apache.geode.management.api.RealizationResult;
@@ -82,4 +83,60 @@ public class IndexRealizerTest {
     });
   }
 
+  @Test
+  public void delete_succeeds() {
+    Region<Object, Object> region = mock(Region.class);
+    org.apache.geode.cache.query.Index removeIndex = 
mock(org.apache.geode.cache.query.Index.class);
+    when(queryService.getIndex(region, "testIndex")).thenReturn(removeIndex);
+    when(cache.getRegion("/testRegion")).thenReturn(region);
+    RealizationResult realizationResult = indexRealizer.delete(index, cache);
+    assertSoftly(softly -> {
+      softly.assertThat(realizationResult.isSuccess()).isTrue();
+      softly.assertThat(realizationResult.getMessage())
+          .isEqualTo("Index testIndex successfully removed from testRegion");
+    });
+  }
+
+  @Test
+  public void delete_fails_removal() {
+    Region<Object, Object> region = mock(Region.class);
+    org.apache.geode.cache.query.Index removeIndex = 
mock(org.apache.geode.cache.query.Index.class);
+    when(queryService.getIndex(region, "testIndex")).thenReturn(removeIndex);
+    when(cache.getRegion("/testRegion")).thenReturn(region);
+    doThrow(new RuntimeException("removal 
failed")).when(queryService).removeIndex(removeIndex);
+    RealizationResult realizationResult = indexRealizer.delete(index, cache);
+    assertSoftly(softly -> {
+      softly.assertThat(realizationResult.isSuccess()).isFalse();
+      softly.assertThat(realizationResult.getMessage()).isEqualTo("removal 
failed");
+    });
+  }
+
+  @Test
+  public void delete_fails_to_find_region() {
+    Region<Object, Object> region = mock(Region.class);
+    org.apache.geode.cache.query.Index removeIndex = 
mock(org.apache.geode.cache.query.Index.class);
+    when(queryService.getIndex(region, "testIndex")).thenReturn(removeIndex);
+    when(cache.getRegion("/testRegion")).thenReturn(null);
+    RealizationResult realizationResult = indexRealizer.delete(index, cache);
+    assertSoftly(softly -> {
+      softly.assertThat(realizationResult.isSuccess()).isFalse();
+      softly.assertThat(realizationResult.getMessage())
+          .isEqualTo("Region for index not found: testRegion");
+    });
+  }
+
+  @Test
+  public void delete_fails_to_find_index() {
+    Region<Object, Object> region = mock(Region.class);
+    org.apache.geode.cache.query.Index removeIndex = 
mock(org.apache.geode.cache.query.Index.class);
+    when(queryService.getIndex(region, "testIndex")).thenReturn(null);
+    when(cache.getRegion("/testRegion")).thenReturn(region);
+    RealizationResult realizationResult = indexRealizer.delete(index, cache);
+    assertSoftly(softly -> {
+      softly.assertThat(realizationResult.isSuccess()).isFalse();
+      softly.assertThat(realizationResult.getMessage())
+          .isEqualTo("Index not found for Region: testRegion, testIndex");
+    });
+  }
+
 }
diff --git 
a/geode-core/src/test/java/org/apache/geode/management/internal/configuration/validators/IndexValidatorTest.java
 
b/geode-core/src/test/java/org/apache/geode/management/internal/configuration/validators/IndexValidatorTest.java
index 6f2caf1..722495a 100644
--- 
a/geode-core/src/test/java/org/apache/geode/management/internal/configuration/validators/IndexValidatorTest.java
+++ 
b/geode-core/src/test/java/org/apache/geode/management/internal/configuration/validators/IndexValidatorTest.java
@@ -16,6 +16,7 @@
 package org.apache.geode.management.internal.configuration.validators;
 
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.assertj.core.api.SoftAssertions.assertSoftly;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyString;
@@ -84,9 +85,15 @@ public class IndexValidatorTest {
   public void validate_hasRegionPath() {
     index.setRegionPath(null);
 
-    assertThatThrownBy(() -> 
indexValidator.validate(CacheElementOperation.CREATE, index))
-        .isInstanceOf(IllegalArgumentException.class)
-        .hasMessageContaining("RegionPath is required");
+    assertSoftly(softly -> {
+      softly.assertThatThrownBy(() -> 
indexValidator.validate(CacheElementOperation.CREATE, index))
+          .isInstanceOf(IllegalArgumentException.class)
+          .hasMessageContaining("RegionPath is required");
+      softly.assertThatThrownBy(() -> 
indexValidator.validate(CacheElementOperation.DELETE, index))
+          .isInstanceOf(IllegalArgumentException.class)
+          .hasMessageContaining("RegionPath is required");
+    });
+
   }
 
   @Test
@@ -102,7 +109,12 @@ public class IndexValidatorTest {
   public void validate_IndexHasName() {
     index.setName(null);
 
-    assertThatThrownBy(() -> 
indexValidator.validate(CacheElementOperation.CREATE, index))
-        
.isInstanceOf(IllegalArgumentException.class).hasMessageContaining("Name is 
required");
+    assertSoftly(softly -> {
+      softly.assertThatThrownBy(() -> 
indexValidator.validate(CacheElementOperation.CREATE, index))
+          
.isInstanceOf(IllegalArgumentException.class).hasMessageContaining("Name is 
required");
+      softly.assertThatThrownBy(() -> 
indexValidator.validate(CacheElementOperation.DELETE, index))
+          
.isInstanceOf(IllegalArgumentException.class).hasMessageContaining("Name is 
required");
+    });
+
   }
 }
diff --git 
a/geode-management/src/main/java/org/apache/geode/management/api/ClusterManagementRealizationResult.java
 
b/geode-management/src/main/java/org/apache/geode/management/api/ClusterManagementRealizationResult.java
index 308806f..0c4729e 100644
--- 
a/geode-management/src/main/java/org/apache/geode/management/api/ClusterManagementRealizationResult.java
+++ 
b/geode-management/src/main/java/org/apache/geode/management/api/ClusterManagementRealizationResult.java
@@ -18,6 +18,7 @@ import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.geode.annotations.Experimental;
+import org.apache.geode.management.configuration.AbstractConfiguration;
 
 @Experimental
 public class ClusterManagementRealizationResult extends 
ClusterManagementResult {
diff --git 
a/geode-web-management/src/integrationTest/java/org/apache/geode/management/internal/rest/ClusterManagementSecurityRestIntegrationTest.java
 
b/geode-web-management/src/integrationTest/java/org/apache/geode/management/internal/rest/ClusterManagementSecurityRestIntegrationTest.java
index cd8f7c0..29e5892 100644
--- 
a/geode-web-management/src/integrationTest/java/org/apache/geode/management/internal/rest/ClusterManagementSecurityRestIntegrationTest.java
+++ 
b/geode-web-management/src/integrationTest/java/org/apache/geode/management/internal/rest/ClusterManagementSecurityRestIntegrationTest.java
@@ -43,6 +43,7 @@ import org.springframework.web.context.WebApplicationContext;
 import org.apache.geode.cache.configuration.GatewayReceiverConfig;
 import org.apache.geode.cache.configuration.PdxType;
 import org.apache.geode.cache.configuration.RegionConfig;
+import org.apache.geode.management.configuration.Index;
 import org.apache.geode.management.configuration.RegionType;
 import org.apache.geode.management.operation.RebalanceOperation;
 import org.apache.geode.util.internal.GeodeJsonMapper;
@@ -89,6 +90,12 @@ public class ClusterManagementSecurityRestIntegrationTest {
     testContexts
         .add(new TestContext(get("/v1/regions/regionA/indexes/index1"),
             "CLUSTER:READ:QUERY"));
+    testContexts
+        .add(new TestContext(post("/v1/regions/regionA/indexes/"),
+            "CLUSTER:MANAGE:QUERY").setContent(mapper.writeValueAsString(new 
Index())));
+    testContexts
+        .add(new TestContext(delete("/v1/regions/regionA/indexes/index1"),
+            "CLUSTER:MANAGE:QUERY"));
 
     testContexts.add(new TestContext(get("/v1/gateways/receivers"), 
"CLUSTER:READ"));
     testContexts
diff --git 
a/geode-web-management/src/integrationTest/java/org/apache/geode/management/internal/rest/RegionManagementControllerSpringTest.java
 
b/geode-web-management/src/integrationTest/java/org/apache/geode/management/internal/rest/RegionManagementControllerSpringTest.java
index 71ed12d..8b412a6 100644
--- 
a/geode-web-management/src/integrationTest/java/org/apache/geode/management/internal/rest/RegionManagementControllerSpringTest.java
+++ 
b/geode-web-management/src/integrationTest/java/org/apache/geode/management/internal/rest/RegionManagementControllerSpringTest.java
@@ -125,4 +125,24 @@ public class RegionManagementControllerSpringTest {
     assertThat(regionPassedToGet.getName())
         .isEqualTo(regionNameWithDot);
   }
+
+  @Test
+  public void deleteRegionMappingRecognizesIndexNameWithDot() throws Exception 
{
+    String regionName = "regionName";
+    String indexNameWithDot = "index.name";
+    String requestPath =
+        URI_VERSION + REGION_CONFIG_ENDPOINT + "/" + regionName + INDEXES + 
"/" + indexNameWithDot;
+
+    when(cms.delete(any())).thenReturn(new 
ClusterManagementRealizationResult());
+
+    context.perform(delete(requestPath))
+        .andExpect(status().is2xxSuccessful());
+
+    ArgumentCaptor<Index> indexCaptor = ArgumentCaptor.forClass(Index.class);
+    verify(cms).delete(indexCaptor.capture());
+    Index indexPassedToGet = indexCaptor.getValue();
+
+    assertThat(indexPassedToGet.getName())
+        .isEqualTo(indexNameWithDot);
+  }
 }
diff --git 
a/geode-web-management/src/integrationTest/java/org/apache/geode/management/internal/rest/RegionManagementIntegrationTest.java
 
b/geode-web-management/src/integrationTest/java/org/apache/geode/management/internal/rest/RegionManagementIntegrationTest.java
index 7f98c85..2e2cfd2 100644
--- 
a/geode-web-management/src/integrationTest/java/org/apache/geode/management/internal/rest/RegionManagementIntegrationTest.java
+++ 
b/geode-web-management/src/integrationTest/java/org/apache/geode/management/internal/rest/RegionManagementIntegrationTest.java
@@ -17,6 +17,7 @@ package org.apache.geode.management.internal.rest;
 
 import static 
org.apache.geode.test.junit.assertions.ClusterManagementRealizationResultAssert.assertManagementResult;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static 
org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
 import static 
org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
 import static 
org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
 import static 
org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
@@ -42,6 +43,7 @@ import 
org.apache.geode.management.api.ClusterManagementResult;
 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.configuration.IndexType;
 import org.apache.geode.management.configuration.Region;
 import org.apache.geode.management.configuration.Region.Expiration;
 import org.apache.geode.management.configuration.Region.ExpirationAction;
@@ -116,8 +118,8 @@ public class RegionManagementIntegrationTest {
 
   @Test
   public void createIndexOnNonExistentRegion() throws Exception {
-    index.setName("index");
-    index.setRegionPath("/regionA");
+    index.setName("index1");
+    index.setRegionPath("regionA");
     index.setExpression("id");
     String postUrl = index.getLinks().getList();
     context.perform(post("/v1" + 
postUrl).content(mapper.writeValueAsString(index)))
@@ -129,43 +131,36 @@ public class RegionManagementIntegrationTest {
 
   @Test
   public void createDuplicateIndex() throws Exception {
-    region.setName("customers");
-    region.setType(RegionType.PARTITION);
-    client.create(region);
-    index.setName("index");
-    index.setRegionPath("/customers");
-    index.setExpression("id");
-    client.create(index);
+    createClusterRegion();
 
-    // trying to create a duplicate index
-    index.setName("index");
-    index.setRegionPath("/customers");
-    index.setExpression("key");
+    createClusterIndex();
+
+    // trying to create a duplicate index, reusing existing
     String postUrl = index.getLinks().getList();
     context.perform(post("/v1" + 
postUrl).content(mapper.writeValueAsString(index)))
         .andExpect(status().isConflict())
         .andExpect(jsonPath("$.statusCode", Matchers.is("ENTITY_EXISTS")))
         .andExpect(jsonPath("$.statusMessage",
-            Matchers.containsString("Index 'index' already exists in group 
cluster.")));
+            Matchers.containsString("Index 'index1' already exists in group 
cluster.")));
 
     // trying to create another index in this region in another group
     index.setName("index2");
-    index.setRegionPath("/customers");
+    index.setRegionPath("region1");
     index.setExpression("key");
     index.setGroup("notExist");
-    
context.perform(post("/v1/regions/customers/indexes").content(mapper.writeValueAsString(index)))
+    
context.perform(post("/v1/regions/region1/indexes").content(mapper.writeValueAsString(index)))
         .andExpect(status().isNotFound())
         .andExpect(jsonPath("$.statusCode", Matchers.is("ENTITY_NOT_FOUND")))
         .andExpect(jsonPath("$.statusMessage",
             Matchers
-                .containsString("Region provided does not exist: 
customers.")));
+                .containsString("Region provided does not exist: region1.")));
 
     assertManagementResult(client.delete(region))
         .hasStatusCode(ClusterManagementResult.StatusCode.OK);
   }
 
   @Test
-  public void postToRegionEndPoint() throws Exception {
+  public void postToIndexRegionEndPoint() throws Exception {
     index.setName("index");
     index.setRegionPath("/customers");
     index.setExpression("id");
@@ -187,6 +182,8 @@ public class RegionManagementIntegrationTest {
 
   @Test
   public void createIndex_failsOnNonExistentRegionGroup() throws Exception {
+    createClusterRegion();
+
     index.setRegionPath("region1");
     index.setExpression("i am le tired");
     index.setName("wontwork");
@@ -198,32 +195,178 @@ public class RegionManagementIntegrationTest {
         .andExpect(jsonPath("$.statusMessage",
             Matchers
                 .containsString("Region provided does not exist: region1.")));
+
+    deleteRegion();
   }
 
-  @Test
-  public void createIndex_succeedsForSpecificRegionAndGroup() throws Exception 
{
-    region.setName("regionGroup");
+  private void createClusterRegion() {
+    region.setName("region1");
     region.setType(RegionType.PARTITION);
-    region.setGroup("legroup");
-
     assertManagementResult(client.create(region))
         .hasStatusCode(ClusterManagementResult.StatusCode.OK);
+  }
+
+  @Test
+  public void createIndex_failsOnNonExistentClusterRegion() throws Exception {
+    createGroupRegion();
 
-    index.setRegionPath("regionGroup");
+    index.setRegionPath("region1");
+    index.setExpression("i am le tired");
+    index.setName("wontwork");
+
+    
context.perform(post("/v1/regions/region1/indexes").content(mapper.writeValueAsString(index)))
+        .andExpect(status().isNotFound())
+        .andExpect(jsonPath("$.statusCode", Matchers.is("ENTITY_NOT_FOUND")))
+        .andExpect(jsonPath("$.statusMessage",
+            Matchers
+                .containsString("Region provided does not exist: region1.")));
+
+    deleteRegion();
+  }
+
+  @Test
+  public void createIndex_succeedsForSpecificRegionAndGroup() throws Exception 
{
+    createGroupRegion();
+
+    index.setRegionPath("region1");
     index.setExpression("i am le tired");
     index.setName("itworks");
-    index.setGroup("legroup");
+    index.setGroup("group1");
 
     context.perform(
-        
post("/v1/regions/regionGroup/indexes").content(mapper.writeValueAsString(index)))
+        
post("/v1/regions/region1/indexes").content(mapper.writeValueAsString(index)))
         .andExpect(status().isCreated())
         .andExpect(jsonPath("$.statusCode", Matchers.is("OK")))
         .andExpect(jsonPath("$.statusMessage",
             Matchers
-                .containsString("Successfully updated configuration for 
legroup.")));
+                .containsString("Successfully updated configuration for 
group1.")));
+
+    deleteRegion();
+  }
+
+  @Test
+  public void deleteIndex_succeeds() throws Exception {
+    createClusterRegion();
+
+    createClusterIndex();
+
+    context.perform(delete("/v1/regions/region1/indexes/index1"))
+        .andExpect(status().isOk())
+        .andExpect(jsonPath("$.statusCode", Matchers.is("OK")))
+        .andExpect(jsonPath("$.statusMessage",
+            Matchers
+                .containsString("Successfully removed configuration for 
[cluster].")));
+
+    deleteRegion();
+  }
+
+  @Test
+  public void deleteIndex_succeeds_with_group() throws Exception {
+    createGroupRegion();
+
+    createGroupIndex();
+
+    
context.perform(delete("/v1/regions/region1/indexes/index1").param("group", 
"group1"))
+        .andExpect(status().isOk())
+        .andExpect(jsonPath("$.statusCode", Matchers.is("OK")))
+        .andExpect(jsonPath("$.statusMessage",
+            Matchers
+                .containsString("Successfully removed configuration for 
[group1].")));
+
+    deleteRegion();
+  }
+
+
+  @Test
+  public void deleteIndex_fails_region_not_found_with_group() throws Exception 
{
+    createClusterRegion();
+
+    createClusterIndex();
+
+    
context.perform(delete("/v1/regions/region1/indexes/index1").param("group", 
"group1"))
+        .andExpect(status().isNotFound())
+        .andExpect(jsonPath("$.statusCode", Matchers.is("ENTITY_NOT_FOUND")))
+        .andExpect(jsonPath("$.statusMessage",
+            Matchers
+                .containsString("Region provided does not exist: region1.")));
+
+    deleteRegion();
+  }
 
+  @Test
+  public void deleteIndex_fails_region_not_found() throws Exception {
+    createGroupRegion();
+
+    createGroupIndex();
+
+    context.perform(delete("/v1/regions/region1/indexes/index1"))
+        .andExpect(status().isNotFound())
+        .andExpect(jsonPath("$.statusCode", Matchers.is("ENTITY_NOT_FOUND")))
+        .andExpect(jsonPath("$.statusMessage",
+            Matchers
+                .containsString("Region provided does not exist: region1.")));
+
+    deleteRegion();
+  }
+
+  @Test
+  public void deleteIndex_fails_index_not_found() throws Exception {
+    createClusterRegion();
+
+    context.perform(delete("/v1/regions/region1/indexes/index1"))
+        .andExpect(status().isNotFound())
+        .andExpect(jsonPath("$.statusCode", Matchers.is("ENTITY_NOT_FOUND")))
+        .andExpect(jsonPath("$.statusMessage",
+            Matchers
+                .containsString("Index 'index1' does not exist.")));
+
+    deleteRegion();
+  }
+
+  @Test
+  public void deleteIndex_fails_index_not_found_with_group() throws Exception {
+    createGroupRegion();
+
+    
context.perform(delete("/v1/regions/region1/indexes/index1").param("group", 
"group1"))
+        .andExpect(status().isNotFound())
+        .andExpect(jsonPath("$.statusCode", Matchers.is("ENTITY_NOT_FOUND")))
+        .andExpect(jsonPath("$.statusMessage",
+            Matchers
+                .containsString("Index 'index1' does not exist.")));
+
+    deleteRegion();
+  }
+
+  private void createGroupRegion() {
+    region.setName("region1");
+    region.setType(RegionType.PARTITION);
+    region.setGroup("group1");
+    assertManagementResult(client.create(region))
+        .hasStatusCode(ClusterManagementResult.StatusCode.OK);
+  }
+
+  private void deleteRegion() {
     region.setGroup(null);
     assertManagementResult(client.delete(region))
         .hasStatusCode(ClusterManagementResult.StatusCode.OK);
   }
+
+  private void createGroupIndex() {
+    index.setRegionPath("region1");
+    index.setIndexType(IndexType.RANGE);
+    index.setName("index1");
+    index.setGroup("group1");
+    index.setExpression("some expression");
+    assertManagementResult(client.create(index))
+        .hasStatusCode(ClusterManagementResult.StatusCode.OK);
+  }
+
+  private void createClusterIndex() {
+    index.setRegionPath("region1");
+    index.setIndexType(IndexType.RANGE);
+    index.setName("index1");
+    index.setExpression("some expression");
+    assertManagementResult(client.create(index))
+        .hasStatusCode(ClusterManagementResult.StatusCode.OK);
+  }
 }
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 975f6a1..258161c 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
@@ -196,4 +196,20 @@ public class RegionManagementController extends 
AbstractManagementController {
     return new ResponseEntity<>(result,
         HttpStatus.CREATED);
   }
+
+  @ApiOperation(value = "delete region index")
+  @PreAuthorize("@securityService.authorize('CLUSTER', 'MANAGE', 'QUERY')")
+  @DeleteMapping(REGION_CONFIG_ENDPOINT + "/{regionName}" + INDEXES + 
"/{indexName:.+}")
+  public ClusterManagementResult deleteIndex(
+      @PathVariable String regionName,
+      @PathVariable String indexName,
+      @RequestParam(required = false) String group) {
+    Index config = new Index();
+    config.setName(indexName);
+    config.setRegionPath(regionName);
+    if (StringUtils.isNotBlank(group)) {
+      config.setGroup(group);
+    }
+    return clusterManagementService.delete(config);
+  }
 }

Reply via email to