| /* |
| * 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.rest; |
| |
| import static org.apache.geode.test.util.ResourceUtils.createTempFileFromResource; |
| import static org.assertj.core.api.Assertions.assertThat; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.nio.file.Path; |
| import java.nio.file.Paths; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.List; |
| import java.util.concurrent.TimeUnit; |
| import java.util.stream.Collectors; |
| |
| import org.junit.BeforeClass; |
| import org.junit.Rule; |
| import org.junit.Test; |
| import org.junit.rules.TemporaryFolder; |
| import org.junit.runner.RunWith; |
| import org.junit.runners.Parameterized; |
| import org.junit.runners.Parameterized.Parameter; |
| import org.junit.runners.Parameterized.Parameters; |
| import org.junit.runners.Parameterized.UseParametersRunnerFactory; |
| |
| import org.apache.geode.internal.AvailablePortHelper; |
| import org.apache.geode.test.compiler.JarBuilder; |
| import org.apache.geode.test.junit.rules.gfsh.GfshExecution; |
| import org.apache.geode.test.junit.rules.gfsh.GfshRule; |
| import org.apache.geode.test.junit.rules.gfsh.GfshScript; |
| import org.apache.geode.test.junit.rules.gfsh.internal.ProcessLogger; |
| import org.apache.geode.test.junit.runners.CategoryWithParameterizedRunnerFactory; |
| |
| @RunWith(Parameterized.class) |
| @UseParametersRunnerFactory(CategoryWithParameterizedRunnerFactory.class) |
| public class StandaloneClientManagementAPIAcceptanceTest { |
| |
| @Rule |
| public GfshRule gfsh = new GfshRule(); |
| |
| @Rule |
| public TemporaryFolder tempDir = new TemporaryFolder(); |
| |
| private static String trustStorePath; |
| |
| @Parameter |
| public Boolean useSsl; |
| |
| @Parameters |
| public static Collection<Boolean> data() { |
| return Arrays.asList(true, false); |
| } |
| |
| @BeforeClass |
| public static void beforeClass() { |
| /* |
| * This file was generated with: |
| * keytool -genkey -dname "CN=localhost" -alias self -validity 3650 -keyalg EC \ |
| * -keystore trusted.keystore -keypass password -storepass password \ |
| * -ext san=ip:127.0.0.1,dns:localhost -storetype jks |
| */ |
| trustStorePath = |
| createTempFileFromResource(StandaloneClientManagementAPIAcceptanceTest.class, |
| "/ssl/trusted.keystore").getAbsolutePath(); |
| assertThat(trustStorePath).as("java file resource not found").isNotBlank(); |
| } |
| |
| @Test |
| public void clientCreatesRegionUsingClusterManagementService() throws Exception { |
| JarBuilder jarBuilder = new JarBuilder(); |
| String filePath = |
| createTempFileFromResource(this.getClass(), "/ManagementClientCreateRegion.java") |
| .getAbsolutePath(); |
| assertThat(filePath).as("java file resource not found").isNotBlank(); |
| |
| File outputJar = new File(tempDir.getRoot(), "output.jar"); |
| jarBuilder.buildJar(outputJar, new File(filePath)); |
| |
| int[] availablePorts = AvailablePortHelper.getRandomAvailableTCPPorts(2); |
| int locatorPort = availablePorts[0]; |
| int httpPort = availablePorts[1]; |
| GfshExecution startCluster = |
| GfshScript.of(String.format("start locator --port=%d --J=-Dgemfire.http-service-port=%d %s", |
| locatorPort, |
| httpPort, |
| getSslParameters()), |
| String.format("start server --locators=localhost[%d] --server-port=0", locatorPort)) |
| .withName("startCluster").execute(gfsh); |
| |
| |
| assertThat(startCluster.getProcess().exitValue()) |
| .as("Cluster did not start correctly").isEqualTo(0); |
| |
| Process process = launchClientProcess(outputJar, httpPort); |
| |
| boolean exited = process.waitFor(30, TimeUnit.SECONDS); |
| assertThat(exited).as("Process did not exit within 10 seconds").isTrue(); |
| assertThat(process.exitValue()).as("Process did not exit with 0 return code").isEqualTo(0); |
| |
| GfshExecution listRegionsResult = GfshScript |
| .of(String.format("connect --locator=localhost[%d]", locatorPort), "list regions") |
| .withName("listRegions").execute(gfsh); |
| assertThat(listRegionsResult.getOutputText()).contains("REGION1"); |
| } |
| |
| private Process launchClientProcess(File outputJar, int httpPort) throws IOException { |
| Path javaBin = Paths.get(System.getProperty("java.home"), "bin", "java"); |
| |
| ProcessBuilder pBuilder = new ProcessBuilder(); |
| pBuilder.directory(tempDir.newFolder()); |
| |
| StringBuilder classPath = new StringBuilder(); |
| for (String module : Arrays.asList( |
| "commons-logging", |
| "commons-lang3", |
| "geode-common", |
| "geode-management", |
| "jackson-annotations", |
| "jackson-core", |
| "jackson-databind", |
| "httpclient", |
| "httpcore", |
| "spring-beans", |
| "spring-core", |
| "spring-web")) { |
| classPath.append(getJarOrClassesForModule(module)); |
| classPath.append(File.pathSeparator); |
| } |
| |
| classPath.append(File.pathSeparator); |
| classPath.append(outputJar.getAbsolutePath()); |
| |
| List<String> command = new ArrayList<>(); |
| command.add(javaBin.toString()); |
| |
| if (useSsl) { |
| command.add("-Djavax.net.ssl.keyStore=" + trustStorePath); |
| command.add("-Djavax.net.ssl.keyStorePassword=password"); |
| command.add("-Djavax.net.ssl.trustStore=" + trustStorePath); |
| command.add("-Djavax.net.ssl.trustStorePassword=password"); |
| } |
| |
| command.add("-classpath"); |
| command.add(classPath.toString()); |
| command.add("ManagementClientCreateRegion"); |
| command.add("REGION1"); |
| command.add(useSsl.toString()); |
| command.add("" + httpPort); |
| |
| pBuilder.command(command); |
| |
| System.out.format("Launching client command: %s\n", command); |
| |
| Process process = pBuilder.start(); |
| new ProcessLogger(process, "clientCreateRegion"); |
| return process; |
| } |
| |
| private String getSslParameters() { |
| if (useSsl) { |
| return String.format(" --J=-Dgemfire.ssl-keystore=%1$s" |
| + " --J=-Dgemfire.ssl-keystore-password=%2$s" |
| + " --J=-Dgemfire.ssl-truststore=%1$s" |
| + " --J=-Dgemfire.ssl-truststore-password=%2$s" |
| + " --J=-Dgemfire.ssl-enabled-components=web", |
| trustStorePath, "password"); |
| } |
| |
| return ""; |
| } |
| |
| private String getJarOrClassesForModule(String module) { |
| String classPath = Arrays.stream(System.getProperty("java.class.path") |
| .split(File.pathSeparator)) |
| .filter(x -> x.contains(module) |
| && (x.endsWith("/classes") || x.endsWith("/classes/java/main") |
| || x.endsWith("/resources") || x.endsWith("/resources/main") |
| || x.endsWith(".jar"))) |
| .collect(Collectors.joining(File.pathSeparator)); |
| |
| assertThat(classPath).as("no classes found for module: " + module) |
| .isNotBlank(); |
| |
| return classPath; |
| } |
| } |