You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by je...@apache.org on 2019/02/22 13:17:48 UTC
[geode] branch develop updated: GEODE-6384: Create consistent API
to retrieve instances of ClusterManagementService (#3191)
This is an automated email from the ASF dual-hosted git repository.
jensdeppe 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 092f598 GEODE-6384: Create consistent API to retrieve instances of ClusterManagementService (#3191)
092f598 is described below
commit 092f5981c79b10ca5c6da642d1df8348f235f41c
Author: Jens Deppe <jd...@pivotal.io>
AuthorDate: Fri Feb 22 05:17:36 2019 -0800
GEODE-6384: Create consistent API to retrieve instances of ClusterManagementService (#3191)
- The overall intent of this commit is to provide a consistent means for
retrieving a ClusterMangementService instance regardless of the
context you are developing in. Currently, the relevant contexts are:
1) a Java application that has no access (or need to access) core
Geode code. 2) a typical Geode client application and 3) server or
locator-side code.
- Introduces a service provider interface
(ClusterManagementServiceProviderFactory) whose implementations are
context dependent. This commit introduces two implementations, namely:
BasicClusterManagementProviderFactory and
SmartClusterManagementServiceProviderFactory). The latter is
incomplete but will be fully supported in the near future.
- The entry point to creating a ClusterManagementService is in
ClusterManagementServiceProvider - more documentation can be found
there.
---
geode-assembly/build.gradle | 1 +
.../geode/test/junit/rules/HttpResponseAssert.java | 2 +-
...ClusterManagementLocatorReconnectDunitTest.java | 2 +-
.../internal/rest/RegionManagementDunitTest.java | 40 ++++-
.../internal/DisabledClusterConfigTest.java | 2 +-
.../integrationTest/resources/assembly_content.txt | 17 ++
...ClusterManagementServiceRetrievalDUnitTest.java | 53 ++++++
.../internal/api/RegionAPIDUnitTest.java | 1 +
.../commands/DescribeMembersCommandDUnitTest.java | 42 ++++-
.../distributed/internal/InternalLocator.java | 2 +-
.../internal/cache/ClusterConfigurationLoader.java | 1 -
...odeClusterManagementServiceProviderFactory.java | 124 ++++++++++++++
.../api/LocatorClusterManagementService.java | 2 +
.../cli/commands/DescribeMemberCommand.java | 5 -
.../internal/cli/domain/MemberInformation.java | 27 ++--
.../functions/GetMemberInformationFunction.java | 21 ++-
.../internal/cli/util/MemberInformation.java | 180 ---------------------
...ent.spi.ClusterManagementServiceProviderFactory | 16 ++
.../sanctioned-geode-core-serializables.txt | 5 +-
.../internal/api/ClusterManagementResultTest.java | 2 +
.../api/LocatorClusterManagementServiceTest.java | 1 +
.../geode/test/dunit/rules/ClusterStartupRule.java | 23 ++-
geode-management/build.gradle | 1 +
.../geode/cache/configuration/RegionConfig.java | 8 +-
.../api/ClusterManagementResult.java | 2 +-
.../api/ClusterManagementService.java | 38 ++++-
.../api/Status.java => api/RestfulEndpoint.java} | 29 +---
.../management/{internal => }/api/Status.java | 2 +-
.../client/ClusterManagementServiceProvider.java | 119 ++++++++++++++
.../client/RestTemplateResponseErrorHandler.java | 25 +--
.../internal/ClusterManagementClient.java | 105 ++++++++++++
.../ClusterManagementServiceProviderFactory.java | 60 +++++++
...JavaClientClusterManagementProviderFactory.java | 54 +++++++
...ent.spi.ClusterManagementServiceProviderFactory | 17 ++
.../src/test/resources/expected-pom.xml | 5 +
geode-web-management/build.gradle | 4 +
...xtLoader.java => BaseLocatorContextLoader.java} | 17 +-
.../LocatorWithSecurityManagerContextLoader.java | 31 ++--
.../internal/rest/PlainLocatorContextLoader.java | 36 ++---
.../rest/StandardRequestPostProcessor.java | 2 +-
.../client/ClusterManagementClientDUnitTest.java | 87 ++++++++++
.../rest/RegionManagementIntegrationTest.java | 3 +-
.../controllers/ManagementControllerAdvice.java | 4 +-
.../controllers/RegionManagementController.java | 2 +-
.../rest/security/RestSecurityConfiguration.java | 2 +-
45 files changed, 900 insertions(+), 322 deletions(-)
diff --git a/geode-assembly/build.gradle b/geode-assembly/build.gradle
index 1a1da28..c5d8510 100755
--- a/geode-assembly/build.gradle
+++ b/geode-assembly/build.gradle
@@ -189,6 +189,7 @@ dependencies {
distributedTestCompile(project(':extensions:session-testing-war'))
distributedTestCompile(project(':geode-assembly:geode-assembly-test'))
distributedTestCompile('org.apache.httpcomponents:httpclient')
+ distributedTestCompile('org.springframework:spring-web')
distributedTestRuntime(project(':extensions:geode-modules-session-internal')) {
exclude group: 'org.apache.tomcat'
diff --git a/geode-assembly/geode-assembly-test/src/main/java/org/apache/geode/test/junit/rules/HttpResponseAssert.java b/geode-assembly/geode-assembly-test/src/main/java/org/apache/geode/test/junit/rules/HttpResponseAssert.java
index 63e0c61..5ff00de 100644
--- a/geode-assembly/geode-assembly-test/src/main/java/org/apache/geode/test/junit/rules/HttpResponseAssert.java
+++ b/geode-assembly/geode-assembly-test/src/main/java/org/apache/geode/test/junit/rules/HttpResponseAssert.java
@@ -33,7 +33,7 @@ import org.assertj.core.api.AbstractCharSequenceAssert;
import org.assertj.core.api.ListAssert;
import org.apache.geode.internal.logging.LogService;
-import org.apache.geode.management.internal.api.ClusterManagementResult;
+import org.apache.geode.management.api.ClusterManagementResult;
public class HttpResponseAssert extends AbstractAssert<HttpResponseAssert, HttpResponse> {
private static final Logger logger = LogService.getLogger();
diff --git a/geode-assembly/src/distributedTest/java/org/apache/geode/management/internal/rest/ClusterManagementLocatorReconnectDunitTest.java b/geode-assembly/src/distributedTest/java/org/apache/geode/management/internal/rest/ClusterManagementLocatorReconnectDunitTest.java
index 846c162..7d70f08 100644
--- a/geode-assembly/src/distributedTest/java/org/apache/geode/management/internal/rest/ClusterManagementLocatorReconnectDunitTest.java
+++ b/geode-assembly/src/distributedTest/java/org/apache/geode/management/internal/rest/ClusterManagementLocatorReconnectDunitTest.java
@@ -28,7 +28,7 @@ import org.apache.geode.cache.Region;
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.management.internal.api.ClusterManagementResult;
+import org.apache.geode.management.api.ClusterManagementResult;
import org.apache.geode.test.dunit.IgnoredException;
import org.apache.geode.test.dunit.rules.ClusterStartupRule;
import org.apache.geode.test.dunit.rules.MemberVM;
diff --git a/geode-assembly/src/distributedTest/java/org/apache/geode/management/internal/rest/RegionManagementDunitTest.java b/geode-assembly/src/distributedTest/java/org/apache/geode/management/internal/rest/RegionManagementDunitTest.java
index 679eaea..db5263a 100644
--- a/geode-assembly/src/distributedTest/java/org/apache/geode/management/internal/rest/RegionManagementDunitTest.java
+++ b/geode-assembly/src/distributedTest/java/org/apache/geode/management/internal/rest/RegionManagementDunitTest.java
@@ -21,13 +21,15 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.client.RestTemplate;
import org.apache.geode.cache.Cache;
import org.apache.geode.cache.Region;
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.management.internal.api.ClusterManagementResult;
+import org.apache.geode.management.api.ClusterManagementResult;
import org.apache.geode.test.dunit.IgnoredException;
import org.apache.geode.test.dunit.rules.ClusterStartupRule;
import org.apache.geode.test.dunit.rules.MemberVM;
@@ -78,6 +80,42 @@ public class RegionManagementDunitTest {
}
@Test
+ public void createsRegionUsingClusterManagementClient() throws Exception {
+ RegionConfig regionConfig = new RegionConfig();
+ regionConfig.setName("customers2");
+ regionConfig.setType("REPLICATE");
+ ObjectMapper mapper = new ObjectMapper();
+ String json = mapper.writeValueAsString(regionConfig);
+
+ String url = String.format("http://localhost:%d/geode-management/v2/regions",
+ locator.getHttpPort());
+ RestTemplate template = new RestTemplate();
+
+ ResponseEntity<ClusterManagementResult> result =
+ template.postForEntity(url, regionConfig, ClusterManagementResult.class);
+
+ result.getBody();
+
+ // ClusterManagementResult result =
+ // restClient.doPostAndAssert("/regions", json)
+ // .hasStatusCode(201)
+ // .getClusterManagementResult();
+ //
+ // assertThat(result.isSuccessfullyAppliedOnMembers()).isTrue();
+ // assertThat(result.isSuccessfullyPersisted()).isTrue();
+ // assertThat(result.getMemberStatuses()).containsKeys("server-1").hasSize(1);
+ //
+ // // make sure region is created
+ // server.invoke(() -> verifyRegionCreated("customers", "REPLICATE"));
+ //
+ // // make sure region is persisted
+ // locator.invoke(() -> verifyRegionPersisted("customers", "REPLICATE"));
+ //
+ // // verify that additional server can be started with the cluster configuration
+ // cluster.startServerVM(2, locator.getPort());
+ }
+
+ @Test
public void createsAPartitionedRegionByDefault() throws Exception {
String json = "{\"name\": \"orders\"}";
diff --git a/geode-assembly/src/integrationTest/java/org/apache/geode/management/internal/DisabledClusterConfigTest.java b/geode-assembly/src/integrationTest/java/org/apache/geode/management/internal/DisabledClusterConfigTest.java
index f596830..d7af562 100644
--- a/geode-assembly/src/integrationTest/java/org/apache/geode/management/internal/DisabledClusterConfigTest.java
+++ b/geode-assembly/src/integrationTest/java/org/apache/geode/management/internal/DisabledClusterConfigTest.java
@@ -22,7 +22,7 @@ import org.junit.Rule;
import org.junit.Test;
import org.apache.geode.distributed.ConfigurationProperties;
-import org.apache.geode.management.internal.api.ClusterManagementResult;
+import org.apache.geode.management.api.ClusterManagementResult;
import org.apache.geode.test.junit.rules.GeodeDevRestClient;
import org.apache.geode.test.junit.rules.LocatorStarterRule;
import org.apache.geode.test.junit.rules.RequiresGeodeHome;
diff --git a/geode-assembly/src/integrationTest/resources/assembly_content.txt b/geode-assembly/src/integrationTest/resources/assembly_content.txt
index ab83cdd..c2569de 100644
--- a/geode-assembly/src/integrationTest/resources/assembly_content.txt
+++ b/geode-assembly/src/integrationTest/resources/assembly_content.txt
@@ -676,6 +676,13 @@ javadoc/org/apache/geode/management/PersistentMemberDetails.html
javadoc/org/apache/geode/management/RegionAttributesData.html
javadoc/org/apache/geode/management/RegionMXBean.html
javadoc/org/apache/geode/management/ServerLoadData.html
+javadoc/org/apache/geode/management/api/ClusterManagementResult.html
+javadoc/org/apache/geode/management/api/ClusterManagementService.html
+javadoc/org/apache/geode/management/api/RestfulEndpoint.html
+javadoc/org/apache/geode/management/api/Status.html
+javadoc/org/apache/geode/management/api/package-frame.html
+javadoc/org/apache/geode/management/api/package-summary.html
+javadoc/org/apache/geode/management/api/package-tree.html
javadoc/org/apache/geode/management/cli/CliFunction.html
javadoc/org/apache/geode/management/cli/CliMetaData.AvailabilityMetadata.html
javadoc/org/apache/geode/management/cli/CliMetaData.html
@@ -693,6 +700,11 @@ javadoc/org/apache/geode/management/cli/UpdateAllConfigurationGroupsMarker.html
javadoc/org/apache/geode/management/cli/package-frame.html
javadoc/org/apache/geode/management/cli/package-summary.html
javadoc/org/apache/geode/management/cli/package-tree.html
+javadoc/org/apache/geode/management/client/ClusterManagementServiceProvider.html
+javadoc/org/apache/geode/management/client/RestTemplateResponseErrorHandler.html
+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/membership/ClientMembership.html
javadoc/org/apache/geode/management/membership/ClientMembershipEvent.html
javadoc/org/apache/geode/management/membership/ClientMembershipListener.html
@@ -707,6 +719,11 @@ javadoc/org/apache/geode/management/membership/package-tree.html
javadoc/org/apache/geode/management/package-frame.html
javadoc/org/apache/geode/management/package-summary.html
javadoc/org/apache/geode/management/package-tree.html
+javadoc/org/apache/geode/management/spi/ClusterManagementServiceProviderFactory.html
+javadoc/org/apache/geode/management/spi/JavaClientClusterManagementProviderFactory.html
+javadoc/org/apache/geode/management/spi/package-frame.html
+javadoc/org/apache/geode/management/spi/package-summary.html
+javadoc/org/apache/geode/management/spi/package-tree.html
javadoc/org/apache/geode/memcached/GemFireMemcachedServer.Protocol.html
javadoc/org/apache/geode/memcached/GemFireMemcachedServer.html
javadoc/org/apache/geode/memcached/package-frame.html
diff --git a/geode-core/src/distributedTest/java/org/apache/geode/management/api/ClusterManagementServiceRetrievalDUnitTest.java b/geode-core/src/distributedTest/java/org/apache/geode/management/api/ClusterManagementServiceRetrievalDUnitTest.java
new file mode 100644
index 0000000..708da0c
--- /dev/null
+++ b/geode-core/src/distributedTest/java/org/apache/geode/management/api/ClusterManagementServiceRetrievalDUnitTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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.api;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.springframework.web.util.AbstractUriTemplateHandler;
+
+import org.apache.geode.management.client.ClusterManagementServiceProvider;
+import org.apache.geode.management.internal.ClusterManagementClient;
+import org.apache.geode.test.dunit.rules.ClusterStartupRule;
+import org.apache.geode.test.dunit.rules.MemberVM;
+
+public class ClusterManagementServiceRetrievalDUnitTest {
+
+ private static MemberVM locator;
+ private static MemberVM server1;
+
+ @ClassRule
+ public static ClusterStartupRule cluster = new ClusterStartupRule();
+
+ @Test
+ public void retrieveClusterManagementServiceFromServer() {
+ locator = cluster.startLocatorVM(0,
+ x -> x.withHttpService());
+ server1 = cluster.startServerVM(1, locator.getPort());
+
+ final String url = String.format("http://localhost:%d", locator.getHttpPort());
+ server1.invoke(() -> {
+ ClusterManagementClient cms =
+ (ClusterManagementClient) ClusterManagementServiceProvider.getService();
+ assertThat(
+ ((AbstractUriTemplateHandler) cms.getRestTemplate().getUriTemplateHandler()).getBaseUrl())
+ .isEqualTo(url);
+ });
+ }
+
+}
diff --git a/geode-core/src/distributedTest/java/org/apache/geode/management/internal/api/RegionAPIDUnitTest.java b/geode-core/src/distributedTest/java/org/apache/geode/management/internal/api/RegionAPIDUnitTest.java
index 0c2fec2..8633015 100644
--- a/geode-core/src/distributedTest/java/org/apache/geode/management/internal/api/RegionAPIDUnitTest.java
+++ b/geode-core/src/distributedTest/java/org/apache/geode/management/internal/api/RegionAPIDUnitTest.java
@@ -29,6 +29,7 @@ import org.apache.geode.cache.RegionShortcut;
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.management.api.ClusterManagementResult;
import org.apache.geode.test.dunit.rules.ClusterStartupRule;
import org.apache.geode.test.dunit.rules.MemberVM;
import org.apache.geode.test.junit.categories.RegionsTest;
diff --git a/geode-core/src/distributedTest/java/org/apache/geode/management/internal/cli/commands/DescribeMembersCommandDUnitTest.java b/geode-core/src/distributedTest/java/org/apache/geode/management/internal/cli/commands/DescribeMembersCommandDUnitTest.java
index 942fd49..b6c61fb 100644
--- a/geode-core/src/distributedTest/java/org/apache/geode/management/internal/cli/commands/DescribeMembersCommandDUnitTest.java
+++ b/geode-core/src/distributedTest/java/org/apache/geode/management/internal/cli/commands/DescribeMembersCommandDUnitTest.java
@@ -15,6 +15,9 @@
package org.apache.geode.management.internal.cli.commands;
import static org.apache.geode.management.internal.cli.i18n.CliStrings.DESCRIBE_MEMBER;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.Map;
import org.junit.BeforeClass;
import org.junit.ClassRule;
@@ -22,6 +25,7 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.categories.Category;
+import org.apache.geode.management.internal.cli.result.CommandResult;
import org.apache.geode.test.dunit.rules.ClusterStartupRule;
import org.apache.geode.test.dunit.rules.MemberVM;
import org.apache.geode.test.junit.categories.JMXTest;
@@ -58,14 +62,44 @@ public class DescribeMembersCommandDUnitTest {
@Test
public void describeLocator() throws Exception {
gfsh.connectAndVerify(locator);
- gfsh.executeAndAssertThat(DESCRIBE_MEMBER + " --name=locator-0").statusIsSuccess()
- .containsOutput("locator-0").doesNotContainOutput("server-1");
+ CommandResult result = gfsh.executeAndAssertThat(DESCRIBE_MEMBER + " --name=locator-0")
+ .statusIsSuccess()
+ .getCommandResult();
+
+ Map<String, String> memberInfo = result.getMapFromSection("0");
+ assertThat(memberInfo.get("Name")).isEqualTo("locator-0");
+ assertThat(memberInfo.get("Id")).contains("locator-0");
+ assertThat(memberInfo.get("Host")).as("Host").isNotBlank();
+ assertThat(memberInfo.get("PID")).as("PID").isNotBlank();
+ assertThat(memberInfo.get("Used Heap")).as("Used Heap").isNotBlank();
+ assertThat(memberInfo.get("Max Heap")).as("Max Heap").isNotBlank();
+ assertThat(memberInfo.get("Working Dir")).as("Working Dir").isNotBlank();
+ assertThat(memberInfo.get("Log file")).as("Log File").isNotBlank();
+ assertThat(memberInfo.get("Locators")).as("Locators").isNotBlank();
}
@Test
public void describeServer() throws Exception {
gfsh.connectAndVerify(locator);
- gfsh.executeAndAssertThat(DESCRIBE_MEMBER + " --name=server-1").statusIsSuccess()
- .doesNotContainOutput("locator-0").containsOutput("server-1");
+ CommandResult result = gfsh.executeAndAssertThat(DESCRIBE_MEMBER + " --name=server-1")
+ .statusIsSuccess()
+ .getCommandResult();
+
+ Map<String, String> memberInfo = result.getMapFromSection("0");
+ assertThat(memberInfo.get("Name")).isEqualTo("server-1");
+ assertThat(memberInfo.get("Id")).contains("server-1");
+ assertThat(memberInfo.get("Host")).as("Host").isNotBlank();
+ assertThat(memberInfo.get("PID")).as("PID").isNotBlank();
+ assertThat(memberInfo.get("Used Heap")).as("Used Heap").isNotBlank();
+ assertThat(memberInfo.get("Max Heap")).as("Max Heap").isNotBlank();
+ assertThat(memberInfo.get("Working Dir")).as("Working Dir").isNotBlank();
+ assertThat(memberInfo.get("Log file")).as("Log File").isNotBlank();
+ assertThat(memberInfo.get("Locators")).as("Locators").isNotBlank();
+
+ Map<String, String> cacheServerInfo = result.getMapFromSection("1");
+ assertThat(cacheServerInfo.get("Server Bind")).as("Server Bind").isBlank();
+ assertThat(cacheServerInfo.get("Server Port")).as("Server Port").isNotBlank();
+ assertThat(cacheServerInfo.get("Running")).as("Running").isEqualTo("true");
+ assertThat(cacheServerInfo.get("Client Connections")).as("Client Connections").isEqualTo("0");
}
}
diff --git a/geode-core/src/main/java/org/apache/geode/distributed/internal/InternalLocator.java b/geode-core/src/main/java/org/apache/geode/distributed/internal/InternalLocator.java
index 03cf0e6..28bd0bd 100644
--- a/geode-core/src/main/java/org/apache/geode/distributed/internal/InternalLocator.java
+++ b/geode-core/src/main/java/org/apache/geode/distributed/internal/InternalLocator.java
@@ -83,10 +83,10 @@ import org.apache.geode.internal.logging.NullLoggingSession;
import org.apache.geode.internal.net.SocketCreator;
import org.apache.geode.internal.net.SocketCreatorFactory;
import org.apache.geode.internal.statistics.StatisticsConfig;
+import org.apache.geode.management.api.ClusterManagementService;
import org.apache.geode.management.internal.AgentUtil;
import org.apache.geode.management.internal.JmxManagerLocator;
import org.apache.geode.management.internal.JmxManagerLocatorRequest;
-import org.apache.geode.management.internal.api.ClusterManagementService;
import org.apache.geode.management.internal.api.LocatorClusterManagementService;
import org.apache.geode.management.internal.configuration.domain.SharedConfigurationStatus;
import org.apache.geode.management.internal.configuration.handlers.SharedConfigurationStatusRequestHandler;
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/ClusterConfigurationLoader.java b/geode-core/src/main/java/org/apache/geode/internal/cache/ClusterConfigurationLoader.java
index 7780600..3e15b00 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/ClusterConfigurationLoader.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/ClusterConfigurationLoader.java
@@ -272,7 +272,6 @@ public class ClusterConfigurationLoader {
throws ClusterConfigurationNotAvailableException, UnknownHostException {
Set<String> groups = getGroups(groupList);
- GetClusterConfigurationFunction function = new GetClusterConfigurationFunction();
ConfigurationResponse response = null;
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/api/GeodeClusterManagementServiceProviderFactory.java b/geode-core/src/main/java/org/apache/geode/management/internal/api/GeodeClusterManagementServiceProviderFactory.java
new file mode 100644
index 0000000..ce8d9c7
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/api/GeodeClusterManagementServiceProviderFactory.java
@@ -0,0 +1,124 @@
+/*
+ * 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.api;
+
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.logging.log4j.Logger;
+
+import org.apache.geode.annotations.Immutable;
+import org.apache.geode.cache.Cache;
+import org.apache.geode.cache.CacheFactory;
+import org.apache.geode.cache.client.ClientCache;
+import org.apache.geode.cache.client.ClientCacheFactory;
+import org.apache.geode.cache.execute.FunctionException;
+import org.apache.geode.cache.execute.FunctionService;
+import org.apache.geode.cache.execute.ResultCollector;
+import org.apache.geode.distributed.internal.InternalLocator;
+import org.apache.geode.distributed.internal.membership.InternalDistributedMember;
+import org.apache.geode.internal.cache.GemFireCacheImpl;
+import org.apache.geode.internal.logging.LogService;
+import org.apache.geode.management.api.ClusterManagementService;
+import org.apache.geode.management.client.ClusterManagementServiceProvider;
+import org.apache.geode.management.internal.ClusterManagementClient;
+import org.apache.geode.management.internal.cli.domain.MemberInformation;
+import org.apache.geode.management.internal.cli.functions.GetMemberInformationFunction;
+import org.apache.geode.management.spi.ClusterManagementServiceProviderFactory;
+import org.apache.geode.management.spi.JavaClientClusterManagementProviderFactory;
+
+/**
+ * An implementation of {@link ClusterManagementServiceProviderFactory} which can be used in any
+ * context where Geode is running (client, server or locator). It will attempt to determine the
+ * address of the {@code ClusterManagementService} when using the {@code create()} call. Otherwise
+ * an explicit can also be used.
+ */
+public class GeodeClusterManagementServiceProviderFactory extends
+ JavaClientClusterManagementProviderFactory {
+
+ @Immutable
+ private static final GetMemberInformationFunction MEMBER_INFORMATION_FUNCTION =
+ new GetMemberInformationFunction();
+
+ private static final Logger logger = LogService.getLogger();
+
+ @Override
+ public String getContext() {
+ return ClusterManagementServiceProvider.GEODE_CONTEXT;
+ }
+
+ @Override
+ public ClusterManagementService create() throws IllegalStateException {
+ if (InternalLocator.getLocator() != null) {
+ return InternalLocator.getLocator().getClusterManagementService();
+ }
+
+ Cache cache = CacheFactory.getAnyInstance();
+ if (cache != null && cache.isServer()) {
+ GemFireCacheImpl cacheImpl = (GemFireCacheImpl) cache;
+
+ Set<InternalDistributedMember> locatorsWithClusterConfig =
+ cacheImpl.getDistributionManager().getAllHostedLocatorsWithSharedConfiguration()
+ .keySet();
+ String serviceAddress = getHttpServiceAddress(locatorsWithClusterConfig);
+
+ return new ClusterManagementClient(serviceAddress);
+ }
+
+ ClientCache clientCache = ClientCacheFactory.getAnyInstance();
+ if (clientCache != null) {
+ throw new IllegalStateException(
+ "Under construction. To retrieve an instance of ClusterManagementService from a Geode client, please use either create(clusterUrl) or create(requestFactory) methods");
+ }
+ // } catch( CacheClosedException e) {
+ throw new IllegalStateException("ClusterManagementService.create() " +
+ "must be executed on one of locator, server or client cache VMs");
+ }
+
+ private String getHttpServiceAddress(Set<InternalDistributedMember> locators) {
+ for (InternalDistributedMember locator : locators) {
+
+ try {
+ ResultCollector resultCollector =
+ FunctionService.onMember(locator).execute(MEMBER_INFORMATION_FUNCTION);
+ List<MemberInformation> memberInformation =
+ (List<MemberInformation>) resultCollector.getResult();
+ // Is this even possible?
+ if (memberInformation.isEmpty()) {
+ continue;
+ }
+
+ // What address to use
+ String host;
+ if (StringUtils.isNotBlank(memberInformation.get(0).getHttpServiceBindAddress())) {
+ host = memberInformation.get(0).getHttpServiceBindAddress();
+ } else if (StringUtils.isNotBlank(memberInformation.get(0).getServerBindAddress())) {
+ host = memberInformation.get(0).getServerBindAddress();
+ } else {
+ host = memberInformation.get(0).getHost();
+ }
+
+ return String.format("http://%s:%d", host, memberInformation.get(0).getHttpServicePort());
+ } catch (FunctionException e) {
+ logger.warn("Unable to execute GetMemberInformationFunction on " + locator.getId());
+ throw new IllegalStateException(e);
+ }
+ }
+
+ throw new IllegalStateException("Unable to determine ClusterManagementService endpoint");
+ }
+}
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 69aa45e..c439f7c 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
@@ -35,6 +35,8 @@ import org.apache.geode.distributed.ConfigurationPersistenceService;
import org.apache.geode.distributed.DistributedMember;
import org.apache.geode.distributed.internal.DistributionManager;
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.internal.cli.CliUtil;
import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
import org.apache.geode.management.internal.cli.functions.UpdateCacheFunction;
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DescribeMemberCommand.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DescribeMemberCommand.java
index b874f5a..753e159 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DescribeMemberCommand.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DescribeMemberCommand.java
@@ -65,11 +65,6 @@ public class DescribeMemberCommand extends InternalGfshCommand {
CompositeResultData crd = ResultBuilder.createCompositeResultData();
MemberInformation memberInformation = (MemberInformation) obj;
- memberInformation.setName(memberToBeDescribed.getName());
- memberInformation.setId(memberToBeDescribed.getId());
- memberInformation.setHost(memberToBeDescribed.getHost());
- memberInformation.setProcessId("" + memberToBeDescribed.getProcessId());
-
CompositeResultData.SectionResultData section = crd.addSection();
section.addData("Name", memberInformation.getName());
section.addData("Id", memberInformation.getId());
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/domain/MemberInformation.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/domain/MemberInformation.java
index a5e1325..357b976 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/domain/MemberInformation.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/domain/MemberInformation.java
@@ -41,8 +41,9 @@ public class MemberInformation implements Serializable {
private String cacheXmlFilePath;
private String host;
private String processId;
- private String locatorBindAddress;
private int locatorPort;
+ private int httpServicePort;
+ private String httpServiceBindAddress;
private boolean isServer;
private List<CacheServerInfo> cacheServerList;
private int clientCount;
@@ -170,14 +171,6 @@ public class MemberInformation implements Serializable {
this.processId = processId;
}
- public String getLocatorBindAddress() {
- return locatorBindAddress;
- }
-
- public void setLocatorBindAddress(String locatorBindAddress) {
- this.locatorBindAddress = locatorBindAddress;
- }
-
public int getLocatorPort() {
return locatorPort;
}
@@ -186,6 +179,22 @@ public class MemberInformation implements Serializable {
this.locatorPort = locatorPort;
}
+ public int getHttpServicePort() {
+ return httpServicePort;
+ }
+
+ public void setHttpServicePort(int httpServicePort) {
+ this.httpServicePort = httpServicePort;
+ }
+
+ public String getHttpServiceBindAddress() {
+ return httpServiceBindAddress;
+ }
+
+ public void setHttpServiceBindAddress(String httpServiceBindAddress) {
+ this.httpServiceBindAddress = httpServiceBindAddress;
+ }
+
public boolean isServer() {
return isServer;
}
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/GetMemberInformationFunction.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/GetMemberInformationFunction.java
index 999f9eb..88c4ee4 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/GetMemberInformationFunction.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/GetMemberInformationFunction.java
@@ -25,9 +25,11 @@ import org.apache.geode.cache.Cache;
import org.apache.geode.cache.CacheClosedException;
import org.apache.geode.cache.execute.FunctionContext;
import org.apache.geode.cache.server.CacheServer;
+import org.apache.geode.distributed.DistributedMember;
import org.apache.geode.distributed.internal.DistributionConfig;
import org.apache.geode.distributed.internal.InternalDistributedSystem;
import org.apache.geode.internal.cache.CacheClientStatus;
+import org.apache.geode.internal.cache.InternalCache;
import org.apache.geode.internal.cache.execute.InternalFunction;
import org.apache.geode.internal.cache.tier.InternalClientMembership;
import org.apache.geode.internal.cache.tier.sockets.ClientProxyMembershipID;
@@ -41,7 +43,8 @@ import org.apache.geode.management.internal.cli.domain.MemberInformation;
*/
public class GetMemberInformationFunction implements InternalFunction {
- private static final long serialVersionUID = 1L;
+
+ private static final long serialVersionUID = 1404642539058875565L;
@Override
public String getId() {
@@ -73,19 +76,29 @@ public class GetMemberInformationFunction implements InternalFunction {
InternalDistributedSystem system = (InternalDistributedSystem) cache.getDistributedSystem();
DistributionConfig config = system.getConfig();
- String serverBindAddress = config.getServerBindAddress();
- MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
+ DistributedMember member =
+ CliUtil.getDistributedMemberByNameOrId(functionContext.getMemberName(),
+ (InternalCache) functionContext.getCache());
MemberInformation memberInfo = new MemberInformation();
+
+ memberInfo.setName(member.getName());
+ memberInfo.setId(member.getId());
+ memberInfo.setHost(member.getHost());
+ memberInfo.setProcessId("" + member.getProcessId());
+
memberInfo.setGroups(config.getGroups());
memberInfo.setLogFilePath(config.getLogFile().getCanonicalPath());
memberInfo.setStatArchiveFilePath(config.getStatisticArchiveFile().getCanonicalPath());
memberInfo.setWorkingDirPath(System.getProperty("user.dir"));
memberInfo.setCacheXmlFilePath(config.getCacheXmlFile().getCanonicalPath());
memberInfo.setLocators(config.getLocators());
- memberInfo.setServerBindAddress(serverBindAddress);
+ memberInfo.setServerBindAddress(config.getServerBindAddress());
memberInfo.setOffHeapMemorySize(config.getOffHeapMemorySize());
+ memberInfo.setHttpServicePort(config.getHttpServicePort());
+ memberInfo.setHttpServiceBindAddress(config.getHttpServiceBindAddress());
+ MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
MemoryUsage memUsage = memoryMXBean.getHeapMemoryUsage();
memberInfo.setHeapUsage(Long.toString(bytesToMeg(memUsage.getUsed())));
memberInfo.setMaxHeapSize(Long.toString(bytesToMeg(memUsage.getMax())));
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/util/MemberInformation.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/util/MemberInformation.java
deleted file mode 100644
index a59f23a..0000000
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/util/MemberInformation.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for additional information regarding
- * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the License. You may obtain a
- * copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-package org.apache.geode.management.internal.cli.util;
-
-import java.io.Serializable;
-
-
-/***
- * Data class to hold the information of the member Used in describe member command
- *
- */
-public class MemberInformation implements Serializable {
- private static final long serialVersionUID = 1L;
- private String name;
- private String id;
- private String workingDirPath;
- private String groups;
- private String logFilePath;
- private String statArchiveFilePath;
- private String cpuUsage;
- private String serverBindAddress;
- private String locators;
- private String heapUsage;
- private String maxHeapSize;
- private String initHeapSize;
- private String cacheXmlFilePath;
- private String host;
- private String processId;
- private String locatorBindAddress;
- private int locatorPort;
-
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public String getId() {
- return id;
- }
-
- public void setId(String id) {
- this.id = id;
- }
-
- public String getWorkingDirPath() {
- return workingDirPath;
- }
-
- public void setWorkingDirPath(String workingDirPath) {
- this.workingDirPath = workingDirPath;
- }
-
- public String getGroups() {
- return groups;
- }
-
- public void setGroups(String groups) {
- this.groups = groups;
- }
-
- public String getLogFilePath() {
- return logFilePath;
- }
-
- public void setLogFilePath(String logFilePath) {
- this.logFilePath = logFilePath;
- }
-
- public String getStatArchiveFilePath() {
- return statArchiveFilePath;
- }
-
- public void setStatArchiveFilePath(String statArchiveFilePath) {
- this.statArchiveFilePath = statArchiveFilePath;
- }
-
- public String getCpuUsage() {
- return cpuUsage;
- }
-
- public void setCpuUsage(String cpuUsage) {
- this.cpuUsage = cpuUsage;
- }
-
- public String getServerBindAddress() {
- return serverBindAddress;
- }
-
- public void setServerBindAddress(String serverBindAddress) {
- this.serverBindAddress = serverBindAddress;
- }
-
- public String getLocators() {
- return locators;
- }
-
- public void setLocators(String locators) {
- this.locators = locators;
- }
-
- public String getHeapUsage() {
- return heapUsage;
- }
-
- public void setHeapUsage(String heapUsage) {
- this.heapUsage = heapUsage;
- }
-
- public String getMaxHeapSize() {
- return maxHeapSize;
- }
-
- public void setMaxHeapSize(String maxHeapSize) {
- this.maxHeapSize = maxHeapSize;
- }
-
- public String getCacheXmlFilePath() {
- return cacheXmlFilePath;
- }
-
- public void setCacheXmlFilePath(String cacheXmlFilePath) {
- this.cacheXmlFilePath = cacheXmlFilePath;
- }
-
- public String getInitHeapSize() {
- return initHeapSize;
- }
-
- public void setInitHeapSize(String initHeapSize) {
- this.initHeapSize = initHeapSize;
- }
-
- public String getHost() {
- return host;
- }
-
- public void setHost(String host) {
- this.host = host;
- }
-
- public String getProcessId() {
- return processId;
- }
-
- public void setProcessId(String processId) {
- this.processId = processId;
- }
-
- public String getLocatorBindAddress() {
- return locatorBindAddress;
- }
-
- public void setLocatorBindAddress(String locatorBindAddress) {
- this.locatorBindAddress = locatorBindAddress;
- }
-
- public int getLocatorPort() {
- return locatorPort;
- }
-
- public void setLocatorPort(int locatorPort) {
- this.locatorPort = locatorPort;
- }
-}
diff --git a/geode-core/src/main/resources/META-INF/services/org.apache.geode.management.spi.ClusterManagementServiceProviderFactory b/geode-core/src/main/resources/META-INF/services/org.apache.geode.management.spi.ClusterManagementServiceProviderFactory
new file mode 100644
index 0000000..ec5fe49
--- /dev/null
+++ b/geode-core/src/main/resources/META-INF/services/org.apache.geode.management.spi.ClusterManagementServiceProviderFactory
@@ -0,0 +1,16 @@
+#
+# 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.
+#
+
+org.apache.geode.management.internal.api.GeodeClusterManagementServiceProviderFactory
diff --git a/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt b/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt
index d4105c2..7a57f84 100644
--- a/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt
+++ b/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt
@@ -524,7 +524,7 @@ org/apache/geode/management/internal/cli/domain/FixedPartitionAttributesInfo,tru
org/apache/geode/management/internal/cli/domain/IndexDetails,true,-2198907141534201288,fromClause:java/lang/String,indexName:java/lang/String,indexStatisticsDetails:org/apache/geode/management/internal/cli/domain/IndexDetails$IndexStatisticsDetails,indexType:org/apache/geode/cache/query/IndexType,indexedExpression:java/lang/String,isValid:boolean,memberId:java/lang/String,memberName:java/lang/String,projectionAttributes:java/lang/String,regionName:java/lang/String,regionPath:java/lang/String
org/apache/geode/management/internal/cli/domain/IndexDetails$IndexStatisticsDetails,false,numberOfKeys:java/lang/Long,numberOfUpdates:java/lang/Long,numberOfValues:java/lang/Long,totalUpdateTime:java/lang/Long,totalUses:java/lang/Long
org/apache/geode/management/internal/cli/domain/MemberConfigurationInfo,false,cacheAttributes:java/util/Map,cacheServerAttributes:java/util/List,gfePropsRuntime:java/util/Map,gfePropsSetFromFile:java/util/Map,gfePropsSetUsingApi:java/util/Map,gfePropsSetWithDefaults:java/util/Map,jvmInputArguments:java/util/List,pdxAttributes:java/util/Map,systemProperties:java/util/Properties
-org/apache/geode/management/internal/cli/domain/MemberInformation,true,1,cacheServerList:java/util/List,cacheXmlFilePath:java/lang/String,clientCount:int,cpuUsage:double,groups:java/lang/String,heapUsage:java/lang/String,host:java/lang/String,hostedRegions:java/util/Set,id:java/lang/String,initHeapSize:java/lang/String,isServer:boolean,locatorBindAddress:java/lang/String,locatorPort:int,locators:java/lang/String,logFilePath:java/lang/String,maxHeapSize:java/lang/String,name:java/lang/Str [...]
+org/apache/geode/management/internal/cli/domain/MemberInformation,true,1,cacheServerList:java/util/List,cacheXmlFilePath:java/lang/String,clientCount:int,cpuUsage:double,groups:java/lang/String,heapUsage:java/lang/String,host:java/lang/String,hostedRegions:java/util/Set,httpServiceBindAddress:java/lang/String,httpServicePort:int,id:java/lang/String,initHeapSize:java/lang/String,isServer:boolean,locatorPort:int,locators:java/lang/String,logFilePath:java/lang/String,maxHeapSize:java/lang/S [...]
org/apache/geode/management/internal/cli/domain/PartitionAttributesInfo,true,1,colocatedWith:java/lang/String,fpaInfoList:java/util/List,localMaxMemory:int,nonDefaultAttributes:java/util/Map,partitionResolverName:java/lang/String,recoveryDelay:long,redundantCopies:int,startupRecoveryDelay:long,totalNumBuckets:int
org/apache/geode/management/internal/cli/domain/RegionAttributesInfo,true,336184564012988487,asyncEventQueueIDs:java/util/Set,cacheListenerClassNames:java/util/List,cacheLoaderClassName:java/lang/String,cacheWriterClassName:java/lang/String,cloningEnabled:boolean,compressorClassName:java/lang/String,concurrencyChecksEnabled:boolean,concurrencyLevel:int,customExpiryIdleTimeoutClass:java/lang/String,customExpiryTTLClass:java/lang/String,dataPolicy:org/apache/geode/cache/DataPolicy,diskStor [...]
org/apache/geode/management/internal/cli/domain/RegionDescription,true,6461449275798378332,cndEvictionAttributes:java/util/Map,cndPartitionAttributes:java/util/Map,cndRegionAttributes:java/util/Map,dataPolicy:org/apache/geode/cache/DataPolicy,isAccessor:boolean,isLocal:boolean,isPartition:boolean,isPersistent:boolean,isReplicate:boolean,name:java/lang/String,regionDescPerMemberMap:java/util/Map,scope:org/apache/geode/cache/Scope
@@ -569,7 +569,7 @@ org/apache/geode/management/internal/cli/functions/GatewaySenderDestroyFunction,
org/apache/geode/management/internal/cli/functions/GatewaySenderDestroyFunctionArgs,true,3848480256348119530,id:java/lang/String,ifExists:boolean
org/apache/geode/management/internal/cli/functions/GatewaySenderFunctionArgs,true,4636678328980816780,alertThreshold:java/lang/Integer,batchSize:java/lang/Integer,batchTimeInterval:java/lang/Integer,diskStoreName:java/lang/String,diskSynchronous:java/lang/Boolean,dispatcherThreads:java/lang/Integer,enableBatchConflation:java/lang/Boolean,enablePersistence:java/lang/Boolean,gatewayEventFilters:java/util/List,gatewayTransportFilters:java/util/List,id:java/lang/String,manualStart:java/lang/ [...]
org/apache/geode/management/internal/cli/functions/GetMemberConfigInformationFunction,true,1
-org/apache/geode/management/internal/cli/functions/GetMemberInformationFunction,true,1
+org/apache/geode/management/internal/cli/functions/GetMemberInformationFunction,true,1404642539058875565
org/apache/geode/management/internal/cli/functions/GetRegionDescriptionFunction,true,1
org/apache/geode/management/internal/cli/functions/GetRegionsFunction,true,1
org/apache/geode/management/internal/cli/functions/GetStackTracesFunction,true,1
@@ -615,7 +615,6 @@ org/apache/geode/management/internal/cli/util/ExportLogsCacheWriter,false,curren
org/apache/geode/management/internal/cli/util/FixedPartitionAttributesInfo,false,isPrimary:boolean,numBuckets:int,partitionName:java/lang/String
org/apache/geode/management/internal/cli/util/JConsoleNotFoundException,true,-1485615321440327206
org/apache/geode/management/internal/cli/util/LogFilter$LineFilterResult,false
-org/apache/geode/management/internal/cli/util/MemberInformation,true,1,cacheXmlFilePath:java/lang/String,cpuUsage:java/lang/String,groups:java/lang/String,heapUsage:java/lang/String,host:java/lang/String,id:java/lang/String,initHeapSize:java/lang/String,locatorBindAddress:java/lang/String,locatorPort:int,locators:java/lang/String,logFilePath:java/lang/String,maxHeapSize:java/lang/String,name:java/lang/String,processId:java/lang/String,serverBindAddress:java/lang/String,statArchiveFilePat [...]
org/apache/geode/management/internal/cli/util/VisualVmNotFoundException,true,-8491645604829510102
org/apache/geode/management/internal/configuration/domain/SharedConfigurationStatus,false
org/apache/geode/management/internal/configuration/functions/DownloadJarFunction,true,1
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/api/ClusterManagementResultTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/api/ClusterManagementResultTest.java
index d58c919..3473d1e 100644
--- a/geode-core/src/test/java/org/apache/geode/management/internal/api/ClusterManagementResultTest.java
+++ b/geode-core/src/test/java/org/apache/geode/management/internal/api/ClusterManagementResultTest.java
@@ -22,6 +22,8 @@ import static org.assertj.core.api.Assertions.assertThat;
import org.junit.Before;
import org.junit.Test;
+import org.apache.geode.management.api.ClusterManagementResult;
+
public class ClusterManagementResultTest {
private ClusterManagementResult result;
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 f6aa96d..e3dbd39 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
@@ -35,6 +35,7 @@ import org.apache.geode.cache.configuration.RegionConfig;
import org.apache.geode.distributed.ConfigurationPersistenceService;
import org.apache.geode.distributed.DistributedMember;
import org.apache.geode.distributed.internal.DistributionManager;
+import org.apache.geode.management.api.ClusterManagementResult;
import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
import org.apache.geode.management.internal.exceptions.EntityExistsException;
diff --git a/geode-dunit/src/main/java/org/apache/geode/test/dunit/rules/ClusterStartupRule.java b/geode-dunit/src/main/java/org/apache/geode/test/dunit/rules/ClusterStartupRule.java
index cd87286..c842715 100644
--- a/geode-dunit/src/main/java/org/apache/geode/test/dunit/rules/ClusterStartupRule.java
+++ b/geode-dunit/src/main/java/org/apache/geode/test/dunit/rules/ClusterStartupRule.java
@@ -74,6 +74,8 @@ public class ClusterStartupRule implements SerializableTestRule {
public static MemberStarterRule<?> memberStarter;
public static ClientCacheRule clientCacheRule;
+ private boolean skipLocalDistributedSystemCleanup;
+
public static InternalCache getCache() {
if (memberStarter == null) {
return null;
@@ -164,7 +166,9 @@ public class ClusterStartupRule implements SerializableTestRule {
private void after(Description description) throws Throwable {
- MemberStarterRule.disconnectDSIfAny();
+ if (!skipLocalDistributedSystemCleanup) {
+ MemberStarterRule.disconnectDSIfAny();
+ }
// stop all the members in the order of clients, servers and locators
List<VMProvider> vms = new ArrayList<>();
@@ -188,6 +192,19 @@ public class ClusterStartupRule implements SerializableTestRule {
DUnitLauncher.closeAndCheckForSuspects();
}
+ public boolean isSkipLocalDistributedSystemCleanup() {
+ return skipLocalDistributedSystemCleanup;
+ }
+
+ /**
+ * In some weird situations you may not want to do local DS cleanup as that lifecyle is deferred
+ * elsewhere - see {@code LocatorCleanupEventListener} and any test that uses {@code
+ * PlainLocatorContextLoader} or {@code LocatorWithSecurityManagerContextLoader}
+ */
+ public void setSkipLocalDistributedSystemCleanup(boolean skipLocalDistributedSystemCleanup) {
+ this.skipLocalDistributedSystemCleanup = skipLocalDistributedSystemCleanup;
+ }
+
public MemberVM startLocatorVM(int index, int... locatorPort) {
return startLocatorVM(index, x -> x.withConnectionToLocator(locatorPort));
}
@@ -326,8 +343,8 @@ public class ClusterStartupRule implements SerializableTestRule {
/**
* gracefully stop the member/client inside this vm
*
- * if this vm is a server/locator, it stops them and cleans the working dir
- * if this vm is a client, it closes the client cache.
+ * if this vm is a server/locator, it stops them and cleans the working dir if this vm is a
+ * client, it closes the client cache.
*
* @param index vm index
*/
diff --git a/geode-management/build.gradle b/geode-management/build.gradle
index d89f506..1c915dc 100755
--- a/geode-management/build.gradle
+++ b/geode-management/build.gradle
@@ -24,6 +24,7 @@ dependencies {
compile('com.fasterxml.jackson.core:jackson-databind')
compile('com.fasterxml.jackson.core:jackson-core')
compile('com.fasterxml.jackson.core:jackson-annotations')
+ compile('org.springframework:spring-web')
compileOnly(project(':geode-common')) {
exclude module: 'junit'
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 7522af8..27f2e73 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 org.apache.geode.annotations.Experimental;
+import org.apache.geode.management.api.RestfulEndpoint;
/**
@@ -149,7 +150,7 @@ import org.apache.geode.annotations.Experimental;
@XmlType(name = "region-type", namespace = "http://geode.apache.org/schema/cache",
propOrder = {"regionAttributes", "indexes", "entries", "regionElements", "regions"})
@Experimental
-public class RegionConfig implements CacheElement {
+public class RegionConfig implements CacheElement, RestfulEndpoint {
@XmlElement(name = "region-attributes", namespace = "http://geode.apache.org/schema/cache")
protected RegionAttributesType regionAttributes;
@XmlElement(name = "index", namespace = "http://geode.apache.org/schema/cache")
@@ -172,6 +173,11 @@ public class RegionConfig implements CacheElement {
this.type = refid;
}
+ @Override
+ public String getEndpoint() {
+ return "/v2/regions";
+ }
+
public RegionAttributesType getRegionAttributes() {
return regionAttributes;
}
diff --git a/geode-management/src/main/java/org/apache/geode/management/internal/api/ClusterManagementResult.java b/geode-management/src/main/java/org/apache/geode/management/api/ClusterManagementResult.java
similarity index 97%
rename from geode-management/src/main/java/org/apache/geode/management/internal/api/ClusterManagementResult.java
rename to geode-management/src/main/java/org/apache/geode/management/api/ClusterManagementResult.java
index a4b03fb..67bdd2c 100644
--- a/geode-management/src/main/java/org/apache/geode/management/internal/api/ClusterManagementResult.java
+++ b/geode-management/src/main/java/org/apache/geode/management/api/ClusterManagementResult.java
@@ -12,7 +12,7 @@
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
-package org.apache.geode.management.internal.api;
+package org.apache.geode.management.api;
import java.util.HashMap;
import java.util.Map;
diff --git a/geode-management/src/main/java/org/apache/geode/management/internal/api/ClusterManagementService.java b/geode-management/src/main/java/org/apache/geode/management/api/ClusterManagementService.java
similarity index 51%
rename from geode-management/src/main/java/org/apache/geode/management/internal/api/ClusterManagementService.java
rename to geode-management/src/main/java/org/apache/geode/management/api/ClusterManagementService.java
index 1a88592..c87b641 100644
--- a/geode-management/src/main/java/org/apache/geode/management/internal/api/ClusterManagementService.java
+++ b/geode-management/src/main/java/org/apache/geode/management/api/ClusterManagementService.java
@@ -13,28 +13,52 @@
* the License.
*/
-package org.apache.geode.management.internal.api;
+package org.apache.geode.management.api;
import org.apache.geode.annotations.Experimental;
import org.apache.geode.cache.configuration.CacheElement;
/**
- * this is responsible for applying and persisting cache configuration changes on locators
- * and/or servers.
+ * this is responsible for applying and persisting cache configuration changes on locators and/or
+ * servers.
*/
@Experimental
public interface ClusterManagementService {
+
/**
- * This method will try to create the element on all the applicable members in the cluster and
- * persist the configuration in the cluster configuration if persistence is enabled.
+ * This method will create the element on all the applicable members in the cluster and persist
+ * the configuration in the cluster configuration if persistence is enabled.
*
- * @param config this holds the configuration attributes of the element you are trying to create
- * on the cluster
+ * @param config this holds the configuration attributes of the element to be created on the
+ * cluster
+ * @param group the server group to which this config applies
* @throws IllegalArgumentException, NoMemberException, EntityExistsException
+ * @see CacheElement
*/
ClusterManagementResult create(CacheElement config, String group);
+ /**
+ * This method will delete the element on all the applicable members in the cluster and update the
+ * configuration in the cluster configuration if persistence is enabled.
+ *
+ * @param config this holds the configuration attributes of the element to be deleted on the
+ * cluster
+ * @param group the server group to which this config applies
+ * @throws IllegalArgumentException, NoMemberException, EntityExistsException
+ * @see CacheElement
+ */
ClusterManagementResult delete(CacheElement config, String group);
+ /**
+ * This method will update the element on all the applicable members in the cluster and persist
+ * the updated configuration in the cluster configuration if persistence is enabled.
+ *
+ * @param config this holds the configuration attributes of the element to be updated on the
+ * cluster
+ * @param group the server group to which this config applies
+ * @throws IllegalArgumentException, NoMemberException, EntityExistsException
+ * @see CacheElement
+ */
ClusterManagementResult update(CacheElement config, String group);
+
}
diff --git a/geode-management/src/main/java/org/apache/geode/management/internal/api/Status.java b/geode-management/src/main/java/org/apache/geode/management/api/RestfulEndpoint.java
similarity index 59%
copy from geode-management/src/main/java/org/apache/geode/management/internal/api/Status.java
copy to geode-management/src/main/java/org/apache/geode/management/api/RestfulEndpoint.java
index 9a8a5cb..81736df 100644
--- a/geode-management/src/main/java/org/apache/geode/management/internal/api/Status.java
+++ b/geode-management/src/main/java/org/apache/geode/management/api/RestfulEndpoint.java
@@ -12,33 +12,10 @@
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
-package org.apache.geode.management.internal.api;
-public class Status {
- boolean success;
- String message;
+package org.apache.geode.management.api;
- // needed for json deserialization
- public Status() {}
+public interface RestfulEndpoint {
- public Status(boolean success, String message) {
- this.success = success;
- this.message = message;
- }
-
- public boolean isSuccess() {
- return success;
- }
-
- public void setSuccess(boolean success) {
- this.success = success;
- }
-
- public String getMessage() {
- return message;
- }
-
- public void setMessage(String message) {
- this.message = message;
- }
+ String getEndpoint();
}
diff --git a/geode-management/src/main/java/org/apache/geode/management/internal/api/Status.java b/geode-management/src/main/java/org/apache/geode/management/api/Status.java
similarity index 96%
rename from geode-management/src/main/java/org/apache/geode/management/internal/api/Status.java
rename to geode-management/src/main/java/org/apache/geode/management/api/Status.java
index 9a8a5cb..e50c85a 100644
--- a/geode-management/src/main/java/org/apache/geode/management/internal/api/Status.java
+++ b/geode-management/src/main/java/org/apache/geode/management/api/Status.java
@@ -12,7 +12,7 @@
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
-package org.apache.geode.management.internal.api;
+package org.apache.geode.management.api;
public class Status {
boolean success;
diff --git a/geode-management/src/main/java/org/apache/geode/management/client/ClusterManagementServiceProvider.java b/geode-management/src/main/java/org/apache/geode/management/client/ClusterManagementServiceProvider.java
new file mode 100644
index 0000000..c378d46
--- /dev/null
+++ b/geode-management/src/main/java/org/apache/geode/management/client/ClusterManagementServiceProvider.java
@@ -0,0 +1,119 @@
+/*
+ * 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.client;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ServiceLoader;
+
+import org.springframework.http.client.ClientHttpRequestFactory;
+
+import org.apache.geode.annotations.Experimental;
+import org.apache.geode.management.api.ClusterManagementService;
+import org.apache.geode.management.spi.ClusterManagementServiceProviderFactory;
+
+/**
+ * Top-level entry point for client interaction with the {@link ClusterManagementService}. A user
+ * can create an instance of the {@code ClusterManagementService} (CMS for short) in several ways,
+ * each providing various level of control or expediency.
+ * <p/>
+ * Calling {@code getFactory(context)} will return an explicit instance of {@link
+ * ClusterManagementServiceProviderFactory}. Methods on this factory can then be called to create or
+ * retrieve instances of a CMS. New {@link ClusterManagementServiceProvider}s can be written if
+ * specific customization or parameterization is required.
+ * <p/>
+ * A note about contexts. A context is simply a unique string which identifies a specific instance
+ * of CMS that will be returned. Contexts map to the different uses of a CMS. Currently, the
+ * following contexts are provided:
+ * <ul>
+ * <li>
+ * {@code JAVA_CLIENT_CONTEXT} ("java-client") - would be used to retrieve a CMS instance on a pure
+ * Java client - i.e. an app that is not running in the context of a Geode client or server. This
+ * context is available when using the <i>geode-management</i> module.
+ * </li>
+ * <li>{@code GEODE_CONTEXT} ("geode") - would be used to retrieve a CMS instance
+ * from a JVM where either a {@code Cache} or {@code ClientCache} exists. This context is available
+ * when using the <i>geode-core</i> module.
+ * </li>
+ * </ul>
+ * If the URL of the Cluster Management Service is known, the {@code getService(url)} method can be
+ * called. This implicitly uses the {@code JAVA_CLIENT_CONTEXT}. For further control the CMS can be
+ * configured with a {@link ClientHttpRequestFactory} by calling {@code
+ * getService(requestFactory)}.
+ * <p/>
+ * Finally, the simplest way to create a CMS instance is simply to call {@code getService()}. This
+ * method will attempt to infer the context and use an appropriate service provider to create a CMS
+ * instance.
+ */
+@Experimental
+public class ClusterManagementServiceProvider {
+
+ public static final String JAVA_CLIENT_CONTEXT = "java-client";
+ public static final String GEODE_CONTEXT = "geode";
+
+ private static List<ClusterManagementServiceProviderFactory> providerFactories = null;
+
+ public static ClusterManagementService getService() {
+ ClusterManagementServiceProviderFactory factory;
+ try {
+ factory = getFactory(GEODE_CONTEXT);
+ try {
+ ClusterManagementService cms = factory.create();
+ return cms;
+ } catch (IllegalStateException ex) {
+ // Ignored
+ }
+ } catch (IllegalArgumentException iex) {
+ // Ig
+ } catch (Exception iex) {
+ iex.printStackTrace();
+ }
+
+ throw new IllegalStateException(
+ "Unable to get ClusterManagementService using any of the default contexts");
+ }
+
+ public static ClusterManagementService getService(String clusterUrl) {
+ return getFactory(JAVA_CLIENT_CONTEXT).create(clusterUrl);
+ }
+
+ public static ClusterManagementService getService(ClientHttpRequestFactory requestFactory) {
+ return getFactory(JAVA_CLIENT_CONTEXT).create(requestFactory);
+ }
+
+ public static synchronized ClusterManagementServiceProviderFactory getFactory(String context) {
+ if (providerFactories == null) {
+ loadClusterManagementServiceProviderFactories();
+ }
+
+ ClusterManagementServiceProviderFactory factory = providerFactories.stream()
+ .filter(x -> x.getContext().equalsIgnoreCase(context))
+ .findFirst()
+ .orElseThrow(
+ () -> new IllegalArgumentException("Did not find provider for context: " + context));
+
+ return factory;
+ }
+
+ private static void loadClusterManagementServiceProviderFactories() {
+ providerFactories = new ArrayList<>();
+
+ for (ClusterManagementServiceProviderFactory factory : ServiceLoader
+ .load(ClusterManagementServiceProviderFactory.class)) {
+ providerFactories.add(factory);
+ }
+ }
+}
diff --git a/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/StandardRequestPostProcessor.java b/geode-management/src/main/java/org/apache/geode/management/client/RestTemplateResponseErrorHandler.java
similarity index 56%
copy from geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/StandardRequestPostProcessor.java
copy to geode-management/src/main/java/org/apache/geode/management/client/RestTemplateResponseErrorHandler.java
index 92a3d5f..6ae39c0 100644
--- a/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/StandardRequestPostProcessor.java
+++ b/geode-management/src/main/java/org/apache/geode/management/client/RestTemplateResponseErrorHandler.java
@@ -13,18 +13,23 @@
* the License.
*/
-package org.apache.geode.management.internal.rest;
+package org.apache.geode.management.client;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.MediaType;
-import org.springframework.mock.web.MockHttpServletRequest;
-import org.springframework.test.web.servlet.request.RequestPostProcessor;
+import java.io.IOException;
+
+import org.springframework.http.client.ClientHttpResponse;
+import org.springframework.web.client.ResponseErrorHandler;
+
+public class RestTemplateResponseErrorHandler implements ResponseErrorHandler {
+ @Override
+ public boolean hasError(ClientHttpResponse response) throws IOException {
+ // All errors should be handled by the server and be returned as part of the
+ // ResponseEntity<ClusterManagementResult>.
+ return false;
+ }
-class StandardRequestPostProcessor implements RequestPostProcessor {
@Override
- public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) {
- request.addHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON);
- request.addHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
- return request;
+ public void handleError(ClientHttpResponse response) throws IOException {
+ // this should not be necessary
}
}
diff --git a/geode-management/src/main/java/org/apache/geode/management/internal/ClusterManagementClient.java b/geode-management/src/main/java/org/apache/geode/management/internal/ClusterManagementClient.java
new file mode 100644
index 0000000..5eeb647
--- /dev/null
+++ b/geode-management/src/main/java/org/apache/geode/management/internal/ClusterManagementClient.java
@@ -0,0 +1,105 @@
+/*
+ * 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;
+
+import org.springframework.http.ResponseEntity;
+import org.springframework.http.client.ClientHttpRequestFactory;
+import org.springframework.web.client.ResponseErrorHandler;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.util.DefaultUriTemplateHandler;
+import sun.reflect.generics.reflectiveObjects.NotImplementedException;
+
+import org.apache.geode.annotations.Experimental;
+import org.apache.geode.cache.configuration.CacheElement;
+import org.apache.geode.management.api.ClusterManagementResult;
+import org.apache.geode.management.api.ClusterManagementService;
+import org.apache.geode.management.api.RestfulEndpoint;
+import org.apache.geode.management.client.RestTemplateResponseErrorHandler;
+
+/**
+ * Implementation of {@link ClusterManagementService} interface which represents the cluster
+ * management service as used by a Java client.
+ * <p/>
+ * In order to manipulate Geode components (Regions, etc.) clients can construct instances of {@link
+ * CacheElement}s and call the corresponding {@link ClusterManagementClient#create(CacheElement,
+ * String)}, {@link ClusterManagementClient#delete(CacheElement, String)} or {@link
+ * ClusterManagementClient#update(CacheElement, String)} method. The returned {@link
+ * ClusterManagementResult} will contain all necessary information about the outcome of the call.
+ * This will include the result of persisting the config as part of the cluster configuration as
+ * well as creating the actual component in the cluster.
+ * <p/>
+ * All create calls are idempotent and will not return an error if the desired component already
+ * exists.
+ */
+@Experimental
+public class ClusterManagementClient implements ClusterManagementService {
+
+ private static final ResponseErrorHandler DEFAULT_ERROR_HANDLER =
+ new RestTemplateResponseErrorHandler();
+
+ private final RestTemplate restTemplate;
+
+ private ClusterManagementClient() {
+ restTemplate = new RestTemplate();
+ restTemplate.setErrorHandler(DEFAULT_ERROR_HANDLER);
+ }
+
+ public ClusterManagementClient(ClientHttpRequestFactory requestFactory) {
+ this();
+ this.restTemplate.setRequestFactory(requestFactory);
+ }
+
+ public ClusterManagementClient(String clusterUrl) {
+ this();
+ DefaultUriTemplateHandler templateHandler = new DefaultUriTemplateHandler();
+ templateHandler.setBaseUrl(clusterUrl);
+ restTemplate.setUriTemplateHandler(templateHandler);
+ }
+
+ @Override
+ public ClusterManagementResult create(CacheElement config, String group) {
+ String endPoint = getEndpoint(config);
+
+ ResponseEntity<ClusterManagementResult> result = restTemplate.postForEntity(endPoint, config,
+ ClusterManagementResult.class);
+
+ return result.getBody();
+ }
+
+ @Override
+ public ClusterManagementResult delete(CacheElement config, String group) {
+ throw new NotImplementedException();
+ }
+
+ @Override
+ public ClusterManagementResult update(CacheElement config, String group) {
+ throw new NotImplementedException();
+ }
+
+ public RestTemplate getRestTemplate() {
+ return restTemplate;
+ }
+
+ private String getEndpoint(CacheElement config) {
+ if (!(config instanceof RestfulEndpoint)) {
+ throw new IllegalArgumentException(
+ String.format("The config type %s does not have a RESTful endpoint defined",
+ config.getClass().getName()));
+ }
+
+ return ((RestfulEndpoint) config).getEndpoint();
+ }
+}
diff --git a/geode-management/src/main/java/org/apache/geode/management/spi/ClusterManagementServiceProviderFactory.java b/geode-management/src/main/java/org/apache/geode/management/spi/ClusterManagementServiceProviderFactory.java
new file mode 100644
index 0000000..44136f2
--- /dev/null
+++ b/geode-management/src/main/java/org/apache/geode/management/spi/ClusterManagementServiceProviderFactory.java
@@ -0,0 +1,60 @@
+/*
+ * 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.spi;
+
+import org.springframework.http.client.ClientHttpRequestFactory;
+
+import org.apache.geode.management.api.ClusterManagementService;
+
+/**
+ * A Server Provider interface which should be implemented to create instances of {@link
+ * ClusterManagementService} for a given context.
+ */
+public interface ClusterManagementServiceProviderFactory {
+
+ /**
+ * Returns a list of the contexts which this provider supports.
+ *
+ * @return a list of names of supported contexts of this factory
+ */
+ String getContext();
+
+ /**
+ * Create a {@code ClusterManagementService} instance. Throws an {@code IllegalStateException}
+ * if the instance cannot be created. This method would typically be used by an implementation
+ * that is able to infer the correct Cluster Management endpoint URL to use.
+ *
+ * @return an instance of the {@code ClusterManagementService}
+ */
+ ClusterManagementService create() throws IllegalStateException;
+
+ /**
+ * Create a {@code ClusterManagementService} that will use the given URL.
+ *
+ * @param clusterUrl the URL to conect to
+ * @return an instance of {@code ClusterManagementService}
+ */
+ ClusterManagementService create(String clusterUrl);
+
+ /**
+ * Create a {@code ClusterManagementService} that will use the given {@link
+ * ClientHttpRequestFactory} to establish connections with the Cluster Management endpoint.
+ *
+ * @param requestFactory the {@code ClientHttpRequestFactory} to use for new connections.
+ * @return an instance of {@code ClusterManagementService}
+ */
+ ClusterManagementService create(ClientHttpRequestFactory requestFactory);
+}
diff --git a/geode-management/src/main/java/org/apache/geode/management/spi/JavaClientClusterManagementProviderFactory.java b/geode-management/src/main/java/org/apache/geode/management/spi/JavaClientClusterManagementProviderFactory.java
new file mode 100644
index 0000000..666ce51
--- /dev/null
+++ b/geode-management/src/main/java/org/apache/geode/management/spi/JavaClientClusterManagementProviderFactory.java
@@ -0,0 +1,54 @@
+/*
+ * 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.spi;
+
+import org.springframework.http.client.ClientHttpRequestFactory;
+
+import org.apache.geode.management.api.ClusterManagementService;
+import org.apache.geode.management.client.ClusterManagementServiceProvider;
+import org.apache.geode.management.internal.ClusterManagementClient;
+
+/**
+ * A Service Provider factory which will be used to create {@link ClusterManagementService}
+ * instances from pure Java code - i.e. the Cluster Management endpoint URL <b>cannot</b> be
+ * inferred from the implied runtime context but needs to be specifically configured using a given
+ * URL or {@code ClientHttpRequestFactory}.
+ */
+public class JavaClientClusterManagementProviderFactory
+ implements ClusterManagementServiceProviderFactory {
+
+ @Override
+ public String getContext() {
+ return ClusterManagementServiceProvider.JAVA_CLIENT_CONTEXT;
+ }
+
+ @Override
+ public ClusterManagementService create() throws IllegalArgumentException {
+ throw new IllegalArgumentException(String.format(
+ "When using a %s context, you must call create(String) or create(ClientHttpRequestFactory)",
+ ClusterManagementServiceProvider.JAVA_CLIENT_CONTEXT));
+ }
+
+ @Override
+ public ClusterManagementService create(String clusterUrl) {
+ return new ClusterManagementClient(clusterUrl);
+ }
+
+ @Override
+ public ClusterManagementService create(ClientHttpRequestFactory requestFactory) {
+ return new ClusterManagementClient(requestFactory);
+ }
+}
diff --git a/geode-management/src/main/resources/META-INF/services/org.apache.geode.management.spi.ClusterManagementServiceProviderFactory b/geode-management/src/main/resources/META-INF/services/org.apache.geode.management.spi.ClusterManagementServiceProviderFactory
new file mode 100644
index 0000000..5863340
--- /dev/null
+++ b/geode-management/src/main/resources/META-INF/services/org.apache.geode.management.spi.ClusterManagementServiceProviderFactory
@@ -0,0 +1,17 @@
+#
+# 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.
+#
+
+
+org.apache.geode.management.spi.JavaClientClusterManagementProviderFactory
diff --git a/geode-management/src/test/resources/expected-pom.xml b/geode-management/src/test/resources/expected-pom.xml
index 14ab573..66e0853 100644
--- a/geode-management/src/test/resources/expected-pom.xml
+++ b/geode-management/src/test/resources/expected-pom.xml
@@ -55,6 +55,11 @@
<artifactId>jackson-annotations</artifactId>
<scope>compile</scope>
</dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-web</artifactId>
+ <scope>compile</scope>
+ </dependency>
</dependencies>
<dependencyManagement>
<dependencies>
diff --git a/geode-web-management/build.gradle b/geode-web-management/build.gradle
index f3868c8..46ab5f6 100644
--- a/geode-web-management/build.gradle
+++ b/geode-web-management/build.gradle
@@ -124,6 +124,10 @@ dependencies {
distributedTestCompile(project(':geode-dunit')) {
exclude module: 'geode-core'
}
+
+ distributedTestRuntimeOnly('org.apache.logging.log4j:log4j-slf4j-impl') {
+ exclude module: 'slf4j-api'
+ }
}
war {
diff --git a/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/PlainLocatorContextLoader.java b/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/BaseLocatorContextLoader.java
similarity index 76%
copy from geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/PlainLocatorContextLoader.java
copy to geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/BaseLocatorContextLoader.java
index e2a28b7..fc27eec 100644
--- a/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/PlainLocatorContextLoader.java
+++ b/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/BaseLocatorContextLoader.java
@@ -17,6 +17,7 @@ package org.apache.geode.management.internal.rest;
import org.springframework.test.context.web.GenericXmlWebContextLoader;
import org.springframework.test.context.web.WebMergedContextConfiguration;
+import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.GenericWebApplicationContext;
import org.apache.geode.internal.cache.HttpService;
@@ -28,24 +29,26 @@ import org.apache.geode.test.junit.rules.LocatorStarterRule;
* ServletContext so that it can be retrieved and cleaned up in the LocatorCleanupEventListener.
* There has to be a better way...
*/
-class PlainLocatorContextLoader extends GenericXmlWebContextLoader {
+public abstract class BaseLocatorContextLoader extends GenericXmlWebContextLoader {
- private LocatorStarterRule locator = new LocatorStarterRule()
- .withAutoStart();
+ public abstract LocatorStarterRule getLocator();
@Override
protected void loadBeanDefinitions(GenericWebApplicationContext context,
WebMergedContextConfiguration webMergedConfig) {
- locator.before();
+ getLocator().before();
super.loadBeanDefinitions(context, webMergedConfig);
context.getServletContext().setAttribute(HttpService.SECURITY_SERVICE_SERVLET_CONTEXT_PARAM,
- locator.getCache().getSecurityService());
+ getLocator().getCache().getSecurityService());
context.getServletContext().setAttribute(HttpService.CLUSTER_MANAGEMENT_SERVICE_CONTEXT_PARAM,
- locator.getLocator().getClusterManagementService());
+ getLocator().getLocator().getClusterManagementService());
- context.getServletContext().setAttribute("locator", locator);
+ context.getServletContext().setAttribute("locator", getLocator());
}
+ public static LocatorStarterRule getLocatorFromContext(WebApplicationContext context) {
+ return (LocatorStarterRule) context.getServletContext().getAttribute("locator");
+ }
}
diff --git a/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/LocatorWithSecurityManagerContextLoader.java b/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/LocatorWithSecurityManagerContextLoader.java
index 4f03a2a..696e16a 100644
--- a/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/LocatorWithSecurityManagerContextLoader.java
+++ b/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/LocatorWithSecurityManagerContextLoader.java
@@ -15,33 +15,22 @@
package org.apache.geode.management.internal.rest;
-import org.springframework.test.context.web.GenericXmlWebContextLoader;
-import org.springframework.test.context.web.WebMergedContextConfiguration;
-import org.springframework.web.context.support.GenericWebApplicationContext;
-
-import org.apache.geode.internal.cache.HttpService;
import org.apache.geode.security.SimpleTestSecurityManager;
import org.apache.geode.test.junit.rules.LocatorStarterRule;
-class LocatorWithSecurityManagerContextLoader extends GenericXmlWebContextLoader {
-
- private LocatorStarterRule locator = new LocatorStarterRule()
- .withSecurityManager(SimpleTestSecurityManager.class)
- .withAutoStart();
-
- @Override
- protected void loadBeanDefinitions(GenericWebApplicationContext context,
- WebMergedContextConfiguration webMergedConfig) {
+public class LocatorWithSecurityManagerContextLoader extends BaseLocatorContextLoader {
- locator.before();
+ private final LocatorStarterRule locator;
- super.loadBeanDefinitions(context, webMergedConfig);
- context.getServletContext().setAttribute(HttpService.SECURITY_SERVICE_SERVLET_CONTEXT_PARAM,
- locator.getCache().getSecurityService());
- context.getServletContext().setAttribute(HttpService.CLUSTER_MANAGEMENT_SERVICE_CONTEXT_PARAM,
- locator.getLocator().getClusterManagementService());
+ public LocatorWithSecurityManagerContextLoader() {
+ locator = new LocatorStarterRule()
+ .withSecurityManager(SimpleTestSecurityManager.class)
+ .withAutoStart();
+ }
- context.getServletContext().setAttribute("locator", locator);
+ @Override
+ public LocatorStarterRule getLocator() {
+ return locator;
}
}
diff --git a/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/PlainLocatorContextLoader.java b/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/PlainLocatorContextLoader.java
index e2a28b7..adedec8 100644
--- a/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/PlainLocatorContextLoader.java
+++ b/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/PlainLocatorContextLoader.java
@@ -15,37 +15,19 @@
package org.apache.geode.management.internal.rest;
-import org.springframework.test.context.web.GenericXmlWebContextLoader;
-import org.springframework.test.context.web.WebMergedContextConfiguration;
-import org.springframework.web.context.support.GenericWebApplicationContext;
-
-import org.apache.geode.internal.cache.HttpService;
import org.apache.geode.test.junit.rules.LocatorStarterRule;
-/**
- * This is quite horrible. In particular we're trying to link the lifecycle of the
- * LocatorStarterRule and Spring's application context. The locator is injected into the
- * ServletContext so that it can be retrieved and cleaned up in the LocatorCleanupEventListener.
- * There has to be a better way...
- */
-class PlainLocatorContextLoader extends GenericXmlWebContextLoader {
-
- private LocatorStarterRule locator = new LocatorStarterRule()
- .withAutoStart();
-
- @Override
- protected void loadBeanDefinitions(GenericWebApplicationContext context,
- WebMergedContextConfiguration webMergedConfig) {
-
- locator.before();
+public class PlainLocatorContextLoader extends BaseLocatorContextLoader {
- super.loadBeanDefinitions(context, webMergedConfig);
- context.getServletContext().setAttribute(HttpService.SECURITY_SERVICE_SERVLET_CONTEXT_PARAM,
- locator.getCache().getSecurityService());
- context.getServletContext().setAttribute(HttpService.CLUSTER_MANAGEMENT_SERVICE_CONTEXT_PARAM,
- locator.getLocator().getClusterManagementService());
+ private final LocatorStarterRule locator;
- context.getServletContext().setAttribute("locator", locator);
+ public PlainLocatorContextLoader() {
+ locator = new LocatorStarterRule()
+ .withAutoStart();
}
+ @Override
+ public LocatorStarterRule getLocator() {
+ return locator;
+ }
}
diff --git a/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/StandardRequestPostProcessor.java b/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/StandardRequestPostProcessor.java
index 92a3d5f..b1282f0 100644
--- a/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/StandardRequestPostProcessor.java
+++ b/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/StandardRequestPostProcessor.java
@@ -20,7 +20,7 @@ import org.springframework.http.MediaType;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.test.web.servlet.request.RequestPostProcessor;
-class StandardRequestPostProcessor implements RequestPostProcessor {
+public class StandardRequestPostProcessor implements RequestPostProcessor {
@Override
public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) {
request.addHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON);
diff --git a/geode-web-management/src/distributedTest/java/org/apache/geode/management/client/ClusterManagementClientDUnitTest.java b/geode-web-management/src/distributedTest/java/org/apache/geode/management/client/ClusterManagementClientDUnitTest.java
new file mode 100644
index 0000000..06a6f4f
--- /dev/null
+++ b/geode-web-management/src/distributedTest/java/org/apache/geode/management/client/ClusterManagementClientDUnitTest.java
@@ -0,0 +1,87 @@
+/*
+ * 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.client;
+
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.test.context.support.WithMockUser;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.context.web.WebAppConfiguration;
+import org.springframework.test.web.client.MockMvcClientHttpRequestFactory;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.web.client.ResponseErrorHandler;
+import org.springframework.web.context.WebApplicationContext;
+
+import org.apache.geode.cache.configuration.RegionConfig;
+import org.apache.geode.management.api.ClusterManagementResult;
+import org.apache.geode.management.api.ClusterManagementService;
+import org.apache.geode.management.internal.rest.BaseLocatorContextLoader;
+import org.apache.geode.management.internal.rest.PlainLocatorContextLoader;
+import org.apache.geode.test.dunit.rules.ClusterStartupRule;
+import org.apache.geode.test.dunit.rules.MemberVM;
+
+@RunWith(SpringRunner.class)
+@ContextConfiguration(locations = {"classpath*:WEB-INF/geode-management-servlet.xml"},
+ loader = PlainLocatorContextLoader.class)
+@WebAppConfiguration
+public class ClusterManagementClientDUnitTest {
+ private static final ResponseErrorHandler ERROR_HANDLER = new RestTemplateResponseErrorHandler();
+
+ @Autowired
+ private WebApplicationContext webApplicationContext;
+
+ @Rule
+ public ClusterStartupRule cluster = new ClusterStartupRule(1);
+
+ private MemberVM server1;
+ private ClusterManagementService client;
+
+ @Before
+ public void before() {
+ cluster.setSkipLocalDistributedSystemCleanup(true);
+ MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
+ .build();
+ MockMvcClientHttpRequestFactory requestFactory = new MockMvcClientHttpRequestFactory(mockMvc);
+ client = ClusterManagementServiceProvider.getService(requestFactory);
+
+ server1 = cluster.startServerVM(0,
+ BaseLocatorContextLoader.getLocatorFromContext(webApplicationContext).getPort());
+ }
+
+ @Test
+ @WithMockUser
+ public void createRegion() {
+ RegionConfig region = new RegionConfig();
+ region.setName("customer");
+ region.setType("REPLICATE");
+
+ ClusterManagementResult result = client.create(region, "");
+
+ // This all fails in light of running this test repeatedly as a stress test. Until we introduce
+ // idempotency and/or the ability to call client.delete we can't do this. But it will get fixed
+ // assertThat(result.isSuccessful()).isTrue();
+
+ // Not implemented yet
+ // result = client.delete(region, "");
+ // assertThat(result.isSuccessful()).isTrue();
+ }
+}
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 5df6a11..14ef4a2 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
@@ -44,8 +44,7 @@ import org.apache.geode.cache.configuration.RegionConfig;
@WebAppConfiguration
public class RegionManagementIntegrationTest {
- static RequestPostProcessor POST_PROCESSOR =
- new StandardRequestPostProcessor();
+ static RequestPostProcessor POST_PROCESSOR = new StandardRequestPostProcessor();
@Autowired
private WebApplicationContext webApplicationContext;
diff --git a/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/controllers/ManagementControllerAdvice.java b/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/controllers/ManagementControllerAdvice.java
index dba5499..9e8265d 100644
--- a/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/controllers/ManagementControllerAdvice.java
+++ b/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/controllers/ManagementControllerAdvice.java
@@ -26,7 +26,7 @@ import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.apache.geode.internal.logging.LogService;
-import org.apache.geode.management.internal.api.ClusterManagementResult;
+import org.apache.geode.management.api.ClusterManagementResult;
import org.apache.geode.management.internal.exceptions.EntityExistsException;
import org.apache.geode.security.AuthenticationFailedException;
import org.apache.geode.security.NotAuthorizedException;
@@ -50,7 +50,7 @@ public class ManagementControllerAdvice {
}
@ExceptionHandler({AuthenticationFailedException.class, AuthenticationException.class})
- public ResponseEntity<ClusterManagementResult> unauthorized(AuthenticationFailedException e) {
+ public ResponseEntity<ClusterManagementResult> unauthorized(Exception e) {
return new ResponseEntity<>(new ClusterManagementResult(false, e.getMessage()),
HttpStatus.UNAUTHORIZED);
}
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 f1ebae2..e59c0a1 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
@@ -26,7 +26,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.apache.geode.cache.configuration.RegionConfig;
-import org.apache.geode.management.internal.api.ClusterManagementResult;
+import org.apache.geode.management.api.ClusterManagementResult;
@Controller("regionManagement")
@RequestMapping(MANAGEMENT_API_VERSION)
diff --git a/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/security/RestSecurityConfiguration.java b/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/security/RestSecurityConfiguration.java
index 2bc6bc6..1edbb79 100644
--- a/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/security/RestSecurityConfiguration.java
+++ b/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/security/RestSecurityConfiguration.java
@@ -37,7 +37,7 @@ import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
-import org.apache.geode.management.internal.api.ClusterManagementResult;
+import org.apache.geode.management.api.ClusterManagementResult;
@Configuration
@EnableWebSecurity