Add integration tests and release 1.1.0.M5

This commit is contained in:
Dave Syer
2016-02-05 12:42:32 +00:00
parent 9be47f709b
commit 032c96d86e
22 changed files with 594 additions and 137 deletions

View File

@@ -13,23 +13,23 @@ Config clients with secret configuration values.
To install, make
sure you have
https://github.com/spring-projects/spring-boot[Spring Boot CLI]
(1.2.0 or better):
(1.3.0 or better):
$ spring version
Spring CLI v1.2.3.RELEASE
Spring CLI v1.3.2.RELEASE
E.g. for GVM users
E.g. for SDKMan users
```
$ gvm install springboot 1.3.0.M5
$ gvm use springboot 1.3.0.M5
$ sdk install springboot 1.3.2.RELEASE
$ sdk use springboot 1.3.2.RELEASE
```
and install the Spring Cloud plugin:
```
$ mvn install
$ spring install org.springframework.cloud:spring-cloud-cli:1.1.0.BUILD-SNAPSHOT
$ spring install org.springframework.cloud:spring-cloud-cli:1.1.0.M5
```
IMPORTANT: **Prerequisites:** to use the encryption and decryption features

View File

@@ -37,5 +37,5 @@ and finally install the Spring Cloud plugin:
```
$ mvn install
$ spring install org.springframework.cloud:spring-cloud-cli:1.0.0.BUILD-SNAPSHOT
$ spring install org.springframework.cloud:spring-cloud-cli:1.0.0.M5
```

View File

@@ -3,11 +3,11 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-cli-docs</artifactId>
<version>1.1.0.BUILD-SNAPSHOT</version>
<version>1.1.0.M5</version>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-build</artifactId>
<version>1.1.0.BUILD-SNAPSHOT</version>
<version>1.1.0.M5</version>
<relativePath/>
</parent>
<packaging>pom</packaging>

View File

@@ -1,23 +1,23 @@
To install, make
sure you have
https://github.com/spring-projects/spring-boot[Spring Boot CLI]
(1.2.0 or better):
(1.3.0 or better):
$ spring version
Spring CLI v1.2.3.RELEASE
Spring CLI v1.3.2.RELEASE
E.g. for GVM users
E.g. for SDKMan users
```
$ gvm install springboot 1.3.0.M5
$ gvm use springboot 1.3.0.M5
$ sdk install springboot 1.3.2.RELEASE
$ sdk use springboot 1.3.2.RELEASE
```
and install the Spring Cloud plugin:
```
$ mvn install
$ spring install org.springframework.cloud:spring-cloud-cli:1.1.0.BUILD-SNAPSHOT
$ spring install org.springframework.cloud:spring-cloud-cli:1.1.0.M5
```
IMPORTANT: **Prerequisites:** to use the encryption and decryption features

View File

@@ -3,11 +3,11 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-cli-parent</artifactId>
<version>1.1.0.BUILD-SNAPSHOT</version>
<version>1.1.0.M5</version>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-build</artifactId>
<version>1.1.0.BUILD-SNAPSHOT</version>
<version>1.1.0.M5</version>
<relativePath/>
</parent>
<packaging>pom</packaging>
@@ -27,6 +27,7 @@
</properties>
<modules>
<module>spring-cloud-cli</module>
<module>spring-cloud-cli-integration-tests</module>
<module>docs</module>
</modules>
<profiles>
@@ -83,14 +84,14 @@
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config</artifactId>
<version>1.1.0.BUILD-SNAPSHOT</version>
<version>1.1.0.M5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>1.1.0.BUILD-SNAPSHOT</version>
<version>1.1.0.M5</version>
<type>pom</type>
<scope>import</scope>
</dependency>

View File

@@ -0,0 +1 @@
/target/

View File

