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 6a177ec GEODE-6612: add entry count for list Region and rework filtering by groups (#3465) 6a177ec is described below commit 6a177ecfebc443affda84bea33f3c6cfa26f7c00 Author: jinmeiliao <jil...@pivotal.io> AuthorDate: Thu Apr 18 11:15:04 2019 -0700 GEODE-6612: add entry count for list Region and rework filtering by groups (#3465) Co-authored-by: Owen Nichols <onich...@pivotal.io> Co-authored-by: Jens Deppe jde...@pivotal.io * Create a RuntimeCacheElement interface to hold multiple groups * Using RegionConfig can only set/get one group --- .../rest/ListRegionManagementDunitTest.java | 140 +++++++++++++++++---- .../integrationTest/resources/assembly_content.txt | 2 + .../RegionConfigMutatorIntegrationTest.java | 2 +- .../api/LocatorClusterManagementService.java | 77 ++++++++---- .../mutators/ConfigurationManager.java | 3 +- .../mutators/RegionConfigManager.java | 39 +++++- .../validators/CacheElementValidator.java | 37 ++++++ .../validators/RegionConfigValidator.java | 5 - .../api/LocatorClusterManagementServiceTest.java | 111 +++++++++++----- .../validators/CacheElementValidatorTest.java} | 32 ++--- .../validators/RegionConfigValidatorTest.java | 9 -- .../assertions/ClusterManagementResultAssert.java | 4 +- .../geode/cache/configuration/CacheElement.java | 40 ++++-- .../geode/cache/configuration/RegionConfig.java | 24 ++++ .../management/api/ClusterManagementResult.java | 8 +- .../management/configuration/MemberConfig.java | 6 +- .../configuration/RuntimeCacheElement.java | 36 ++++++ .../configuration/RuntimeRegionConfig.java | 45 +++++++ .../configuration/CacheElementJsonMappingTest.java | 54 +++++++- .../cache/configuration/CacheElementTest.java | 102 +++++++++++++++ .../ClientClusterManagementServiceDUnitTest.java | 15 +-- .../rest/RegionManagementIntegrationTest.java | 13 ++ 22 files changed, 656 insertions(+), 148 deletions(-) diff --git a/geode-assembly/src/distributedTest/java/org/apache/geode/management/internal/rest/ListRegionManagementDunitTest.java b/geode-assembly/src/distributedTest/java/org/apache/geode/management/internal/rest/ListRegionManagementDunitTest.java index 6dd1135..b0bca71 100644 --- a/geode-assembly/src/distributedTest/java/org/apache/geode/management/internal/rest/ListRegionManagementDunitTest.java +++ b/geode-assembly/src/distributedTest/java/org/apache/geode/management/internal/rest/ListRegionManagementDunitTest.java @@ -15,6 +15,7 @@ package org.apache.geode.management.internal.rest; +import static org.apache.geode.test.awaitility.GeodeAwaitility.await; import static org.assertj.core.api.Assertions.assertThat; import java.util.List; @@ -25,10 +26,14 @@ import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; +import org.apache.geode.cache.Region; import org.apache.geode.cache.configuration.CacheElement; import org.apache.geode.cache.configuration.RegionConfig; +import org.apache.geode.cache.configuration.RegionType; import org.apache.geode.management.api.ClusterManagementService; import org.apache.geode.management.client.ClusterManagementServiceProvider; +import org.apache.geode.management.configuration.RuntimeCacheElement; +import org.apache.geode.management.configuration.RuntimeRegionConfig; import org.apache.geode.test.dunit.rules.ClusterStartupRule; import org.apache.geode.test.dunit.rules.MemberVM; import org.apache.geode.test.junit.rules.GfshCommandRule; @@ -61,15 +66,34 @@ public class ListRegionManagementDunitTest { regionConfig.setName("customers1"); regionConfig.setGroup("group1"); client.create(regionConfig); + locator.waitUntilRegionIsReadyOnExactlyThisManyServers("/customers1", 1); + + // create a region that has different type on different group + regionConfig = new RegionConfig(); + regionConfig.setName("customers2"); + regionConfig.setGroup("group1"); + regionConfig.setType(RegionType.PARTITION_PROXY); + client.create(regionConfig); regionConfig = new RegionConfig(); regionConfig.setName("customers2"); regionConfig.setGroup("group2"); client.create(regionConfig); + locator.waitUntilRegionIsReadyOnExactlyThisManyServers("/customers2", 2); regionConfig = new RegionConfig(); regionConfig.setName("customers"); client.create(regionConfig); + locator.waitUntilRegionIsReadyOnExactlyThisManyServers("/customers", 2); + + // create a region that belongs to multiple groups + regionConfig = new RegionConfig(); + regionConfig.setName("customers3"); + regionConfig.setGroup("group1"); + client.create(regionConfig); + regionConfig.setGroup("group2"); + client.create(regionConfig); + locator.waitUntilRegionIsReadyOnExactlyThisManyServers("/customers3", 2); } @Before @@ -80,69 +104,141 @@ public class ListRegionManagementDunitTest { @Test public void listAll() throws Exception { // list all - List<CacheElement> regions = client.list(filter).getResult(); - assertThat(regions.stream().map(CacheElement::getId).collect(Collectors.toList())) - .containsExactlyInAnyOrder("customers", "customers1", "customers2"); - assertThat(regions.stream().map(CacheElement::getConfigGroup).collect(Collectors.toList())) - .containsExactlyInAnyOrder("cluster", "group1", "group2"); + List<RuntimeCacheElement> regions = client.list(filter).getResult(); + assertThat(regions).hasSize(5); + RuntimeCacheElement element = CacheElement.findElement(regions, "customers"); + assertThat(element.getGroup()).isNull(); + + element = CacheElement.findElement(regions, "customers1"); + assertThat(element.getGroup()).isEqualTo("group1"); + + RegionConfig region = (RegionConfig) CacheElement.findElement(regions, "customers2"); + assertThat(region.getGroup()).isIn("group1", "group2"); + assertThat(region.getType()).isIn("PARTITION", "PARTITION_PROXY"); + + element = CacheElement.findElement(regions, "customers3"); + assertThat(element.getGroups()).containsExactlyInAnyOrder("group1", "group2"); } @Test public void listClusterLevel() throws Exception { // list cluster level only filter.setGroup("cluster"); - List<CacheElement> regions = client.list(filter).getResult(); + List<RuntimeCacheElement> regions = client.list(filter).getResult(); assertThat(regions).hasSize(1); assertThat(regions.get(0).getId()).isEqualTo("customers"); - assertThat(regions.get(0).getConfigGroup()).isEqualTo("cluster"); assertThat(regions.get(0).getGroup()).isNull(); } @Test + public void testEntryCount() throws Exception { + server1.invoke(() -> { + Region region = ClusterStartupRule.getCache().getRegion("/customers"); + region.put("k1", "v1"); + region.put("k2", "v2"); + }); + + // wait till entry size are correctly gathered by the mbean + locator.invoke(() -> { + await().untilAsserted( + () -> assertThat(ClusterStartupRule.memberStarter.getRegionMBean("/customers") + .getSystemRegionEntryCount()).isEqualTo(2)); + }); + + filter.setName("customers"); + List<RuntimeCacheElement> regions = client.list(filter).getResult(); + assertThat(regions).hasSize(1); + RuntimeRegionConfig regionConfig = (RuntimeRegionConfig) regions.get(0); + assertThat(regionConfig.getName()).isEqualTo("customers"); + assertThat(regionConfig).isInstanceOf(RuntimeRegionConfig.class); + assertThat(regionConfig.getEntryCount()).isEqualTo(2); + } + + @Test public void listGroup1() throws Exception { // list group1 filter.setGroup("group1"); - List<CacheElement> regions = client.list(filter).getResult(); - assertThat(regions).hasSize(1); - assertThat(regions.get(0).getId()).isEqualTo("customers1"); - assertThat(regions.get(0).getConfigGroup()).isEqualTo("group1"); - assertThat(regions.get(0).getGroup()).isEqualTo("group1"); + List<RuntimeCacheElement> regions = client.list(filter).getResult(); + assertThat(regions).hasSize(3); + // when filtering by group, the returned list should not have group info + RuntimeCacheElement region = + (RuntimeCacheElement) CacheElement.findElement(regions, "customers1"); + assertThat(region.getGroup()).isEqualTo("group1"); + + region = (RuntimeCacheElement) CacheElement.findElement(regions, "customers2"); + assertThat(region.getGroup()).isEqualTo("group1"); + + region = (RuntimeCacheElement) CacheElement.findElement(regions, "customers3"); + assertThat(region.getGroups()).containsExactlyInAnyOrder("group1", "group2"); } @Test public void listGroup2() throws Exception { // list group1 filter.setGroup("group2"); - List<CacheElement> regions = client.list(filter).getResult(); - assertThat(regions).hasSize(1); - assertThat(regions.get(0).getId()).isEqualTo("customers2"); - assertThat(regions.get(0).getConfigGroup()).isEqualTo("group2"); - assertThat(regions.get(0).getGroup()).isEqualTo("group2"); + List<RuntimeCacheElement> regions = client.list(filter).getResult(); + assertThat(regions).hasSize(2); + + RuntimeCacheElement region = CacheElement.findElement(regions, "customers2"); + assertThat(region.getGroup()).isEqualTo("group2"); + + region = CacheElement.findElement(regions, "customers3"); + assertThat(region.getGroups()).containsExactlyInAnyOrder("group1", "group2"); } @Test public void listNonExistentGroup() throws Exception { // list non-existent group filter.setGroup("group3"); - List<CacheElement> regions = client.list(filter).getResult(); + List<RuntimeCacheElement> regions = client.list(filter).getResult(); assertThat(regions).hasSize(0); } @Test public void listRegionByName() throws Exception { filter.setName("customers"); - List<CacheElement> regions = client.list(filter).getResult(); + List<RuntimeCacheElement> regions = client.list(filter).getResult(); assertThat(regions).hasSize(1); assertThat(regions.get(0).getId()).isEqualTo("customers"); - assertThat(regions.get(0).getConfigGroup()).isEqualTo("cluster"); assertThat(regions.get(0).getGroup()).isNull(); } @Test + public void listRegionByName1() throws Exception { + filter.setName("customers1"); + List<RuntimeCacheElement> regions = client.list(filter).getResult(); + assertThat(regions).hasSize(1); + assertThat(regions.get(0).getId()).isEqualTo("customers1"); + assertThat(regions.get(0).getGroup()).isEqualTo("group1"); + } + + @Test + public void listRegionByName2() throws Exception { + filter.setName("customers2"); + List<RuntimeCacheElement> regions = client.list(filter).getResult(); + assertThat(regions).hasSize(2); + assertThat(regions.stream().map(RuntimeCacheElement::getGroup).collect(Collectors.toList())) + .containsExactlyInAnyOrder("group1", "group2"); + assertThat(regions.stream().map(RegionConfig.class::cast) + .map(RegionConfig::getType) + .collect(Collectors.toList())) + .containsExactlyInAnyOrder("PARTITION", "PARTITION_PROXY"); + } + + @Test + public void listRegionByName3() throws Exception { + filter.setName("customers3"); + List<RuntimeCacheElement> regions = client.list(filter).getResult(); + assertThat(regions).hasSize(1); + assertThat(regions.get(0).getId()).isEqualTo("customers3"); + assertThat(regions.get(0).getGroups()).containsExactlyInAnyOrder("group1", "group2"); + } + + @Test public void listNonExistentRegion() throws Exception { // list non-existent region - filter.setName("customer3"); - List<CacheElement> regions = client.list(filter).getResult(); + filter.setName("customer4"); + List<RuntimeCacheElement> regions = client.list(filter).getResult(); assertThat(regions).hasSize(0); } } diff --git a/geode-assembly/src/integrationTest/resources/assembly_content.txt b/geode-assembly/src/integrationTest/resources/assembly_content.txt index bb3200b..5cc2a63 100644 --- a/geode-assembly/src/integrationTest/resources/assembly_content.txt +++ b/geode-assembly/src/integrationTest/resources/assembly_content.txt @@ -707,6 +707,8 @@ javadoc/org/apache/geode/management/client/package-frame.html javadoc/org/apache/geode/management/client/package-summary.html javadoc/org/apache/geode/management/client/package-tree.html javadoc/org/apache/geode/management/configuration/MemberConfig.html +javadoc/org/apache/geode/management/configuration/RuntimeCacheElement.html +javadoc/org/apache/geode/management/configuration/RuntimeRegionConfig.html javadoc/org/apache/geode/management/configuration/package-frame.html javadoc/org/apache/geode/management/configuration/package-summary.html javadoc/org/apache/geode/management/configuration/package-tree.html diff --git a/geode-core/src/integrationTest/java/org/apache/geode/management/internal/configuration/mutators/RegionConfigMutatorIntegrationTest.java b/geode-core/src/integrationTest/java/org/apache/geode/management/internal/configuration/mutators/RegionConfigMutatorIntegrationTest.java index 30d4140..c3b84aa 100644 --- a/geode-core/src/integrationTest/java/org/apache/geode/management/internal/configuration/mutators/RegionConfigMutatorIntegrationTest.java +++ b/geode-core/src/integrationTest/java/org/apache/geode/management/internal/configuration/mutators/RegionConfigMutatorIntegrationTest.java @@ -37,7 +37,7 @@ public class RegionConfigMutatorIntegrationTest { @Before public void before() throws Exception { config = new RegionConfig(); - mutator = new RegionConfigManager(); + mutator = new RegionConfigManager(locator.getCache()); } @Test 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 5d79e29..ffa9342 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 @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -42,12 +43,14 @@ import org.apache.geode.internal.logging.LogService; import org.apache.geode.management.api.ClusterManagementResult; import org.apache.geode.management.api.ClusterManagementService; import org.apache.geode.management.configuration.MemberConfig; +import org.apache.geode.management.configuration.RuntimeCacheElement; import org.apache.geode.management.internal.cli.CliUtil; import org.apache.geode.management.internal.cli.functions.CliFunctionResult; import org.apache.geode.management.internal.cli.functions.UpdateCacheFunction; import org.apache.geode.management.internal.configuration.mutators.ConfigurationManager; import org.apache.geode.management.internal.configuration.mutators.MemberConfigManager; import org.apache.geode.management.internal.configuration.mutators.RegionConfigManager; +import org.apache.geode.management.internal.configuration.validators.CacheElementValidator; import org.apache.geode.management.internal.configuration.validators.ConfigurationValidator; import org.apache.geode.management.internal.configuration.validators.RegionConfigValidator; import org.apache.geode.management.internal.exceptions.EntityExistsException; @@ -56,23 +59,24 @@ public class LocatorClusterManagementService implements ClusterManagementService private static final Logger logger = LogService.getLogger(); private InternalCache cache; private ConfigurationPersistenceService persistenceService; - private HashMap<Class, ConfigurationManager> managers; - private HashMap<Class, ConfigurationValidator> validators; + private Map<Class, ConfigurationManager> managers; + private Map<Class, ConfigurationValidator> validators; public LocatorClusterManagementService(InternalCache cache, ConfigurationPersistenceService persistenceService) { this(cache, persistenceService, new HashMap(), new HashMap()); // initialize the list of managers - managers.put(RegionConfig.class, new RegionConfigManager()); + managers.put(RegionConfig.class, new RegionConfigManager(cache)); managers.put(MemberConfig.class, new MemberConfigManager(cache)); // initialize the list of validators + validators.put(CacheElement.class, new CacheElementValidator()); validators.put(RegionConfig.class, new RegionConfigValidator(cache)); } @VisibleForTesting public LocatorClusterManagementService(InternalCache cache, - ConfigurationPersistenceService persistenceService, HashMap managers, HashMap validators) { + ConfigurationPersistenceService persistenceService, Map managers, Map validators) { this.cache = cache; this.persistenceService = persistenceService; this.managers = managers; @@ -88,18 +92,24 @@ public class LocatorClusterManagementService implements ClusterManagementService "Cluster configuration service needs to be enabled"); } - ClusterManagementResult result = new ClusterManagementResult(); - ConfigurationManager configurationMutator = managers.get(config.getClass()); + // first validate common attributes of all configuration object + validators.get(CacheElement.class).validate(config); ConfigurationValidator validator = validators.get(config.getClass()); if (validator != null) { validator.validate(config); + // exit early if config element already exists in cache config + CacheConfig currentPersistedConfig = persistenceService.getCacheConfig(group, true); + if (validator.exists(config, currentPersistedConfig)) { + throw new EntityExistsException("cache element " + config.getId() + " already exists."); + } } - // exit early if config element already exists in cache config - CacheConfig currentPersistedConfig = persistenceService.getCacheConfig(group, true); - if (validator.exists(config, currentPersistedConfig)) { - throw new EntityExistsException("cache element " + config.getId() + " already exists."); + // validate that user used the correct config object type + ConfigurationManager configurationManager = managers.get(config.getClass()); + if (configurationManager == null) { + throw new IllegalArgumentException(String.format("Configuration type %s is not supported.", + config.getClass().getSimpleName())); } // execute function on all members @@ -110,6 +120,8 @@ public class LocatorClusterManagementService implements ClusterManagementService "no members found in " + group + " to create cache element"); } + ClusterManagementResult result = new ClusterManagementResult(); + List<CliFunctionResult> functionResults = executeAndGetFunctionResult( new UpdateCacheFunction(), Arrays.asList(config, UpdateCacheFunction.CacheElementOperation.ADD), @@ -129,7 +141,7 @@ public class LocatorClusterManagementService implements ClusterManagementService final String finalGroup = group; // the below lambda requires a reference that is final persistenceService.updateCacheConfig(finalGroup, cacheConfigForGroup -> { try { - configurationMutator.add(config, cacheConfigForGroup); + configurationManager.add(config, cacheConfigForGroup); result.setStatus(true, "successfully persisted config for " + finalGroup); } catch (Exception e) { @@ -159,7 +171,7 @@ public class LocatorClusterManagementService implements ClusterManagementService ClusterManagementResult result = new ClusterManagementResult(); if (filter instanceof MemberConfig) { - List<CacheElement> listResults = manager.list(filter, null); + List<RuntimeCacheElement> listResults = manager.list(filter, null); result.setResult(listResults); return result; } @@ -169,23 +181,46 @@ public class LocatorClusterManagementService implements ClusterManagementService "Cluster configuration service needs to be enabled"); } - List<CacheElement> elements = new ArrayList<>(); + List<RuntimeCacheElement> resultList = new ArrayList<>(); + + // get a list of all the resultList from all groups that satisfy the filter criteria (all + // filters + // have been applied except the group) for (String group : persistenceService.getGroups()) { - if (StringUtils.isBlank(filter.getGroup()) || group.equals(filter.getConfigGroup())) { - CacheConfig currentPersistedConfig = persistenceService.getCacheConfig(group, true); - List<CacheElement> listInGroup = manager.list(filter, currentPersistedConfig); - // only set the group attribute when the config level is not in the cluster level - if (!group.equals("cluster")) { - listInGroup.stream().forEach(e -> e.setGroup(group)); + CacheConfig currentPersistedConfig = persistenceService.getCacheConfig(group, true); + List<RuntimeCacheElement> listInGroup = manager.list(filter, currentPersistedConfig); + for (RuntimeCacheElement element : listInGroup) { + element.getGroups().add(group); + int index = resultList.indexOf(element); + if (index >= 0) { + RuntimeCacheElement exist = resultList.get(index); + exist.getGroups().add(group); + } else { + resultList.add(element); } - elements.addAll(listInGroup); } } - result.setResult(elements); + // filtering by group. Do this after iterating through all the groups because some region might + // belong to multiple groups and we want the "group" field to show that. + if (StringUtils.isNotBlank(filter.getGroup())) { + resultList = + resultList.stream().filter(e -> e.getGroups().contains(filter.getConfigGroup())) + .collect(Collectors.toList()); + } + + // if "cluster" is the only group of the element, remove it + for (RuntimeCacheElement element : resultList) { + if (element.getGroups().size() == 1 && "cluster".equals(element.getGroup())) { + element.getGroups().clear(); + } + } + + result.setResult(resultList); return result; } + @Override public boolean isConnected() { return true; diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/configuration/mutators/ConfigurationManager.java b/geode-core/src/main/java/org/apache/geode/management/internal/configuration/mutators/ConfigurationManager.java index 9862cff..83f31f9 100644 --- a/geode-core/src/main/java/org/apache/geode/management/internal/configuration/mutators/ConfigurationManager.java +++ b/geode-core/src/main/java/org/apache/geode/management/internal/configuration/mutators/ConfigurationManager.java @@ -22,6 +22,7 @@ import java.util.List; import org.apache.geode.annotations.Experimental; import org.apache.geode.cache.configuration.CacheConfig; import org.apache.geode.cache.configuration.CacheElement; +import org.apache.geode.management.configuration.RuntimeCacheElement; /** * Defines the behavior to mutate a configuration change into a pre-existing cache config from a @@ -37,5 +38,5 @@ public interface ConfigurationManager<T extends CacheElement> { void delete(T config, CacheConfig existing); - List<? extends T> list(T filterConfig, CacheConfig existing); + List<? extends RuntimeCacheElement> list(T filterConfig, CacheConfig existing); } diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/configuration/mutators/RegionConfigManager.java b/geode-core/src/main/java/org/apache/geode/management/internal/configuration/mutators/RegionConfigManager.java index 87e239e..de44010 100644 --- a/geode-core/src/main/java/org/apache/geode/management/internal/configuration/mutators/RegionConfigManager.java +++ b/geode-core/src/main/java/org/apache/geode/management/internal/configuration/mutators/RegionConfigManager.java @@ -17,6 +17,7 @@ package org.apache.geode.management.internal.configuration.mutators; +import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -25,10 +26,20 @@ import org.apache.commons.lang3.StringUtils; import org.apache.geode.cache.configuration.CacheConfig; import org.apache.geode.cache.configuration.RegionConfig; +import org.apache.geode.internal.cache.InternalCache; +import org.apache.geode.management.DistributedRegionMXBean; +import org.apache.geode.management.ManagementService; +import org.apache.geode.management.configuration.RuntimeRegionConfig; -public class RegionConfigManager implements ConfigurationManager<RegionConfig> { +public class RegionConfigManager + implements ConfigurationManager<RegionConfig> { + private InternalCache cache; + private ManagementService managementService; - public RegionConfigManager() {} + public RegionConfigManager(InternalCache cache) { + this.cache = cache; + this.managementService = ManagementService.getExistingManagementService(cache); + } @Override public void add(RegionConfig configElement, CacheConfig existingConfig) { @@ -46,11 +57,27 @@ public class RegionConfigManager implements ConfigurationManager<RegionConfig> { } @Override - public List<RegionConfig> list(RegionConfig filter, CacheConfig existing) { + public List<RuntimeRegionConfig> list(RegionConfig filter, CacheConfig existing) { + List<RegionConfig> staticRegionConfigs; if (StringUtils.isBlank(filter.getName())) { - return existing.getRegions(); + staticRegionConfigs = existing.getRegions(); + } else { + staticRegionConfigs = + existing.getRegions().stream().filter(r -> filter.getName().equals(r.getName())).collect( + Collectors.toList()); + } + + List<RuntimeRegionConfig> results = new ArrayList<>(); + for (RegionConfig config : staticRegionConfigs) { + DistributedRegionMXBean distributedRegionMXBean = + managementService.getDistributedRegionMXBean("/" + config.getName()); + if (distributedRegionMXBean == null) { + throw new IllegalStateException("Can't get the region mbean info for " + config.getName()); + } + RuntimeRegionConfig runtimeConfig = new RuntimeRegionConfig(config); + runtimeConfig.setEntryCount(distributedRegionMXBean.getSystemRegionEntryCount()); + results.add(runtimeConfig); } - return existing.getRegions().stream().filter(r -> filter.getName().equals(r.getName())).collect( - Collectors.toList()); + return results; } } diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/configuration/validators/CacheElementValidator.java b/geode-core/src/main/java/org/apache/geode/management/internal/configuration/validators/CacheElementValidator.java new file mode 100644 index 0000000..085fce3 --- /dev/null +++ b/geode-core/src/main/java/org/apache/geode/management/internal/configuration/validators/CacheElementValidator.java @@ -0,0 +1,37 @@ +/* + * 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.validators; + +import org.apache.geode.cache.configuration.CacheConfig; +import org.apache.geode.cache.configuration.CacheElement; + +/** + * this is used to validate all the common attributes of CacheElement, eg. group + */ +public class CacheElementValidator implements ConfigurationValidator<CacheElement> { + @Override + public void validate(CacheElement config) throws IllegalArgumentException { + if ("cluster".equalsIgnoreCase(config.getGroup())) { + throw new IllegalArgumentException( + "cluster is a reserved group name. Do not use it for member groups."); + } + } + + @Override + public boolean exists(CacheElement config, CacheConfig persistedConfig) { + return false; + } +} diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/configuration/validators/RegionConfigValidator.java b/geode-core/src/main/java/org/apache/geode/management/internal/configuration/validators/RegionConfigValidator.java index 79084fe..f794e4a 100644 --- a/geode-core/src/main/java/org/apache/geode/management/internal/configuration/validators/RegionConfigValidator.java +++ b/geode-core/src/main/java/org/apache/geode/management/internal/configuration/validators/RegionConfigValidator.java @@ -40,11 +40,6 @@ public class RegionConfigValidator implements ConfigurationValidator<RegionConfi RegionNameValidation.validate(config.getName()); - if ("cluster".equalsIgnoreCase(config.getGroup())) { - throw new IllegalArgumentException( - "cluster is a reserved group name. Do not use it for member groups."); - } - if (config.getType() == null) { RegionType defaultRegion = RegionType.PARTITION; config.setType(defaultRegion); diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/api/LocatorClusterManagementServiceTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/api/LocatorClusterManagementServiceTest.java index ff5a79b..7bf79c8 100644 --- a/geode-core/src/test/java/org/apache/geode/management/internal/api/LocatorClusterManagementServiceTest.java +++ b/geode-core/src/test/java/org/apache/geode/management/internal/api/LocatorClusterManagementServiceTest.java @@ -15,29 +15,45 @@ package org.apache.geode.management.internal.api; +import static org.apache.geode.test.junit.assertions.ClusterManagementResultAssert.assertManagementResult; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import com.google.common.collect.Sets; import org.junit.Before; import org.junit.Test; import org.apache.geode.cache.configuration.CacheConfig; +import org.apache.geode.cache.configuration.CacheElement; import org.apache.geode.cache.configuration.RegionConfig; import org.apache.geode.distributed.ConfigurationPersistenceService; import org.apache.geode.distributed.DistributedMember; import org.apache.geode.internal.cache.InternalCache; import org.apache.geode.management.api.ClusterManagementResult; +import org.apache.geode.management.configuration.MemberConfig; +import org.apache.geode.management.configuration.RuntimeCacheElement; +import org.apache.geode.management.configuration.RuntimeRegionConfig; import org.apache.geode.management.internal.cli.functions.CliFunctionResult; -import org.apache.geode.management.internal.exceptions.EntityExistsException; +import org.apache.geode.management.internal.configuration.mutators.ConfigurationManager; +import org.apache.geode.management.internal.configuration.validators.CacheElementValidator; +import org.apache.geode.management.internal.configuration.validators.ConfigurationValidator; +import org.apache.geode.management.internal.configuration.validators.RegionConfigValidator; public class LocatorClusterManagementServiceTest { @@ -46,12 +62,25 @@ public class LocatorClusterManagementServiceTest { private ConfigurationPersistenceService persistenceService; private RegionConfig regionConfig; private ClusterManagementResult result; + private Map<Class, ConfigurationValidator> validators = new HashMap<>(); + private Map<Class, ConfigurationManager> managers = new HashMap<>(); + private ConfigurationValidator<RegionConfig> regionValidator; + private ConfigurationValidator<CacheElement> cacheElementValidator; + private ConfigurationManager<RegionConfig> regionManager; @Before public void before() throws Exception { + regionValidator = mock(RegionConfigValidator.class); + regionManager = mock(ConfigurationManager.class); + cacheElementValidator = mock(CacheElementValidator.class); + validators.put(RegionConfig.class, regionValidator); + validators.put(CacheElement.class, cacheElementValidator); + managers.put(RegionConfig.class, regionManager); + cache = mock(InternalCache.class); persistenceService = mock(ConfigurationPersistenceService.class); - service = spy(new LocatorClusterManagementService(cache, persistenceService)); + service = + spy(new LocatorClusterManagementService(cache, persistenceService, managers, validators)); regionConfig = new RegionConfig(); } @@ -65,33 +94,14 @@ public class LocatorClusterManagementServiceTest { } @Test - public void elementAlreadyExist() throws Exception { - regionConfig.setName("test"); - CacheConfig cacheConfig = new CacheConfig(); - cacheConfig.getRegions().add(regionConfig); - when(persistenceService.getCacheConfig("cluster", true)).thenReturn(cacheConfig); - - assertThatThrownBy(() -> service.create(regionConfig)) - .isInstanceOf(EntityExistsException.class) - .hasMessageContaining("cache element test already exists"); - } - - @Test - public void validationFailed() throws Exception { - assertThatThrownBy(() -> service.create(regionConfig)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Name of the region has to be specified"); - } - - @Test - public void noMemberFound() throws Exception { - regionConfig.setName("test"); - when(persistenceService.getCacheConfig("cluster", true)).thenReturn(new CacheConfig()); - doReturn(Collections.emptySet()).when(service).findMembers(any()); - result = service.create(regionConfig); - assertThat(result.isSuccessful()).isFalse(); - assertThat(result.getStatusMessage()) - .contains("no members found in cluster to create cache element"); + public void validatorIsCalledCorrectly() throws Exception { + doReturn(Collections.emptySet()).when(service).findMembers(anyString()); + assertManagementResult(service.create(regionConfig)) + .failed().hasStatusCode(ClusterManagementResult.StatusCode.ERROR) + .containsStatusMessage("no members found"); + verify(cacheElementValidator).validate(regionConfig); + verify(regionValidator).validate(regionConfig); + verify(regionValidator).exists(eq(regionConfig), any()); } @Test @@ -110,4 +120,47 @@ public class LocatorClusterManagementServiceTest { assertThat(result.getStatusMessage()) .contains("Failed to apply the update on all members"); } + + @Test + public void non_supportedConfigObject() throws Exception { + MemberConfig config = new MemberConfig(); + assertThatThrownBy(() -> service.create(config)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Configuration type MemberConfig is not supported"); + } + + @Test + public void listOneGroup() throws Exception { + regionConfig.setGroup("cluster"); + when(persistenceService.getGroups()).thenReturn(Sets.newHashSet("cluster", "group1")); + + service.list(regionConfig); + // even we are listing regions in one group, we still need to go through all the groups + verify(persistenceService).getCacheConfig("cluster", true); + verify(persistenceService).getCacheConfig("group1", true); + verify(regionManager, times(2)).list(any(), any()); + } + + @Test + public void aRegionInClusterAndGroup1() throws Exception { + when(persistenceService.getGroups()).thenReturn(Sets.newHashSet("cluster", "group1")); + RuntimeRegionConfig region1 = new RuntimeRegionConfig(); + region1.setName("region1"); + region1.setType("REPLICATE"); + RuntimeRegionConfig region2 = new RuntimeRegionConfig(); + region2.setName("region1"); + region2.setType("REPLICATE"); + + List clusterRegions = Arrays.asList(region1); + List group1Regions = Arrays.asList(region2); + when(regionManager.list(any(), any())).thenReturn(clusterRegions) + .thenReturn(group1Regions); + + // this is to make sure when 'cluster" is in one of the group, it will show + // the cluster and the other group name + List<RuntimeCacheElement> results = service.list(new RegionConfig()).getResult(); + assertThat(results).hasSize(1); + RuntimeRegionConfig result = (RuntimeRegionConfig) results.get(0); + assertThat(result.getName()).isEqualTo("region1"); + assertThat(result.getGroups()).containsExactlyInAnyOrder("cluster", "group1"); + } } diff --git a/geode-core/src/integrationTest/java/org/apache/geode/management/internal/configuration/mutators/RegionConfigMutatorIntegrationTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/configuration/validators/CacheElementValidatorTest.java similarity index 52% copy from geode-core/src/integrationTest/java/org/apache/geode/management/internal/configuration/mutators/RegionConfigMutatorIntegrationTest.java copy to geode-core/src/test/java/org/apache/geode/management/internal/configuration/validators/CacheElementValidatorTest.java index 30d4140..1be5265 100644 --- a/geode-core/src/integrationTest/java/org/apache/geode/management/internal/configuration/mutators/RegionConfigMutatorIntegrationTest.java +++ b/geode-core/src/test/java/org/apache/geode/management/internal/configuration/validators/CacheElementValidatorTest.java @@ -12,42 +12,34 @@ * 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; +package org.apache.geode.management.internal.configuration.validators; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; -import org.apache.geode.cache.configuration.CacheConfig; -import org.apache.geode.cache.configuration.CacheElement; import org.apache.geode.cache.configuration.RegionConfig; -import org.apache.geode.cache.configuration.RegionType; -import org.apache.geode.test.junit.rules.LocatorStarterRule; - -public class RegionConfigMutatorIntegrationTest { - @Rule - public LocatorStarterRule locator = new LocatorStarterRule().withAutoStart(); +public class CacheElementValidatorTest { - private RegionConfigManager mutator; + private CacheElementValidator validator; private RegionConfig config; @Before public void before() throws Exception { + validator = new CacheElementValidator(); config = new RegionConfig(); - mutator = new RegionConfigManager(); } @Test - public void sanity() throws Exception { - config.setType(RegionType.REPLICATE); + public void invalidGroup_cluster() throws Exception { config.setName("test"); - CacheConfig cacheConfig = - locator.getLocator().getConfigurationPersistenceService().getCacheConfig("cluster", true); - - mutator.add(config, cacheConfig); - assertThat(CacheElement.findElement(cacheConfig.getRegions(), config.getId())).isNotNull(); + config.setGroup("cluster"); + assertThatThrownBy(() -> validator.validate(config)).isInstanceOf( + IllegalArgumentException.class) + .hasMessageContaining( + "cluster is a reserved group name"); } } diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/configuration/validators/RegionConfigValidatorTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/configuration/validators/RegionConfigValidatorTest.java index 8c70c00..38dbf58 100644 --- a/geode-core/src/test/java/org/apache/geode/management/internal/configuration/validators/RegionConfigValidatorTest.java +++ b/geode-core/src/test/java/org/apache/geode/management/internal/configuration/validators/RegionConfigValidatorTest.java @@ -113,13 +113,4 @@ public class RegionConfigValidatorTest { "Region names may only be alphanumeric and may contain hyphens or underscores"); } - @Test - public void invalidGroup() throws Exception { - config.setName("test"); - config.setGroup("cluster"); - assertThatThrownBy(() -> validator.validate(config)).isInstanceOf( - IllegalArgumentException.class) - .hasMessageContaining( - "cluster is a reserved group name"); - } } diff --git a/geode-junit/src/main/java/org/apache/geode/test/junit/assertions/ClusterManagementResultAssert.java b/geode-junit/src/main/java/org/apache/geode/test/junit/assertions/ClusterManagementResultAssert.java index f66acbe..fa3a7a8 100644 --- a/geode-junit/src/main/java/org/apache/geode/test/junit/assertions/ClusterManagementResultAssert.java +++ b/geode-junit/src/main/java/org/apache/geode/test/junit/assertions/ClusterManagementResultAssert.java @@ -20,8 +20,8 @@ import static org.assertj.core.api.Assertions.assertThat; import org.assertj.core.api.AbstractAssert; import org.assertj.core.api.ListAssert; -import org.apache.geode.cache.configuration.CacheElement; import org.apache.geode.management.api.ClusterManagementResult; +import org.apache.geode.management.configuration.RuntimeCacheElement; public class ClusterManagementResultAssert extends AbstractAssert<ClusterManagementResultAssert, ClusterManagementResult> { @@ -50,7 +50,7 @@ public class ClusterManagementResultAssert return this; } - public ListAssert<CacheElement> hasListResult() { + public ListAssert<RuntimeCacheElement> hasListResult() { return assertThat(actual.getResult()); } diff --git a/geode-management/src/main/java/org/apache/geode/cache/configuration/CacheElement.java b/geode-management/src/main/java/org/apache/geode/cache/configuration/CacheElement.java index 4462f57..268ae1d 100644 --- a/geode-management/src/main/java/org/apache/geode/cache/configuration/CacheElement.java +++ b/geode-management/src/main/java/org/apache/geode/cache/configuration/CacheElement.java @@ -18,11 +18,13 @@ package org.apache.geode.cache.configuration; import java.io.Serializable; +import java.util.ArrayList; import java.util.List; import javax.xml.bind.annotation.XmlTransient; import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonSetter; import com.fasterxml.jackson.annotation.JsonTypeInfo; import org.apache.commons.lang3.StringUtils; @@ -32,35 +34,53 @@ import org.apache.geode.lang.Identifiable; @Experimental @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "class") public abstract class CacheElement implements Identifiable<String>, Serializable { - private String group; + protected List<String> groups = new ArrayList<>(); - public static <T extends CacheElement> boolean exists(List<T> list, String id) { + public static <T extends Identifiable> boolean exists(List<T> list, String id) { return list.stream().anyMatch(o -> o.getId().equals(id)); } - public static <T extends CacheElement> T findElement(List<T> list, String id) { + public static <T extends Identifiable> T findElement(List<T> list, String id) { return list.stream().filter(o -> o.getId().equals(id)).findFirst().orElse(null); } - public static <T extends CacheElement> void removeElement(List<T> list, String id) { + public static <T extends Identifiable> void removeElement(List<T> list, String id) { list.removeIf(t -> t.getId().equals(id)); } - @XmlTransient - public String getGroup() { - return group; - } - + /** + * this returns a non-null value + * for cluster level element, it will return "cluster" for sure. + */ @XmlTransient @JsonIgnore public String getConfigGroup() { + String group = getGroup(); if (StringUtils.isBlank(group)) { return "cluster"; } return group; } + /** + * this returns the first group set by the user + * if no group is set, this returns null + */ + @XmlTransient + public String getGroup() { + if (groups.size() == 0) { + return null; + } + return groups.get(0); + } + + @JsonSetter public void setGroup(String group) { - this.group = group; + groups.clear(); + + if (StringUtils.isBlank(group)) { + return; + } + groups.add(group); } } 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 b3d43e4..610233e 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 @@ -30,6 +30,7 @@ import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlType; import com.fasterxml.jackson.annotation.JsonIgnore; +import com.google.common.base.Objects; import org.apache.geode.annotations.Experimental; import org.apache.geode.management.api.RestfulEndpoint; @@ -178,6 +179,17 @@ public class RegionConfig extends CacheElement implements RestfulEndpoint { this.type = refid; } + public RegionConfig(RegionConfig config) { + this.regionAttributes = config.getRegionAttributes(); + this.type = config.getType(); + this.entries = config.getEntries(); + this.indexes = config.getIndexes(); + this.name = config.getName(); + this.regionElements = config.getCustomRegionElements(); + this.regions = config.getRegions(); + this.setGroup(config.getGroup()); + } + @Override public String getEndpoint() { return REGION_CONFIG_ENDPOINT; @@ -467,6 +479,18 @@ public class RegionConfig extends CacheElement implements RestfulEndpoint { return getName(); } + @Override + public boolean equals(Object that) { + if (this == that) { + return true; + } + if (that == null || getClass() != that.getClass()) { + return false; + } + RegionConfig config = (RegionConfig) that; + return Objects.equal(getName(), config.getName()) && + Objects.equal(getType(), config.getType()); + } /** * <p> diff --git a/geode-management/src/main/java/org/apache/geode/management/api/ClusterManagementResult.java b/geode-management/src/main/java/org/apache/geode/management/api/ClusterManagementResult.java index 0f825f2..17fc775 100644 --- a/geode-management/src/main/java/org/apache/geode/management/api/ClusterManagementResult.java +++ b/geode-management/src/main/java/org/apache/geode/management/api/ClusterManagementResult.java @@ -22,7 +22,7 @@ import java.util.Map; import com.fasterxml.jackson.annotation.JsonIgnore; import org.apache.geode.annotations.Experimental; -import org.apache.geode.cache.configuration.CacheElement; +import org.apache.geode.management.configuration.RuntimeCacheElement; @Experimental public class ClusterManagementResult { @@ -59,7 +59,7 @@ public class ClusterManagementResult { private StatusCode statusCode = StatusCode.OK; private String statusMessage; - private List<CacheElement> result = new ArrayList<>(); + private List<RuntimeCacheElement> result = new ArrayList<>(); public ClusterManagementResult() {} @@ -109,11 +109,11 @@ public class ClusterManagementResult { return statusCode; } - public List<CacheElement> getResult() { + public List<RuntimeCacheElement> getResult() { return result; } - public void setResult(List<CacheElement> result) { + public void setResult(List<RuntimeCacheElement> result) { this.result = result; } } diff --git a/geode-management/src/main/java/org/apache/geode/management/configuration/MemberConfig.java b/geode-management/src/main/java/org/apache/geode/management/configuration/MemberConfig.java index 4f488db..f4697f5 100644 --- a/geode-management/src/main/java/org/apache/geode/management/configuration/MemberConfig.java +++ b/geode-management/src/main/java/org/apache/geode/management/configuration/MemberConfig.java @@ -22,7 +22,7 @@ import org.apache.geode.cache.configuration.CacheElement; import org.apache.geode.management.api.RestfulEndpoint; @Experimental -public class MemberConfig extends CacheElement implements RestfulEndpoint { +public class MemberConfig extends CacheElement implements RuntimeCacheElement, RestfulEndpoint { private static final long serialVersionUID = -6262538068604902018L; @@ -92,4 +92,8 @@ public class MemberConfig extends CacheElement implements RestfulEndpoint { public String getId() { return id; } + + public List<String> getGroups() { + return groups; + } } diff --git a/geode-management/src/main/java/org/apache/geode/management/configuration/RuntimeCacheElement.java b/geode-management/src/main/java/org/apache/geode/management/configuration/RuntimeCacheElement.java new file mode 100644 index 0000000..b15e199 --- /dev/null +++ b/geode-management/src/main/java/org/apache/geode/management/configuration/RuntimeCacheElement.java @@ -0,0 +1,36 @@ +/* + * 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 java.io.Serializable; +import java.util.List; + +import javax.xml.bind.annotation.XmlTransient; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonTypeInfo; + +import org.apache.geode.lang.Identifiable; + +@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "class") +public interface RuntimeCacheElement extends Identifiable<String>, Serializable { + @XmlTransient + List<String> getGroups(); + + @XmlTransient + @JsonIgnore + String getGroup(); +} diff --git a/geode-management/src/main/java/org/apache/geode/management/configuration/RuntimeRegionConfig.java b/geode-management/src/main/java/org/apache/geode/management/configuration/RuntimeRegionConfig.java new file mode 100644 index 0000000..da4367e --- /dev/null +++ b/geode-management/src/main/java/org/apache/geode/management/configuration/RuntimeRegionConfig.java @@ -0,0 +1,45 @@ +/* + * 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 java.util.List; + +import org.apache.geode.annotations.Experimental; +import org.apache.geode.cache.configuration.RegionConfig; + +@Experimental +public class RuntimeRegionConfig extends RegionConfig implements RuntimeCacheElement { + private long entryCount; + + public RuntimeRegionConfig() {} + + public RuntimeRegionConfig(RegionConfig config) { + super(config); + } + + public long getEntryCount() { + return entryCount; + } + + public void setEntryCount(long entrySize) { + this.entryCount = entrySize; + } + + public List<String> getGroups() { + return groups; + } +} 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 c244e00..2d2be4f 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 @@ -26,13 +26,15 @@ import org.junit.Test; import org.apache.geode.management.api.ClusterManagementResult; import org.apache.geode.management.configuration.MemberConfig; +import org.apache.geode.management.configuration.RuntimeCacheElement; +import org.apache.geode.management.configuration.RuntimeRegionConfig; import org.apache.geode.util.internal.GeodeJsonMapper; public class CacheElementJsonMappingTest { private static ObjectMapper mapper = GeodeJsonMapper.getMapper(); private static MemberConfig member; - private static RegionConfig region; + private static RuntimeRegionConfig region; @BeforeClass public static void beforeClass() throws Exception { @@ -40,7 +42,7 @@ public class CacheElementJsonMappingTest { member.setId("server"); member.setPid("123"); - region = new RegionConfig(); + region = new RuntimeRegionConfig(); region.setName("test"); } @@ -79,7 +81,7 @@ public class CacheElementJsonMappingTest { @Test public void serializeResult() throws Exception { ClusterManagementResult result = new ClusterManagementResult(); - List<CacheElement> elements = new ArrayList<>(); + List<RuntimeCacheElement> elements = new ArrayList<>(); elements.add(region); elements.add(member); result.setResult(elements); @@ -108,4 +110,50 @@ public class CacheElementJsonMappingTest { String json = mapper.writeValueAsString(region); assertThat(json).doesNotContain("\"group\""); } + + @Test + public void group() throws Exception { + String json = "{'name':'test','group':'group1'}"; + RegionConfig regionConfig = mapper.readValue(json, RegionConfig.class); + assertThat(regionConfig.getGroup()).isEqualTo("group1"); + } + + @Test + public void groups() throws Exception { + String json = "{'name':'test','groups':['group1','group2']}"; + RuntimeRegionConfig regionConfig = mapper.readValue(json, RuntimeRegionConfig.class); + assertThat(regionConfig.getGroups()).containsExactlyInAnyOrder("group1", "group2"); + } + + @Test + public void serializeGroup() throws Exception { + RegionConfig config = new RegionConfig(); + config.setName("test"); + config.setGroup("group1"); + String json = mapper.writeValueAsString(config); + System.out.println(json); + assertThat(json) + .contains("\"group\":\"group1\""); + } + + @Test + public void serializeMultipleGroup() throws Exception { + RuntimeRegionConfig config = new RuntimeRegionConfig(); + config.setName("test"); + config.getGroups().add("group1"); + config.getGroups().add("group2"); + String json = mapper.writeValueAsString(config); + System.out.println(json); + assertThat(json).contains("\"groups\":[\"group1\",\"group2\"]").doesNotContain("\"group\""); + } + + @Test + public void serializeGroupCluster() throws Exception { + RegionConfig config = new RegionConfig(); + config.setName("test"); + config.setGroup("cluster"); + String json = mapper.writeValueAsString(config); + System.out.println(json); + assertThat(json).contains("\"group\":\"cluster\""); + } } diff --git a/geode-management/src/test/java/org/apache/geode/cache/configuration/CacheElementTest.java b/geode-management/src/test/java/org/apache/geode/cache/configuration/CacheElementTest.java new file mode 100644 index 0000000..b3d075b --- /dev/null +++ b/geode-management/src/test/java/org/apache/geode/cache/configuration/CacheElementTest.java @@ -0,0 +1,102 @@ +/* + * 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.cache.configuration; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import org.apache.geode.management.configuration.RuntimeCacheElement; +import org.apache.geode.management.configuration.RuntimeRegionConfig; +import org.apache.geode.util.internal.GeodeJsonMapper; + +public class CacheElementTest { + + private CacheElement element; + private RuntimeCacheElement runtime; + + private static ObjectMapper mapper; + private String json; + + @BeforeClass + public static void beforeClass() { + mapper = GeodeJsonMapper.getMapper(); + } + + @Before + public void before() throws Exception { + element = new RegionConfig(); + runtime = new RuntimeRegionConfig(); + } + + @Test + public void plainRegionConfig() throws Exception { + assertThat(element.getGroup()).isNull(); + assertThat(element.getConfigGroup()).isEqualTo("cluster"); + json = mapper.writeValueAsString(element); + System.out.println(json); + assertThat(json).doesNotContain("group").doesNotContain("groups"); + } + + @Test + public void plainRuntimeRegionConfig() throws Exception { + assertThat(runtime.getGroup()).isNull(); + assertThat(runtime.getGroups()).isNotNull().isEmpty(); + json = mapper.writeValueAsString(runtime); + System.out.println(json); + assertThat(json).doesNotContain("group").doesNotContain("groups"); + } + + + @Test + public void setterRegionConfigGroup() throws Exception { + element.setGroup("group1"); + assertThat(element.getGroup()).isEqualTo("group1"); + assertThat(element.getConfigGroup()).isEqualTo("group1"); + json = mapper.writeValueAsString(element); + System.out.println(json); + assertThat(json).contains("\"group\":\"group1\"").doesNotContain("groups"); + } + + @Test + public void setterRuntimeRegionConfig() throws Exception { + runtime.getGroups().add("group1"); + assertThat(runtime.getGroup()).isEqualTo("group1"); + json = mapper.writeValueAsString(runtime); + System.out.println(json); + assertThat(json).contains("\"groups\":[\"group1\"]").doesNotContain("\"group\""); + } + + @Test + public void copy() throws Exception { + RegionConfig config = new RegionConfig(); + config.setName("test"); + runtime = new RuntimeRegionConfig(config); + assertThat(runtime.getGroup()).isNull(); + assertThat(runtime.getGroups()).hasSize(0); + } + + @Test + public void setGroup() throws Exception { + element.setGroup("group1"); + assertThat(element.getGroup()).isEqualTo("group1"); + element.setGroup(""); + assertThat(element.getGroup()).isNull(); + } +} diff --git a/geode-web-management/src/distributedTest/java/org/apache/geode/management/client/ClientClusterManagementServiceDUnitTest.java b/geode-web-management/src/distributedTest/java/org/apache/geode/management/client/ClientClusterManagementServiceDUnitTest.java index c98b445..2d14160 100644 --- a/geode-web-management/src/distributedTest/java/org/apache/geode/management/client/ClientClusterManagementServiceDUnitTest.java +++ b/geode-web-management/src/distributedTest/java/org/apache/geode/management/client/ClientClusterManagementServiceDUnitTest.java @@ -19,8 +19,6 @@ package org.apache.geode.management.client; import static org.apache.geode.test.junit.assertions.ClusterManagementResultAssert.assertManagementResult; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -import java.util.List; - import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -32,7 +30,6 @@ import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.web.context.WebApplicationContext; -import org.apache.geode.cache.configuration.CacheElement; import org.apache.geode.cache.configuration.RegionConfig; import org.apache.geode.cache.configuration.RegionType; import org.apache.geode.management.api.ClusterManagementResult; @@ -68,7 +65,7 @@ public class ClientClusterManagementServiceDUnitTest { @Test @WithMockUser - public void createAndListRegion() { + public void createRegion() { RegionConfig region = new RegionConfig(); region.setName("customer"); region.setType(RegionType.REPLICATE); @@ -78,16 +75,6 @@ public class ClientClusterManagementServiceDUnitTest { // in StressNewTest, this will be run multiple times without restarting the locator assertManagementResult(result).hasStatusCode(ClusterManagementResult.StatusCode.OK, ClusterManagementResult.StatusCode.ENTITY_EXISTS); - - // list region when regions are not created in a group - RegionConfig noFilter = new RegionConfig(); - ClusterManagementResult list = client.list(noFilter); - List<CacheElement> regions = list.getResult(); - assertThat(regions.size()).isEqualTo(1); - RegionConfig cacheElement = (RegionConfig) regions.get(0); - assertThat(cacheElement.getId()).isEqualTo("customer"); - assertThat(cacheElement.getType()).isEqualTo("REPLICATE"); - assertThat(cacheElement.getConfigGroup()).isEqualTo("cluster"); } 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 35c81d3..b193e1a 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 @@ -34,6 +34,7 @@ import org.apache.geode.cache.configuration.RegionType; import org.apache.geode.management.api.ClusterManagementResult; import org.apache.geode.management.api.ClusterManagementService; import org.apache.geode.management.client.ClusterManagementServiceProvider; +import org.apache.geode.management.configuration.RuntimeRegionConfig; @RunWith(SpringRunner.class) @ContextConfiguration(locations = {"classpath*:WEB-INF/geode-management-servlet.xml"}, @@ -94,6 +95,18 @@ public class RegionManagementIntegrationTest { } @Test + public void invalidConfigObject() throws Exception { + RuntimeRegionConfig regionConfig = new RuntimeRegionConfig(); + regionConfig.setName("customers"); + regionConfig.setGroup("group1"); + + assertManagementResult(client.create(regionConfig)) + .failed() + .hasStatusCode(ClusterManagementResult.StatusCode.ILLEGAL_ARGUMENT) + .containsStatusMessage("Configuration type RuntimeRegionConfig is not supported"); + } + + @Test @WithMockUser public void ping() throws Exception { context.perform(get("/v2/ping"))