@@ -0,0 +1,9 @@
Spring Boot command line features for
[Spring Cloud](https://github.com/spring-cloud). To install, make
sure you have
[Spring Boot CLI](https://github.com/spring-projects/spring-boot)
(1.1.x with x>=5):
$ spring version
Spring CLI v1.1.5.RELEASE

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-cli-integration-tests</artifactId>
<version>1.1.0.M5</version>
<packaging>jar</packaging>
<name>spring-cloud-cli-integration-tests</name>
<description>Spring Patform Cli integration project</description>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-cli-parent</artifactId>
<version>1.1.0.M5</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-cli</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-cli</artifactId>
<version>${spring-boot.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.7</java.version>
<spring-cloud.version>${project.version}</spring-cloud.version>
</properties>
<build>
<plugins>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,22 @@
package org.test
@Component
class Example implements CommandLineRunner {
@Autowired
private MyService myService
void run(String... args) {
println "Hello ${this.myService.sayWorld()} From ${getClass().getClassLoader().getResource('samples/app.groovy')}"
}
}
@Service
class MyService {
String sayWorld() {
return "World!"
}
}

View File

@@ -0,0 +1,6 @@
package org.test
@EnableConfigServer
class Example {
}

View File

@@ -0,0 +1,6 @@
package org.test
@EnableDiscoveryClient
class Example {
}

View File

@@ -0,0 +1,6 @@
package org.test
@EnableEurekaServer
class Example {
}

View File

@@ -0,0 +1,6 @@
package org.test
@EnableBinding(transport="rabbit")
class Example {
}

View File

@@ -0,0 +1,6 @@
package org.test
@EnableZuulProxy
class Example {
}

View File

@@ -0,0 +1 @@
org.springframework.cloud.cli.command.CloudCommandFactory

View File

@@ -0,0 +1,12 @@
org.springframework.cloud.cli.compiler.SpringCloudCompilerAutoConfiguration
org.springframework.cloud.cli.compiler.ConfigServerCompilerAutoConfiguration
org.springframework.cloud.cli.compiler.EurekaClientCompilerAutoConfiguration
org.springframework.cloud.cli.compiler.EurekaServerCompilerAutoConfiguration
org.springframework.cloud.cli.compiler.HystrixCompilerAutoConfiguration
org.springframework.cloud.cli.compiler.HystrixDashboardCompilerAutoConfiguration
org.springframework.cloud.cli.compiler.OAuth2LoadBalancedCompilerAutoConfiguration
org.springframework.cloud.cli.compiler.RibbonClientCompilerAutoConfiguration
org.springframework.cloud.cli.compiler.StreamKafkaCompilerAutoConfiguration
org.springframework.cloud.cli.compiler.StreamRabbitCompilerAutoConfiguration
org.springframework.cloud.cli.compiler.StreamRedisCompilerAutoConfiguration
org.springframework.cloud.cli.compiler.ZuulCompilerAutoConfiguration

View File

@@ -0,0 +1 @@
org.springframework.cloud.cli.compiler.SpringCloudBomAstTransformation

View File

@@ -0,0 +1,228 @@
/*
* Copyright 2012-2014 the original author or authors.
*
* Licensed 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.springframework.cloud.cli;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.junit.Assume;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import org.springframework.boot.cli.command.AbstractCommand;
import org.springframework.boot.cli.command.OptionParsingCommand;
import org.springframework.boot.cli.command.archive.JarCommand;
import org.springframework.boot.cli.command.grab.GrabCommand;
import org.springframework.boot.cli.command.run.RunCommand;
import org.springframework.boot.cli.command.test.TestCommand;
import org.springframework.util.SocketUtils;
/**
* {@link TestRule} that can be used to invoke CLI commands.
*
* @author Phillip Webb
* @author Dave Syer
* @author Andy Wilkinson
*/
public class CliTester implements TestRule {
private final OutputCapture outputCapture = new OutputCapture();
private long timeout = TimeUnit.MINUTES.toMillis(6);
private final List<AbstractCommand> commands = new ArrayList<AbstractCommand>();
private final String prefix;
private final int port = SocketUtils.findAvailableTcpPort();
public CliTester(String prefix) {
this.prefix = prefix;
}
public void setTimeout(long timeout) {
this.timeout = timeout;
}
public String run(String... args) throws Exception {
Future<RunCommand> future = submitCommand(new RunCommand(), args);
this.commands.add(future.get(this.timeout, TimeUnit.MILLISECONDS));
return getOutput();
}
public String test(String... args) throws Exception {
Future<TestCommand> future = submitCommand(new TestCommand(), args);
try {
this.commands.add(future.get(this.timeout, TimeUnit.MILLISECONDS));
return getOutput();
}
catch (Exception ex) {
return getOutput();
}
}
public String grab(String... args) throws Exception {
Future<GrabCommand> future = submitCommand(new GrabCommand(), args);
this.commands.add(future.get(this.timeout, TimeUnit.MILLISECONDS));
return getOutput();
}
public String jar(String... args) throws Exception {
Future<JarCommand> future = submitCommand(new JarCommand(), args);
this.commands.add(future.get(this.timeout, TimeUnit.MILLISECONDS));
return getOutput();
}
private <T extends OptionParsingCommand> Future<T> submitCommand(final T command,
String... args) {
clearUrlHandler();
final String[] sources = getSources(args);
return Executors.newSingleThreadExecutor().submit(new Callable<T>() {
@Override
public T call() throws Exception {
ClassLoader loader = Thread.currentThread().getContextClassLoader();
System.setProperty("server.port", String.valueOf(CliTester.this.port));
try {
command.run(sources);
return command;
}
finally {
System.clearProperty("server.port");
Thread.currentThread().setContextClassLoader(loader);
}
}
});
}
/**
* The TomcatURLStreamHandlerFactory fails if the factory is already set, use
* reflection to reset it.
*/
private void clearUrlHandler() {
try {
Field field = URL.class.getDeclaredField("factory");
field.setAccessible(true);
field.set(null, null);
}
catch (Exception ex) {
throw new IllegalStateException(ex);
}
}
protected String[] getSources(String... args) {
final String[] sources = new String[args.length];
for (int i = 0; i < args.length; i++) {
String arg = args[i];
if (!arg.endsWith(".groovy") && !arg.endsWith(".xml")) {
if (new File(this.prefix + arg).isDirectory()) {
sources[i] = this.prefix + arg;
}
else {
sources[i] = arg;
}
}
else {
sources[i] = this.prefix + arg;
}
}
return sources;
}
public String getOutput() {
return this.outputCapture.toString();
}
@Override
public Statement apply(final Statement base, final Description description) {
final Statement statement = CliTester.this.outputCapture
.apply(new RunLauncherStatement(base), description);
return new Statement() {
@Override
public void evaluate() throws Throwable {
Assume.assumeTrue(
"Not running sample integration tests because integration profile not active",
System.getProperty("spring.profiles.active", "integration")
.contains("integration"));
statement.evaluate();
}
};
}
public String getHttpOutput() {
return getHttpOutput("/");
}
public String getHttpOutput(String uri) {
try {
InputStream stream = URI.create("http://localhost:" + this.port + uri).toURL()
.openStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
String line;
StringBuilder result = new StringBuilder();
while ((line = reader.readLine()) != null) {
result.append(line);
}
return result.toString();
}
catch (Exception ex) {
throw new IllegalStateException(ex);
}
}
private final class RunLauncherStatement extends Statement {
private final Statement base;
private RunLauncherStatement(Statement base) {
this.base = base;
}
@Override
public void evaluate() throws Throwable {
System.setProperty("disableSpringSnapshotRepos", "false");
try {
try {
this.base.evaluate();
}
finally {
for (AbstractCommand command : CliTester.this.commands) {
if (command != null && command instanceof RunCommand) {
((RunCommand) command).stop();
}
}
System.clearProperty("disableSpringSnapshotRepos");
}
}
catch (Exception ex) {
throw new IllegalStateException(ex);
}
}
}
}

View File

@@ -0,0 +1,127 @@
/*
* Copyright 2012-2014 the original author or authors.
*
* Licensed 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.springframework.cloud.cli;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
/**
* Capture output from System.out and System.err.
*
* @author Phillip Webb
*/
public class OutputCapture implements TestRule {
private CaptureOutputStream captureOut;
private CaptureOutputStream captureErr;
private ByteArrayOutputStream copy;
@Override
public Statement apply(final Statement base, Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
captureOutput();
try {
base.evaluate();
}
finally {
releaseOutput();
}
}
};
}
protected void captureOutput() {
this.copy = new ByteArrayOutputStream();
this.captureOut = new CaptureOutputStream(System.out, this.copy);
this.captureErr = new CaptureOutputStream(System.err, this.copy);
System.setOut(new PrintStream(this.captureOut));
System.setErr(new PrintStream(this.captureErr));
}
protected void releaseOutput() {
System.setOut(this.captureOut.getOriginal());
System.setErr(this.captureErr.getOriginal());
this.copy = null;
}
public void flush() {
try {
this.captureOut.flush();
this.captureErr.flush();
}
catch (IOException ex) {
// ignore
}
}
@Override
public String toString() {
flush();
return this.copy.toString();
}
private static class CaptureOutputStream extends OutputStream {
private final PrintStream original;
private final OutputStream copy;
CaptureOutputStream(PrintStream original, OutputStream copy) {
this.original = original;
this.copy = copy;
}
@Override
public void write(int b) throws IOException {
this.copy.write(b);
this.original.write(b);
this.original.flush();
}
@Override
public void write(byte[] b) throws IOException {
write(b, 0, b.length);
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
this.copy.write(b, off, len);
this.original.write(b, off, len);
}
public PrintStream getOriginal() {
return this.original;
}
@Override
public void flush() throws IOException {
this.copy.flush();
this.original.flush();
}
}
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed 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.springframework.cloud.cli;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.net.URI;
import org.junit.Rule;
import org.junit.Test;
/**
* @author Dave Syer
*
*/
public class SampleIntegrationTests {
@Rule
public CliTester cli = new CliTester("samples/");
@Test
public void appSample() throws Exception {
String output = this.cli.run("app.groovy");
URI scriptUri = new File("samples/app.groovy").toURI();
assertTrue("Wrong output: " + output,
output.contains("Hello World! From " + scriptUri));
}
@Test
public void eurekaSample() throws Exception {
String output = this.cli.run("eureka.groovy");
assertTrue("Wrong output: " + output,
output.contains("Setting initial instance status as: STARTING"));
}
@Test
public void eurekaServerSample() throws Exception {
String output = this.cli.run("eurekaserver.groovy");
assertTrue("Wrong output: " + output,
output.contains("Setting the eureka configuration.."));
}
@Test
public void rabbitSample() throws Exception {
String output = this.cli.run("rabbit.groovy");
assertTrue("Wrong output: " + output,
output.contains("Registering MessageChannel errorChannel"));
}
@Test
public void configServerSample() throws Exception {
String output = this.cli.run("configserver.groovy", "--",
"--spring.config.name=configserver");
assertTrue("Wrong output: " + output,
output.contains("[/{name}/{profiles}/{label:.*}],methods=[GET]"));
}
@Test
public void zuulProxySample() throws Exception {
String output = this.cli.run("zuulproxy.groovy");
assertTrue("Wrong output: " + output,
output.contains("[/routes || /routes.json],methods=[GET]"));
}
}

View File

@@ -5,7 +5,7 @@
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-cli</artifactId>
<version>1.1.0.BUILD-SNAPSHOT</version>
<version>1.1.0.M5</version>
<packaging>jar</packaging>
<name>spring-cloud-cli</name>
@@ -14,7 +14,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-cli-parent</artifactId>
<version>1.1.0.BUILD-SNAPSHOT</version>
<version>1.1.0.M5</version>
</parent>
<dependencies>
@@ -40,119 +40,4 @@
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.7</java.version>
<spring-cloud.version>${project.version}</spring-cloud.version>
</properties>
<profiles>
<profile>
<id>milestone</id>
<distributionManagement>
<repository>
<id>repo.spring.io</id>
<name>Spring Milestone Repository</name>
<url>https://repo.spring.io/libs-milestone-local</url>
</repository>
</distributionManagement>
</profile>
<profile>
<id>central</id>
<distributionManagement>
<snapshotRepository>
<id>sonatype-nexus-snapshots</id>
<name>Sonatype Nexus Snapshots</name>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
</snapshotRepository>
<repository>
<id>sonatype-nexus-staging</id>
<name>Nexus Release Repository</name>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<distributionManagement>
<!-- see 'staging' profile for dry-run deployment settings -->
<downloadUrl>http://www.springsource.com/download/community
</downloadUrl>
<site>
<id>spring-docs</id>
<url>scp://static.springframework.org/var/www/domains/springframework.org/static/htdocs/spring-cloud-cli/docs/${project.version}
</url>
</site>
<repository>
<id>repo.spring.io</id>
<name>Spring Release Repository</name>
<url>https://repo.spring.io/libs-release-local</url>
</repository>
<snapshotRepository>
<id>repo.spring.io</id>
<name>Spring Snapshot Repository</name>
<url>https://repo.spring.io/libs-snapshot-local</url>
</snapshotRepository>
</distributionManagement>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>http://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>http://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>http://repo.spring.io/release</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>http://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>http://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>

View File

@@ -28,7 +28,7 @@ import org.springframework.boot.cli.compiler.GenericBomAstTransformation;
@GroovyASTTransformation(phase = CompilePhase.CONVERSION)
public class SpringCloudBomAstTransformation extends GenericBomAstTransformation {
private static final String SPRING_CLOUD_VERSION = "Brixton.BUILD-SNAPSHOT";
private static final String SPRING_CLOUD_VERSION = "Brixton.M5";
@Override
protected String getBomModule() {