diff --git a/docs/pom.xml b/docs/pom.xml
index 7fc9069..b95ab7e 100644
--- a/docs/pom.xml
+++ b/docs/pom.xml
@@ -6,7 +6,7 @@
org.springframework.cloud
spring-cloud-cli-parent
- 1.1.3.BUILD-SNAPSHOT
+ 1.2.0.BUILD-SNAPSHOT
pom
Spring Cloud Cli Docs
diff --git a/pom.xml b/pom.xml
index dd36198..e5d5a92 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,11 +3,11 @@
4.0.0
org.springframework.cloud
spring-cloud-cli-parent
- 1.1.3.BUILD-SNAPSHOT
+ 1.2.0.BUILD-SNAPSHOT
org.springframework.cloud
spring-cloud-build
- 1.1.2.BUILD-SNAPSHOT
+ 1.2.0.BUILD-SNAPSHOT
pom
@@ -26,6 +26,7 @@
${basedir}/..
+ spring-cloud-launcher
spring-cloud-cli
spring-cloud-cli-integration-tests
docs
diff --git a/spring-cloud-cli-integration-tests/pom.xml b/spring-cloud-cli-integration-tests/pom.xml
index 4a25eef..517fa67 100644
--- a/spring-cloud-cli-integration-tests/pom.xml
+++ b/spring-cloud-cli-integration-tests/pom.xml
@@ -5,7 +5,7 @@
org.springframework.cloud
spring-cloud-cli-integration-tests
- 1.1.3.BUILD-SNAPSHOT
+ 1.2.0.BUILD-SNAPSHOT
jar
spring-cloud-cli-integration-tests
@@ -14,7 +14,7 @@
org.springframework.cloud
spring-cloud-cli-parent
- 1.1.3.BUILD-SNAPSHOT
+ 1.2.0.BUILD-SNAPSHOT
diff --git a/spring-cloud-cli/pom.xml b/spring-cloud-cli/pom.xml
index 9c0dbc8..1d7200e 100644
--- a/spring-cloud-cli/pom.xml
+++ b/spring-cloud-cli/pom.xml
@@ -5,7 +5,7 @@
org.springframework.cloud
spring-cloud-cli
- 1.1.3.BUILD-SNAPSHOT
+ 1.2.0.BUILD-SNAPSHOT
jar
spring-cloud-cli
@@ -14,10 +14,15 @@
org.springframework.cloud
spring-cloud-cli-parent
- 1.1.3.BUILD-SNAPSHOT
+ 1.2.0.BUILD-SNAPSHOT
+
+ org.springframework.cloud.launcher
+ spring-cloud-launcher-cli
+ ${project.version}
+
org.springframework.boot
spring-boot-cli
diff --git a/spring-cloud-cli/src/main/java/org/springframework/cloud/cli/command/CloudCommandFactory.java b/spring-cloud-cli/src/main/java/org/springframework/cloud/cli/command/CloudCommandFactory.java
index a249715..1230862 100644
--- a/spring-cloud-cli/src/main/java/org/springframework/cloud/cli/command/CloudCommandFactory.java
+++ b/spring-cloud-cli/src/main/java/org/springframework/cloud/cli/command/CloudCommandFactory.java
@@ -22,6 +22,7 @@ import org.springframework.boot.cli.command.Command;
import org.springframework.boot.cli.command.CommandFactory;
import org.springframework.cloud.cli.command.encrypt.DecryptCommand;
import org.springframework.cloud.cli.command.encrypt.EncryptCommand;
+import org.springframework.cloud.launcher.cli.LauncherCommand;
/**
* @author Dave Syer
@@ -31,7 +32,7 @@ public class CloudCommandFactory implements CommandFactory {
@Override
public Collection getCommands() {
- return Arrays.asList(new EncryptCommand(), new DecryptCommand());
+ return Arrays.asList(new EncryptCommand(), new DecryptCommand(), new LauncherCommand());
}
}
diff --git a/spring-cloud-launcher/README.md b/spring-cloud-launcher/README.md
new file mode 100644
index 0000000..bf5821c
--- /dev/null
+++ b/spring-cloud-launcher/README.md
@@ -0,0 +1,70 @@
+## Spring Cloud Launcher
+
+### Building
+
+`./mvnw clean install` from parent directory
+
+### Installing
+
+Install Spring CLI first: https://github.com/spring-cloud/spring-cloud-cli/blob/master/docs/src/main/asciidoc/install.adoc
+
+```
+$ spring install org.springframework.cloud:spring-cloud-cli:1.2.0.BUILD-SNAPSHOT
+```
+
+### Running
+
+```
+$ spring cloud
+```
+
+Currently starts configserver, eureka, h2 (db server), hystrixdashboard and kafka. [Here](https://github.com/spring-cloud/spring-cloud-cli/blob/devtools/spring-cloud-launcher/spring-cloud-launcher-deployer/src/main/resources/cloud.yml) is the full configuration.
+
+### Configuring
+
+Spring Cloud Launcher use normal Spring Boot configuration mechanisms. The config name is `cloud`, so configuration can go in `cloud.yml` or `cloud.properties`.
+
+For example, to run configserver and eureka, create a `cloud.yml` that looks like:
+```
+spring:
+ cloud:
+ launcher:
+ deployables:
+ - name: configserver
+ coordinates: maven://org.springframework.cloud.launcher:spring-cloud-launcher-configserver:1.1.0.BUILD-SNAPSHOT
+ port: 8888
+ waitUntilStarted: true
+ order: -10
+ - name: eureka
+ coordinates: maven://org.springframework.cloud.launcher:spring-cloud-launcher-eureka:1.1.0.BUILD-SNAPSHOT
+ port: 8761
+```
+
+The `name` attribute is required. If `waitUntilStarted` is true, Launcher will block until the application has reached the `deployed` state. Before commands are deployed, the list is sorted using Spring's `OrderComparator`. In the above case, `configserver` is deployed before any other app is deployed. Currently only `maven:` coordinates and standard Spring Resources (`file:`, etc...) are supported.
+
+You can also use the `--deploy` option to select from the [predefined deployables](https://github.com/spring-cloud/spring-cloud-cli/blob/devtools/spring-cloud-launcher/spring-cloud-launcher-deployer/src/main/resources/cloud.yml). For example to run Spring Cloud Data Flow execute:
+```
+spring cloud --launch=configserver,h2,kafka,dataflow
+```
+
+### Stopping
+
+`Ctrl-C` in the same terminal `spring cloud` was run.
+
+### TODO
+
+- [X] Eureka
+- [X] Configserver
+- [X] Hystrix Dashboard
+- [X] Kafka Broker
+- [X] Kafka Bus
+- [X] Easy inclusion of default deployables
+- [X] H2 Database
+- [X] Spring Cloud Dataflow server
+- [X] Launcher landing page (Eureka Dashboard works for now)
+- [ ] Support external rabbit
+- [ ] Speedup startup (parallel start?, retry for config server, db and kafka?)
+- [ ] Sleuth/Zipkin
+- [ ] Cassandra Database
+- [ ] Client Side Library
+- [ ] Spring Boot Admin (Not compatible with Brixton)
diff --git a/spring-cloud-launcher/pom.xml b/spring-cloud-launcher/pom.xml
new file mode 100644
index 0000000..fd6d3e5
--- /dev/null
+++ b/spring-cloud-launcher/pom.xml
@@ -0,0 +1,73 @@
+
+
+ 4.0.0
+
+ org.springframework.cloud
+ spring-cloud-launcher
+ 1.2.0.BUILD-SNAPSHOT
+ pom
+
+ spring-cloud-launcher
+ Spring Cloud Launcher
+
+
+ org.springframework.cloud
+ spring-cloud-cli-parent
+ 1.2.0.BUILD-SNAPSHOT
+
+
+
+ spring-cloud-launcher-cli
+ spring-cloud-launcher-configserver
+ spring-cloud-launcher-dataflow
+ spring-cloud-launcher-deployer
+ spring-cloud-launcher-eureka
+ spring-cloud-launcher-h2
+ spring-cloud-launcher-hystrixdashboard
+ spring-cloud-launcher-kafka
+
+
+
+ 1.1.0.BUILD-SNAPSHOT
+ 1.0.0.BUILD-SNAPSHOT
+ 1.0.0.BUILD-SNAPSHOT
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-bus
+ ${spring-cloud-bus.version}
+ pom
+ import
+
+
+ org.springframework.cloud
+ spring-cloud-dataflow-dependencies
+ ${spring-cloud-dataflow.version}
+ pom
+ import
+
+
+ org.springframework.cloud
+ spring-cloud-deployer-local
+ ${spring-cloud-deployer.version}
+
+
+ org.springframework.cloud
+ spring-cloud-deployer-resource-support
+ ${spring-cloud-deployer.version}
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+
diff --git a/spring-cloud-launcher/spring-cloud-launcher-cli/pom.xml b/spring-cloud-launcher/spring-cloud-launcher-cli/pom.xml
new file mode 100644
index 0000000..76ac8dd
--- /dev/null
+++ b/spring-cloud-launcher/spring-cloud-launcher-cli/pom.xml
@@ -0,0 +1,40 @@
+
+
+ 4.0.0
+
+ org.springframework.cloud.launcher
+ spring-cloud-launcher-cli
+ 1.2.0.BUILD-SNAPSHOT
+ jar
+
+ spring-cloud-launcher-cli
+ Spring Cloud Launcher CLI
+
+
+ org.springframework.cloud
+ spring-cloud-launcher
+ 1.2.0.BUILD-SNAPSHOT
+
+
+
+
+ org.springframework.boot
+ spring-boot-cli
+ ${spring-boot.version}
+ provided
+
+
+ commons-logging
+ commons-logging
+ 1.2
+ provided
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
diff --git a/spring-cloud-launcher/spring-cloud-launcher-cli/src/main/java/org/springframework/cloud/launcher/cli/LauncherCommand.java b/spring-cloud-launcher/spring-cloud-launcher-cli/src/main/java/org/springframework/cloud/launcher/cli/LauncherCommand.java
new file mode 100644
index 0000000..1b5e33d
--- /dev/null
+++ b/spring-cloud-launcher/spring-cloud-launcher-cli/src/main/java/org/springframework/cloud/launcher/cli/LauncherCommand.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2013-2016 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.launcher.cli;
+
+import java.io.File;
+import java.lang.reflect.Constructor;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URLClassLoader;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.codehaus.groovy.control.CompilerConfiguration;
+import org.springframework.boot.cli.command.AbstractCommand;
+import org.springframework.boot.cli.command.status.ExitStatus;
+import org.springframework.boot.cli.compiler.RepositoryConfigurationFactory;
+import org.springframework.boot.cli.compiler.grape.AetherGrapeEngine;
+import org.springframework.boot.cli.compiler.grape.AetherGrapeEngineFactory;
+import org.springframework.boot.cli.compiler.grape.DependencyResolutionContext;
+import org.springframework.boot.cli.compiler.grape.RepositoryConfiguration;
+
+import groovy.lang.GroovyClassLoader;
+
+/**
+ * @author Spencer Gibb
+ */
+public class LauncherCommand extends AbstractCommand {
+
+ public static final Log log = LogFactory.getLog(LauncherCommand.class);
+
+ public LauncherCommand() {
+ super("cloud", "Start Spring Cloud Launcher");
+ }
+
+ @Override
+ public ExitStatus run(String... args) throws Exception {
+
+ try {
+ URLClassLoader classLoader = populateClassloader();
+
+ String name = "org.springframework.cloud.launcher.deployer.DeployerThread";
+ Class> threadClass = classLoader.loadClass(name);
+
+ Constructor> constructor = threadClass.getConstructor(ClassLoader.class, String[].class);
+ Thread thread = (Thread) constructor.newInstance(classLoader, args);
+ thread.start();
+ thread.join();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return ExitStatus.OK;
+ }
+
+ URLClassLoader populateClassloader() throws MalformedURLException {
+ DependencyResolutionContext resolutionContext = new DependencyResolutionContext();
+
+ GroovyClassLoader loader = new GroovyClassLoader(Thread.currentThread().getContextClassLoader(), new CompilerConfiguration());
+
+ List repositoryConfiguration = RepositoryConfigurationFactory
+ .createDefaultRepositoryConfiguration();
+ repositoryConfiguration.add(0, new RepositoryConfiguration("local",
+ new File("repository").toURI(), true));
+
+ String[] classpaths = {"."};
+ for (String classpath : classpaths) {
+ loader.addClasspath(classpath);
+ }
+
+ System.setProperty("groovy.grape.report.downloads", "true");
+ //System.setProperty("grape.root", ".");
+
+ AetherGrapeEngine grapeEngine = AetherGrapeEngineFactory.create(loader,
+ repositoryConfiguration, resolutionContext);
+
+ //GrapeEngineInstaller.install(grapeEngine);
+
+ //TODO: get version dynamically?
+ HashMap dependency = new HashMap<>();
+ dependency.put("group", "org.springframework.cloud.launcher");
+ dependency.put("module", "spring-cloud-launcher-deployer");
+ dependency.put("version", "1.2.0.BUILD-SNAPSHOT");
+ URI[] uris = grapeEngine.resolve(null, dependency);
+ //System.out.println("resolved URI's " + Arrays.asList(uris));
+ for (URI uri : uris) {
+ loader.addURL(uri.toURL());
+ }
+ log.debug("resolved URI's " + Arrays.asList(loader.getURLs()));
+ return loader;
+ }
+
+}
diff --git a/spring-cloud-launcher/spring-cloud-launcher-cli/src/test/java/org/springframework/cloud/launcher/cli/LauncherCommandTests.java b/spring-cloud-launcher/spring-cloud-launcher-cli/src/test/java/org/springframework/cloud/launcher/cli/LauncherCommandTests.java
new file mode 100644
index 0000000..b6ea09e
--- /dev/null
+++ b/spring-cloud-launcher/spring-cloud-launcher-cli/src/test/java/org/springframework/cloud/launcher/cli/LauncherCommandTests.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2013-2016 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.launcher.cli;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * @author Spencer Gibb
+ */
+public class LauncherCommandTests {
+
+ @Test
+ @Ignore
+ public void testLoadDeployer() throws Exception {
+ //new LauncherCommand().populateClassloader();
+ new LauncherCommand().run();
+ }
+}
diff --git a/spring-cloud-launcher/spring-cloud-launcher-configserver/pom.xml b/spring-cloud-launcher/spring-cloud-launcher-configserver/pom.xml
new file mode 100644
index 0000000..1cf9fed
--- /dev/null
+++ b/spring-cloud-launcher/spring-cloud-launcher-configserver/pom.xml
@@ -0,0 +1,52 @@
+
+
+ 4.0.0
+
+ org.springframework.cloud.launcher
+ spring-cloud-launcher-configserver
+ 1.2.0.BUILD-SNAPSHOT
+ jar
+
+ spring-cloud-launcher-configserver
+ Spring Cloud Launcher ConfigServer
+
+
+ org.springframework.cloud
+ spring-cloud-launcher
+ 1.2.0.BUILD-SNAPSHOT
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+ org.springframework.cloud
+ spring-cloud-starter-eureka
+
+
+ org.springframework.cloud
+ spring-cloud-starter-bus-kafka
+
+
+ org.springframework.cloud
+ spring-cloud-config-server
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
diff --git a/spring-cloud-launcher/spring-cloud-launcher-configserver/src/main/java/org/springframework/cloud/launcher/configserver/ConfigServerApplication.java b/spring-cloud-launcher/spring-cloud-launcher-configserver/src/main/java/org/springframework/cloud/launcher/configserver/ConfigServerApplication.java
new file mode 100644
index 0000000..3f613ae
--- /dev/null
+++ b/spring-cloud-launcher/spring-cloud-launcher-configserver/src/main/java/org/springframework/cloud/launcher/configserver/ConfigServerApplication.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2013-2016 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.launcher.configserver;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.cloud.config.server.EnableConfigServer;
+
+/**
+ * @author Spencer Gibb
+ */
+@EnableConfigServer
+@EnableDiscoveryClient
+@SpringBootApplication
+public class ConfigServerApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(ConfigServerApplication.class, args);
+ }
+}
diff --git a/spring-cloud-launcher/spring-cloud-launcher-configserver/src/main/resources/application.yml b/spring-cloud-launcher/spring-cloud-launcher-configserver/src/main/resources/application.yml
new file mode 100644
index 0000000..513b02a
--- /dev/null
+++ b/spring-cloud-launcher/spring-cloud-launcher-configserver/src/main/resources/application.yml
@@ -0,0 +1,26 @@
+spring:
+ application:
+ name: configserver
+ profiles:
+ active: native
+ cloud:
+ config:
+ server:
+ bootstrap: true
+ native:
+ search-locations: classpath:/launcher/, file:./launcher/
+
+server:
+ port: 8888
+
+management:
+ context-path: /admin
+
+eureka:
+ instance:
+ status-page-url-path: ${management.context-path}/info
+
+info:
+ artifactId: @project.artifactId@
+ description: @project.description@
+ version: @project.version@
\ No newline at end of file
diff --git a/spring-cloud-launcher/spring-cloud-launcher-configserver/src/main/resources/launcher/application.yml b/spring-cloud-launcher/spring-cloud-launcher-configserver/src/main/resources/launcher/application.yml
new file mode 100644
index 0000000..3aafd1c
--- /dev/null
+++ b/spring-cloud-launcher/spring-cloud-launcher-configserver/src/main/resources/launcher/application.yml
@@ -0,0 +1,28 @@
+info:
+ description: Spring Cloud Launcher
+
+eureka:
+ client:
+ instance-info-replication-interval-seconds: 5
+ initial-instance-info-replication-interval-seconds: 5
+ serviceUrl:
+ defaultZone: http://localhost:8761/eureka/
+
+endpoints:
+ restart: enabled
+
+ribbon:
+ ConnectTimeout: 3000
+ ReadTimeout: 60000
+
+spring:
+ datasource:
+ url: jdbc:h2:tcp://localhost:9096/~/launcher
+
+logging:
+ level:
+ kafka: WARN
+ org.apache.zookeeper: WARN
+ org.apache.zookeeper.ClientCnxn: ERROR
+ org.apache.kafka: WARN
+ org.I0Itec: WARN
diff --git a/spring-cloud-launcher/spring-cloud-launcher-dataflow/pom.xml b/spring-cloud-launcher/spring-cloud-launcher-dataflow/pom.xml
new file mode 100644
index 0000000..1944cff
--- /dev/null
+++ b/spring-cloud-launcher/spring-cloud-launcher-dataflow/pom.xml
@@ -0,0 +1,56 @@
+
+
+ 4.0.0
+
+ org.springframework.cloud.launcher
+ spring-cloud-launcher-dataflow
+ 1.2.0.BUILD-SNAPSHOT
+ jar
+
+ spring-cloud-launcher-dataflow
+ Spring Cloud Launcher Data Flow
+
+
+ org.springframework.cloud
+ spring-cloud-launcher
+ 1.2.0.BUILD-SNAPSHOT
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+ org.springframework.cloud
+ spring-cloud-starter-config
+
+
+ org.springframework.cloud
+ spring-cloud-starter-eureka
+
+
+ org.springframework.cloud
+ spring-cloud-deployer-local
+
+
+ org.springframework.cloud
+ spring-cloud-dataflow-server-core
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
diff --git a/spring-cloud-launcher/spring-cloud-launcher-dataflow/src/main/java/org/springframework/cloud/launcher/dataflow/DataFlowApplication.java b/spring-cloud-launcher/spring-cloud-launcher-dataflow/src/main/java/org/springframework/cloud/launcher/dataflow/DataFlowApplication.java
new file mode 100644
index 0000000..37984d3
--- /dev/null
+++ b/spring-cloud-launcher/spring-cloud-launcher-dataflow/src/main/java/org/springframework/cloud/launcher/dataflow/DataFlowApplication.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2013-2016 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.launcher.dataflow;
+
+import javax.sql.DataSource;
+
+import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.batch.BatchDatabaseInitializer;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.cloud.dataflow.server.EnableDataFlowServer;
+import org.springframework.cloud.task.repository.support.TaskRepositoryInitializer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.jdbc.datasource.DataSourceTransactionManager;
+
+/**
+ * @author Spencer Gibb
+ */
+@EnableDataFlowServer
+@EnableDiscoveryClient
+@SpringBootApplication
+public class DataFlowApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(DataFlowApplication.class, args);
+ }
+
+ @Bean
+ public JobRepositoryFactoryBean jobRepositoryFactoryBeanForServer(
+ DataSource dataSource,
+ DataSourceTransactionManager dataSourceTransactionManager) {
+ JobRepositoryFactoryBean repositoryFactoryBean = new JobRepositoryFactoryBean();
+ repositoryFactoryBean.setDataSource(dataSource);
+ repositoryFactoryBean.setTransactionManager(dataSourceTransactionManager);
+ return repositoryFactoryBean;
+ }
+
+ @Bean
+ public DataSourceTransactionManager transactionManagerForServer(
+ DataSource dataSource) {
+ return new DataSourceTransactionManager(dataSource);
+ }
+
+ @Bean
+ public BatchDatabaseInitializer batchRepositoryInitializerForDefaultDBForServer() {
+ return new BatchDatabaseInitializer();
+ }
+
+ @Bean
+ public TaskRepositoryInitializer taskRepositoryInitializerForDefaultDB(
+ DataSource dataSource) {
+ TaskRepositoryInitializer taskRepositoryInitializer = new TaskRepositoryInitializer();
+ taskRepositoryInitializer.setDataSource(dataSource);
+ return taskRepositoryInitializer;
+ }
+}
diff --git a/spring-cloud-launcher/spring-cloud-launcher-dataflow/src/main/resources/application.yml b/spring-cloud-launcher/spring-cloud-launcher-dataflow/src/main/resources/application.yml
new file mode 100644
index 0000000..cfbe078
--- /dev/null
+++ b/spring-cloud-launcher/spring-cloud-launcher-dataflow/src/main/resources/application.yml
@@ -0,0 +1,20 @@
+server:
+ port: 9393
+
+eureka:
+ instance:
+ status-page-url-path: /admin-ui #allows you to click on the link in eureka dashboard
+
+info:
+ artifactId: @project.artifactId@
+ description: @project.description@
+ version: @project.version@
+
+security:
+ basic:
+ enabled: false
+
+management:
+ context-path: /admin
+ security:
+ enabled: false
\ No newline at end of file
diff --git a/spring-cloud-launcher/spring-cloud-launcher-dataflow/src/main/resources/bootstrap.yml b/spring-cloud-launcher/spring-cloud-launcher-dataflow/src/main/resources/bootstrap.yml
new file mode 100644
index 0000000..6ef41f9
--- /dev/null
+++ b/spring-cloud-launcher/spring-cloud-launcher-dataflow/src/main/resources/bootstrap.yml
@@ -0,0 +1,3 @@
+spring:
+ application:
+ name: dataflow
diff --git a/spring-cloud-launcher/spring-cloud-launcher-deployer/pom.xml b/spring-cloud-launcher/spring-cloud-launcher-deployer/pom.xml
new file mode 100644
index 0000000..0652015
--- /dev/null
+++ b/spring-cloud-launcher/spring-cloud-launcher-deployer/pom.xml
@@ -0,0 +1,40 @@
+
+
+ 4.0.0
+
+ org.springframework.cloud.launcher
+ spring-cloud-launcher-deployer
+ 1.2.0.BUILD-SNAPSHOT
+ jar
+
+ spring-cloud-launcher-deployer
+ Spring Cloud Launcher Deployer
+
+
+ org.springframework.cloud
+ spring-cloud-launcher
+ 1.2.0.BUILD-SNAPSHOT
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+ org.springframework.cloud
+ spring-cloud-deployer-local
+
+
+ org.springframework.cloud
+ spring-cloud-deployer-resource-support
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
diff --git a/spring-cloud-launcher/spring-cloud-launcher-deployer/src/main/java/org/springframework/cloud/launcher/deployer/DeployerConfiguration.java b/spring-cloud-launcher/spring-cloud-launcher-deployer/src/main/java/org/springframework/cloud/launcher/deployer/DeployerConfiguration.java
new file mode 100644
index 0000000..f3c72cb
--- /dev/null
+++ b/spring-cloud-launcher/spring-cloud-launcher-deployer/src/main/java/org/springframework/cloud/launcher/deployer/DeployerConfiguration.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2013-2016 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.launcher.deployer;
+
+import java.util.HashMap;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.cloud.deployer.resource.maven.MavenProperties;
+import org.springframework.cloud.deployer.resource.maven.MavenResourceLoader;
+import org.springframework.cloud.deployer.resource.support.DelegatingResourceLoader;
+import org.springframework.cloud.deployer.spi.app.AppDeployer;
+import org.springframework.cloud.deployer.spi.local.LocalAppDeployer;
+import org.springframework.cloud.deployer.spi.local.LocalDeployerProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.ResourceLoader;
+
+/**
+ * @author Spencer Gibb
+ */
+@Configuration
+@EnableConfigurationProperties
+public class DeployerConfiguration {
+
+ @Bean
+ public DeployerProperties deployerProperties() {
+ return new DeployerProperties();
+ }
+
+ @Bean
+ public LocalDeployerProperties localDeployerProperties() {
+ return new LocalDeployerProperties();
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ public AppDeployer appDeployer() {
+ return new LocalAppDeployer(localDeployerProperties());
+ }
+
+ @Bean
+ public MavenProperties mavenProperties() {
+ return new MavenProperties(); //TODO: exposed as config properties?
+ }
+
+ @Bean
+ public MavenResourceLoader mavenResourceLoader(MavenProperties mavenProperties) {
+ return new MavenResourceLoader(mavenProperties);
+ }
+
+ @Bean
+ public DelegatingResourceLoader delegatingResourceLoader(MavenResourceLoader mavenResourceLoader) {
+ HashMap map = new HashMap<>();
+ map.put("maven", mavenResourceLoader);
+ return new DelegatingResourceLoader(map);
+ }
+}
diff --git a/spring-cloud-launcher/spring-cloud-launcher-deployer/src/main/java/org/springframework/cloud/launcher/deployer/DeployerProperties.java b/spring-cloud-launcher/spring-cloud-launcher-deployer/src/main/java/org/springframework/cloud/launcher/deployer/DeployerProperties.java
new file mode 100644
index 0000000..e63c1e5
--- /dev/null
+++ b/spring-cloud-launcher/spring-cloud-launcher-deployer/src/main/java/org/springframework/cloud/launcher/deployer/DeployerProperties.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2013-2016 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.launcher.deployer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.validation.constraints.NotNull;
+
+import org.hibernate.validator.constraints.NotEmpty;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.core.Ordered;
+
+/**
+ * @author Spencer Gibb
+ */
+@ConfigurationProperties(prefix = "spring.cloud.launcher")
+public class DeployerProperties {
+
+ @NotNull
+ private List deployables = new ArrayList<>();
+
+ @NotNull
+ private List deploy = new ArrayList<>();
+
+ private int statusSleepMillis = 300;
+
+ public List getDeployables() {
+ return deployables;
+ }
+
+ public void setDeployables(List deployables) {
+ this.deployables = deployables;
+ }
+
+ public List getDeploy() {
+ return deploy;
+ }
+
+ public void setDeploy(List deploy) {
+ this.deploy = deploy;
+ }
+
+ public int getStatusSleepMillis() {
+ return statusSleepMillis;
+ }
+
+ public void setStatusSleepMillis(int statusSleepMillis) {
+ this.statusSleepMillis = statusSleepMillis;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuffer sb = new StringBuffer("DeployerProperties{");
+ sb.append("deployables=").append(deployables);
+ sb.append("deploy=").append(deploy);
+ sb.append("statusSleepMillis=").append(statusSleepMillis);
+ sb.append('}');
+ return sb.toString();
+ }
+
+ public static class Deployable implements Ordered {
+ @NotEmpty
+ private String coordinates;
+ @NotEmpty
+ private String name;
+ private int port = 0;
+ private boolean waitUntilStarted;
+ private int order = 0;
+ private String message;
+
+ public String getCoordinates() {
+ return coordinates;
+ }
+
+ public void setCoordinates(String coordinates) {
+ this.coordinates = coordinates;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+ public boolean isWaitUntilStarted() {
+ return waitUntilStarted;
+ }
+
+ public void setWaitUntilStarted(boolean waitUntilStarted) {
+ this.waitUntilStarted = waitUntilStarted;
+ }
+
+ @Override
+ public int getOrder() {
+ return order;
+ }
+
+ public void setOrder(int order) {
+ this.order = order;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuffer sb = new StringBuffer("Deployable{");
+ sb.append("coordinates='").append(coordinates).append('\'');
+ sb.append(", name='").append(name).append('\'');
+ sb.append(", port=").append(port);
+ sb.append(", waitUntilStarted=").append(waitUntilStarted);
+ sb.append(", order=").append(order);
+ sb.append(", message=").append(message);
+ sb.append('}');
+ return sb.toString();
+ }
+ }
+}
diff --git a/spring-cloud-launcher/spring-cloud-launcher-deployer/src/main/java/org/springframework/cloud/launcher/deployer/DeployerThread.java b/spring-cloud-launcher/spring-cloud-launcher-deployer/src/main/java/org/springframework/cloud/launcher/deployer/DeployerThread.java
new file mode 100644
index 0000000..506029b
--- /dev/null
+++ b/spring-cloud-launcher/spring-cloud-launcher-deployer/src/main/java/org/springframework/cloud/launcher/deployer/DeployerThread.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2013-2016 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.launcher.deployer;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.cloud.deployer.resource.support.DelegatingResourceLoader;
+import org.springframework.cloud.deployer.spi.app.AppDeployer;
+import org.springframework.cloud.deployer.spi.app.AppStatus;
+import org.springframework.cloud.deployer.spi.app.DeploymentState;
+import org.springframework.cloud.deployer.spi.core.AppDefinition;
+import org.springframework.cloud.deployer.spi.core.AppDeploymentRequest;
+import org.springframework.cloud.launcher.deployer.DeployerProperties.Deployable;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.core.OrderComparator;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.ResourceLoader;
+import org.springframework.util.StringUtils;
+
+/**
+ * @author Spencer Gibb
+ */
+@SuppressWarnings("unused")
+public class DeployerThread extends Thread {
+
+ private static final Logger logger = LoggerFactory.getLogger(DeployerThread.class);
+
+ private Map deployed = new ConcurrentHashMap<>();
+
+ private String[] args;
+
+ public DeployerThread(ClassLoader classLoader, String[] args) {
+ super("spring-cloud-launcher");
+ this.args = args;
+ setContextClassLoader(classLoader);
+ setDaemon(true);
+ }
+
+ @Override
+ public void run() {
+ final ConfigurableApplicationContext context = new SpringApplicationBuilder(PropertyPlaceholderAutoConfiguration.class, DeployerConfiguration.class)
+ .web(false)
+ .properties("spring.config.name=cloud", "banner.location=launcher-banner.txt")
+ .run(args);
+
+ final AppDeployer deployer = context.getBean(AppDeployer.class);
+
+ ResourceLoader resourceLoader = context.getBean(DelegatingResourceLoader.class);
+
+ DeployerProperties properties = context.getBean(DeployerProperties.class);
+
+ ArrayList deployables = new ArrayList<>(properties.getDeployables());
+ OrderComparator.sort(deployables);
+
+ logger.debug("toDeploy {}", properties.getDeployables());
+
+ for (Deployable deployable : deployables) {
+ deploy(deployer, resourceLoader, deployable, properties);
+ }
+
+ Runtime.getRuntime().addShutdownHook(new Thread() {
+ @Override
+ public void run() {
+ logger.info("\n\nShutting down ...\n");
+ for (String id : DeployerThread.this.deployed.keySet()) {
+ logger.info("Undeploying {}", id);
+ deployer.undeploy(id);
+ }
+ context.close();
+ }
+ });
+
+ for (Deployable deployable : deployables) {
+ if (shouldDeploy(deployable, properties) && StringUtils.hasText(deployable.getMessage())) {
+ logger.info("\n\n{}: {}\n", deployable.getName(), deployable.getMessage());
+ }
+ }
+
+ logger.info("\n\nType Ctrl-C to quit.\n");
+
+ while (true) {
+ for (Map.Entry entry : this.deployed.entrySet()) {
+ String id = entry.getKey();
+ DeploymentState state = entry.getValue();
+ AppStatus status = deployer.status(id);
+ DeploymentState newState = status.getState();
+ if (state != newState) {
+ logger.info("{} change status from {} to {}", id, state, newState);
+ this.deployed.put(id, newState);
+ }
+ }
+ try {
+ Thread.sleep(properties.getStatusSleepMillis());
+ } catch (InterruptedException e) {
+ logger.error("error sleeping", e);
+ }
+ }
+ }
+
+ private String deploy(AppDeployer deployer, ResourceLoader resourceLoader, Deployable deployable, DeployerProperties properties) {
+ if (!shouldDeploy(deployable, properties)) {
+ // this deployable isn't in the list of things to deploy
+ logger.info("Skipping deploy of {}", deployable.getName());
+ return null;
+ }
+
+ logger.debug("getting resource {} = {}", deployable.getName(), deployable.getCoordinates());
+ Resource resource = resourceLoader.getResource(deployable.getCoordinates());
+
+ Map appDefProps = new HashMap<>();
+ appDefProps.put("server.port", String.valueOf(deployable.getPort()));
+
+ //TODO: move to notDeployedProps or something
+ if (!shouldDeploy("kafka", properties)) {
+ appDefProps.put("spring.cloud.bus.enabled", Boolean.FALSE.toString());
+ }
+
+ AppDefinition definition = new AppDefinition(deployable.getName(), appDefProps);
+
+ Map environmentProperties = Collections.singletonMap(AppDeployer.GROUP_PROPERTY_KEY, "launcher");
+ AppDeploymentRequest request = new AppDeploymentRequest(definition, resource, environmentProperties);
+
+ logger.debug("deploying resource {} = {}", deployable.getName(), deployable.getCoordinates());
+ String id = deployer.deploy(request);
+ AppStatus appStatus = getAppStatus(deployer, id);
+ logger.info("Status of {}: {}", id, appStatus);
+ //TODO: stream stdout/stderr like docker-compose (with colors and prefix)
+
+ if (deployable.isWaitUntilStarted()) {
+ try {
+ logger.info("\n\nWaiting for {} to start.\n", deployable.getName());
+
+ while (appStatus.getState() != DeploymentState.deployed
+ && appStatus.getState() != DeploymentState.failed) {
+ Thread.sleep(properties.getStatusSleepMillis());
+ appStatus = getAppStatus(deployer, id);
+ logger.debug("State of {} = {}", id, appStatus.getState());
+ }
+ } catch (Exception e) {
+ logger.error("error updating status of " + id, e);
+ }
+ }
+
+ return id;
+ }
+
+ private boolean shouldDeploy(Deployable deployable, DeployerProperties properties) {
+ return shouldDeploy(deployable.getName(), properties);
+ }
+
+ private boolean shouldDeploy(String name, DeployerProperties properties) {
+ boolean deploy = properties.getDeploy().contains(name);
+ logger.debug("shouldDeploy {} = {}", name, deploy);
+ return deploy;
+ }
+
+ private AppStatus getAppStatus(AppDeployer deployer, String id) {
+ AppStatus appStatus = deployer.status(id);
+ this.deployed.put(id, appStatus.getState());
+ return appStatus;
+ }
+
+
+}
diff --git a/spring-cloud-launcher/spring-cloud-launcher-deployer/src/main/resources/cloud.yml b/spring-cloud-launcher/spring-cloud-launcher-deployer/src/main/resources/cloud.yml
new file mode 100644
index 0000000..4451b63
--- /dev/null
+++ b/spring-cloud-launcher/spring-cloud-launcher-deployer/src/main/resources/cloud.yml
@@ -0,0 +1,33 @@
+dt:
+ pre: maven://org.springframework.cloud.launcher:spring-cloud-launcher-
+ ver: 1.2.0.BUILD-SNAPSHOT
+spring:
+ cloud:
+ launcher:
+ deployables:
+ - name: configserver
+ coordinates: ${dt.pre}configserver:${dt.ver}
+ port: 8888
+ waitUntilStarted: true
+ order: -100
+ - name: dataflow
+ coordinates: ${dt.pre}dataflow:${dt.ver}
+ port: 9393
+ - name: eureka
+ coordinates: ${dt.pre}eureka:${dt.ver}
+ port: 8761
+ message: To see the dashboard open http://localhost:8761
+ - name: h2
+ coordinates: ${dt.pre}h2:${dt.ver}
+ port: 9095
+ waitUntilStarted: true
+ order: -50
+ - name: hystrixdashboard
+ coordinates: ${dt.pre}hystrixdashboard:${dt.ver}
+ port: 7979
+ - name: kafka
+ coordinates: ${dt.pre}kafka:${dt.ver}
+ port: 9091
+ waitUntilStarted: true
+ order: -200
+ deploy: ${launch:configserver,eureka,h2, hystrixdashboard,kafka}
diff --git a/spring-cloud-launcher/spring-cloud-launcher-deployer/src/main/resources/launcher-banner.txt b/spring-cloud-launcher/spring-cloud-launcher-deployer/src/main/resources/launcher-banner.txt
new file mode 100644
index 0000000..d8d3646
--- /dev/null
+++ b/spring-cloud-launcher/spring-cloud-launcher-deployer/src/main/resources/launcher-banner.txt
@@ -0,0 +1,9 @@
+${Ansi.GREEN}
+███████╗██████╗ ██████╗ ██╗███╗ ██╗ ██████╗ ██████╗██╗ ██████╗ ██╗ ██╗██████╗
+██╔════╝██╔══██╗██╔══██╗██║████╗ ██║██╔════╝ ██╔════╝██║ ██╔═══██╗██║ ██║██╔══██╗
+███████╗██████╔╝██████╔╝██║██╔██╗ ██║██║ ███╗ ██║ ██║ ██║ ██║██║ ██║██║ ██║
+╚════██║██╔═══╝ ██╔══██╗██║██║╚██╗██║██║ ██║ ██║ ██║ ██║ ██║██║ ██║██║ ██║
+███████║██║ ██║ ██║██║██║ ╚████║╚██████╔╝ ╚██████╗███████╗╚██████╔╝╚██████╔╝██████╔╝
+╚══════╝╚═╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚═════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝
+${Ansi.WHITE}
+-- Spring Cloud Launcher --
diff --git a/spring-cloud-launcher/spring-cloud-launcher-eureka/pom.xml b/spring-cloud-launcher/spring-cloud-launcher-eureka/pom.xml
new file mode 100644
index 0000000..b7ea80e
--- /dev/null
+++ b/spring-cloud-launcher/spring-cloud-launcher-eureka/pom.xml
@@ -0,0 +1,52 @@
+
+
+ 4.0.0
+
+ org.springframework.cloud.launcher
+ spring-cloud-launcher-eureka
+ 1.2.0.BUILD-SNAPSHOT
+ jar
+
+ spring-cloud-launcher-eureka
+ Spring Cloud Launcher Eureka
+
+
+ org.springframework.cloud
+ spring-cloud-launcher
+ 1.2.0.BUILD-SNAPSHOT
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+ org.springframework.cloud
+ spring-cloud-starter-config
+
+
+ org.springframework.cloud
+ spring-cloud-starter-bus-kafka
+
+
+ org.springframework.cloud
+ spring-cloud-netflix-eureka-server
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
diff --git a/spring-cloud-launcher/spring-cloud-launcher-eureka/src/main/java/org/springframework/cloud/launcher/eureka/EurekaApplication.java b/spring-cloud-launcher/spring-cloud-launcher-eureka/src/main/java/org/springframework/cloud/launcher/eureka/EurekaApplication.java
new file mode 100644
index 0000000..2dc1a64
--- /dev/null
+++ b/spring-cloud-launcher/spring-cloud-launcher-eureka/src/main/java/org/springframework/cloud/launcher/eureka/EurekaApplication.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2013-2016 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.launcher.eureka;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
+
+/**
+ * @author Spencer Gibb
+ */
+@EnableEurekaServer
+@SpringBootApplication
+public class EurekaApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(EurekaApplication.class, args);
+ }
+}
diff --git a/spring-cloud-launcher/spring-cloud-launcher-eureka/src/main/resources/application.yml b/spring-cloud-launcher/spring-cloud-launcher-eureka/src/main/resources/application.yml
new file mode 100644
index 0000000..b79d75c
--- /dev/null
+++ b/spring-cloud-launcher/spring-cloud-launcher-eureka/src/main/resources/application.yml
@@ -0,0 +1,15 @@
+server:
+ port: 8761
+
+eureka:
+ client:
+ registerWithEureka: false
+ fetchRegistry: false
+ server:
+ renewal-percent-threshold: 0.01
+ waitTimeInMsWhenSyncEmpty: 0
+
+info:
+ artifactId: @project.artifactId@
+ description: @project.description@
+ version: @project.version@
diff --git a/spring-cloud-launcher/spring-cloud-launcher-eureka/src/main/resources/bootstrap.yml b/spring-cloud-launcher/spring-cloud-launcher-eureka/src/main/resources/bootstrap.yml
new file mode 100644
index 0000000..076a289
--- /dev/null
+++ b/spring-cloud-launcher/spring-cloud-launcher-eureka/src/main/resources/bootstrap.yml
@@ -0,0 +1,3 @@
+spring:
+ application:
+ name: eurekaserver
diff --git a/spring-cloud-launcher/spring-cloud-launcher-h2/pom.xml b/spring-cloud-launcher/spring-cloud-launcher-h2/pom.xml
new file mode 100644
index 0000000..bed2405
--- /dev/null
+++ b/spring-cloud-launcher/spring-cloud-launcher-h2/pom.xml
@@ -0,0 +1,56 @@
+
+
+ 4.0.0
+
+ org.springframework.cloud.launcher
+ spring-cloud-launcher-h2
+ 1.2.0.BUILD-SNAPSHOT
+ jar
+
+ spring-cloud-launcher-h2
+ Spring Cloud Launcher H2
+
+
+ org.springframework.cloud
+ spring-cloud-launcher
+ 1.2.0.BUILD-SNAPSHOT
+
+
+
+
+ com.h2database
+ h2
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+ org.springframework.cloud
+ spring-cloud-starter-config
+
+
+ org.springframework.cloud
+ spring-cloud-starter-eureka
+
+
+ org.springframework.cloud
+ spring-cloud-starter-bus-kafka
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
diff --git a/spring-cloud-launcher/spring-cloud-launcher-h2/src/main/java/org/springframework/cloud/launcher/h2/H2Application.java b/spring-cloud-launcher/spring-cloud-launcher-h2/src/main/java/org/springframework/cloud/launcher/h2/H2Application.java
new file mode 100644
index 0000000..653ba95
--- /dev/null
+++ b/spring-cloud-launcher/spring-cloud-launcher-h2/src/main/java/org/springframework/cloud/launcher/h2/H2Application.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2013-2016 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.launcher.h2;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.h2.tools.Console;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.context.SmartLifecycle;
+import org.springframework.stereotype.Controller;
+import org.springframework.stereotype.Service;
+import org.springframework.util.Assert;
+import org.springframework.util.ReflectionUtils;
+import org.springframework.util.StringUtils;
+
+/**
+ * @author Spencer Gibb
+ */
+@EnableDiscoveryClient
+@SpringBootApplication
+@Controller
+public class H2Application {
+ private static final Log log = LogFactory.getLog(H2Application.class);
+
+ public static void main(String[] args) {
+ SpringApplication.run(H2Application.class, args);
+ }
+
+ @SuppressWarnings("unused")
+ @Service
+ static class H2Server implements SmartLifecycle {
+ private AtomicBoolean running = new AtomicBoolean(false);
+
+ private Console console;
+
+ @Value("${spring.datasource.url:9096}")
+ private String dataSourceUrl;
+
+ @Override
+ public boolean isAutoStartup() {
+ return true;
+ }
+
+ @Override
+ public void stop(Runnable callback) {
+ stop();
+ callback.run();
+ }
+
+ @Override
+ public void start() {
+ if (this.running.compareAndSet(false, true)) {
+ try {
+ log.info("Starting H2 Server");
+ this.console = new Console();
+ this.console.runTool("-tcp", "-pg", "-web", "-tcpAllowOthers", "-tcpPort", getH2Port(dataSourceUrl));
+ } catch (Exception e) {
+ ReflectionUtils.rethrowRuntimeException(e);
+ }
+ }
+ }
+
+ private String getH2Port(String url) {
+ String[] tokens = StringUtils.tokenizeToStringArray(url, ":");
+ Assert.isTrue(tokens.length >= 5, "URL not properly formatted");
+ return tokens[4].substring(0, tokens[4].indexOf("/"));
+ }
+
+ @Override
+ public void stop() {
+ if (this.running.compareAndSet(true, false)) {
+ log.info("Stoping H2 Server");
+ this.console.shutdown();
+ }
+ }
+
+ @Override
+ public boolean isRunning() {
+ return this.running.get();
+ }
+
+ @Override
+ public int getPhase() {
+ return 0;
+ }
+ }
+}
diff --git a/spring-cloud-launcher/spring-cloud-launcher-h2/src/main/resources/application.yml b/spring-cloud-launcher/spring-cloud-launcher-h2/src/main/resources/application.yml
new file mode 100644
index 0000000..6994fba
--- /dev/null
+++ b/spring-cloud-launcher/spring-cloud-launcher-h2/src/main/resources/application.yml
@@ -0,0 +1,13 @@
+server:
+ port: 9095
+
+info:
+ artifactId: @project.artifactId@
+ description: @project.description@
+ version: @project.version@
+
+eureka:
+ instance:
+ # port of the h2 console
+ non-secure-port: 8082
+ status-page-url-path: / #allows you to click on the link in eureka dashboard
\ No newline at end of file
diff --git a/spring-cloud-launcher/spring-cloud-launcher-h2/src/main/resources/bootstrap.yml b/spring-cloud-launcher/spring-cloud-launcher-h2/src/main/resources/bootstrap.yml
new file mode 100644
index 0000000..52cbd0f
--- /dev/null
+++ b/spring-cloud-launcher/spring-cloud-launcher-h2/src/main/resources/bootstrap.yml
@@ -0,0 +1,3 @@
+spring:
+ application:
+ name: h2server
diff --git a/spring-cloud-launcher/spring-cloud-launcher-hystrixdashboard/pom.xml b/spring-cloud-launcher/spring-cloud-launcher-hystrixdashboard/pom.xml
new file mode 100644
index 0000000..030c474
--- /dev/null
+++ b/spring-cloud-launcher/spring-cloud-launcher-hystrixdashboard/pom.xml
@@ -0,0 +1,56 @@
+
+
+ 4.0.0
+
+ org.springframework.cloud.launcher
+ spring-cloud-launcher-hystrixdashboard
+ 1.2.0.BUILD-SNAPSHOT
+ jar
+
+ spring-cloud-launcher-hystrixdashboard
+ Spring Cloud Launcher Hystrix Dashboard
+
+
+ org.springframework.cloud
+ spring-cloud-launcher
+ 1.2.0.BUILD-SNAPSHOT
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+ org.springframework.cloud
+ spring-cloud-starter-config
+
+
+ org.springframework.cloud
+ spring-cloud-starter-eureka
+
+
+ org.springframework.cloud
+ spring-cloud-starter-bus-kafka
+
+
+ org.springframework.cloud
+ spring-cloud-starter-hystrix-dashboard
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
diff --git a/spring-cloud-launcher/spring-cloud-launcher-hystrixdashboard/src/main/java/org/springframework/cloud/launcher/hystrixdashboard/HystrixDashboardApplication.java b/spring-cloud-launcher/spring-cloud-launcher-hystrixdashboard/src/main/java/org/springframework/cloud/launcher/hystrixdashboard/HystrixDashboardApplication.java
new file mode 100644
index 0000000..8a8ec58
--- /dev/null
+++ b/spring-cloud-launcher/spring-cloud-launcher-hystrixdashboard/src/main/java/org/springframework/cloud/launcher/hystrixdashboard/HystrixDashboardApplication.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2013-2016 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.launcher.hystrixdashboard;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+/**
+ * @author Spencer Gibb
+ */
+@EnableDiscoveryClient
+@EnableHystrixDashboard
+@SpringBootApplication
+@Controller
+public class HystrixDashboardApplication {
+
+ @RequestMapping(path = "/", method = RequestMethod.GET)
+ public String home() {
+ return "redirect:/hystrix";
+ }
+
+ public static void main(String[] args) {
+ SpringApplication.run(HystrixDashboardApplication.class, args);
+ }
+}
diff --git a/spring-cloud-launcher/spring-cloud-launcher-hystrixdashboard/src/main/resources/application.yml b/spring-cloud-launcher/spring-cloud-launcher-hystrixdashboard/src/main/resources/application.yml
new file mode 100644
index 0000000..b6cd473
--- /dev/null
+++ b/spring-cloud-launcher/spring-cloud-launcher-hystrixdashboard/src/main/resources/application.yml
@@ -0,0 +1,11 @@
+server:
+ port: 7979
+
+eureka:
+ instance:
+ status-page-url-path: /hystrix #allows you to click on the link in eureka dashboard
+
+info:
+ artifactId: @project.artifactId@
+ description: @project.description@
+ version: @project.version@
diff --git a/spring-cloud-launcher/spring-cloud-launcher-hystrixdashboard/src/main/resources/bootstrap.yml b/spring-cloud-launcher/spring-cloud-launcher-hystrixdashboard/src/main/resources/bootstrap.yml
new file mode 100644
index 0000000..0970919
--- /dev/null
+++ b/spring-cloud-launcher/spring-cloud-launcher-hystrixdashboard/src/main/resources/bootstrap.yml
@@ -0,0 +1,3 @@
+spring:
+ application:
+ name: hystrixdashboard
diff --git a/spring-cloud-launcher/spring-cloud-launcher-kafka/pom.xml b/spring-cloud-launcher/spring-cloud-launcher-kafka/pom.xml
new file mode 100644
index 0000000..7ac132b
--- /dev/null
+++ b/spring-cloud-launcher/spring-cloud-launcher-kafka/pom.xml
@@ -0,0 +1,86 @@
+
+
+ 4.0.0
+
+ org.springframework.cloud.launcher
+ spring-cloud-launcher-kafka
+ 1.2.0.BUILD-SNAPSHOT
+ jar
+
+ spring-cloud-launcher-kafka
+ Spring Cloud Launcher Kafka
+
+
+ org.springframework.cloud
+ spring-cloud-launcher
+ 1.2.0.BUILD-SNAPSHOT
+
+
+
+ 0.9.0.1
+ 2.10.0
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+ org.springframework.cloud
+ spring-cloud-starter-config
+
+
+ org.apache.curator
+ curator-recipes
+ ${curator.version}
+
+
+ org.apache.kafka
+ kafka_2.11
+ ${kafka.version}
+
+
+ org.slf4j
+ slf4j-log4j12
+
+
+
+
+ org.apache.kafka
+ kafka_2.11
+ test
+ ${kafka.version}
+
+
+ org.slf4j
+ slf4j-log4j12
+
+
+
+
+ org.apache.curator
+ curator-test
+ ${curator.version}
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
diff --git a/spring-cloud-launcher/spring-cloud-launcher-kafka/src/main/java/org/springframework/cloud/launcher/kafka/KafkaApplication.java b/spring-cloud-launcher/spring-cloud-launcher-kafka/src/main/java/org/springframework/cloud/launcher/kafka/KafkaApplication.java
new file mode 100644
index 0000000..acc4d24
--- /dev/null
+++ b/spring-cloud-launcher/spring-cloud-launcher-kafka/src/main/java/org/springframework/cloud/launcher/kafka/KafkaApplication.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2013-2016 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.launcher.kafka;
+
+import java.io.File;
+import java.net.InetSocketAddress;
+import java.util.Properties;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.I0Itec.zkclient.ZkClient;
+import org.I0Itec.zkclient.exception.ZkInterruptedException;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.kafka.common.protocol.SecurityProtocol;
+import org.apache.kafka.common.utils.Utils;
+import org.apache.zookeeper.server.NIOServerCnxnFactory;
+import org.apache.zookeeper.server.ZooKeeperServer;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.context.SmartLifecycle;
+import org.springframework.stereotype.Service;
+import org.springframework.util.ReflectionUtils;
+
+import kafka.server.KafkaConfig;
+import kafka.server.KafkaServer;
+import kafka.server.NotRunning;
+import kafka.utils.CoreUtils;
+import kafka.utils.SystemTime$;
+import kafka.utils.TestUtils;
+import kafka.utils.ZKStringSerializer$;
+
+/**
+ * @author Spencer Gibb
+ */
+@SpringBootApplication
+public class KafkaApplication {
+
+ private static final Log log = LogFactory.getLog(KafkaApplication.class);
+
+ public static void main(String[] args) {
+ new SpringApplicationBuilder(KafkaApplication.class)
+ .run(args);
+ }
+
+ @SuppressWarnings("unused")
+ @Service
+ static class KafkaDevServer implements SmartLifecycle {
+ private AtomicBoolean running = new AtomicBoolean(false);
+ private ZkClient zkClient;
+
+ private EmbeddedZookeeper zookeeper;
+
+ private KafkaServer kafkaServer;
+
+ @Value("${kafka.port:${KAFKA_PORT:9092}}")
+ private int port;
+
+ @Value("${zk.port:${ZK_PORT:2181}}")
+ private int zkPort;
+
+ @Override
+ public boolean isAutoStartup() {
+ return true;
+ }
+
+ @Override
+ public void stop(Runnable callback) {
+ stop();
+ callback.run();
+ }
+
+ @Override
+ public void start() {
+ if (this.running.compareAndSet(false, true)) {
+ try {
+ log.info("Starting Zookeeper");
+ this.zookeeper = new EmbeddedZookeeper(this.zkPort);
+ String zkConnectString = "127.0.0.1:" + this.zookeeper.getPort();
+ log.info("Started Zookeeper at " + zkConnectString);
+ try {
+ int zkConnectionTimeout = 10000;
+ int zkSessionTimeout = 10000;
+ zkClient = new ZkClient(zkConnectString, zkSessionTimeout, zkConnectionTimeout, ZKStringSerializer$.MODULE$);
+ }
+ catch (Exception e) {
+ zookeeper.shutdown();
+ throw e;
+ }
+ try {
+ log.info("Creating Kafka server");
+ //TODO: move to properties?
+ int nodeId = 0;
+ boolean enableControlledShutdown = true;
+ Properties brokerConfigProperties = TestUtils.createBrokerConfig(nodeId, zkConnectString, enableControlledShutdown,
+ true, port,
+ scala.Option.apply(null),
+ scala.Option.apply(null),
+ true, false, 0, false, 0, false, 0);
+ brokerConfigProperties.setProperty("replica.socket.timeout.ms", "1000");
+ brokerConfigProperties.setProperty("controller.socket.timeout.ms", "1000");
+ brokerConfigProperties.setProperty("offsets.topic.replication.factor", "1");
+ brokerConfigProperties.put("zookeeper.connect", zkConnectString);
+ kafkaServer = TestUtils.createServer(new KafkaConfig(brokerConfigProperties), SystemTime$.MODULE$);
+ log.info("Created Kafka server at " + kafkaServer.config().hostName() + ":" + kafkaServer.config().port());
+ }
+ catch (Exception e) {
+ zookeeper.shutdown();
+ zkClient.close();
+ throw e;
+ }
+ } catch (Exception e) {
+ ReflectionUtils.rethrowRuntimeException(e);
+ }
+ }
+ }
+
+ @Override
+ public void stop() {
+ if (this.running.compareAndSet(true, false)) {
+ log.info("Stoping Kafka");
+ try {
+ if (kafkaServer.brokerState().currentState() != (NotRunning.state())) {
+ kafkaServer.shutdown();
+ kafkaServer.awaitShutdown();
+ }
+ }
+ catch (Exception e) {
+ // do nothing
+ }
+ try {
+ CoreUtils.rm(kafkaServer.config().logDirs());
+ }
+ catch (Exception e) {
+ // do nothing
+ }
+ log.info("Stoping Zookeeper");
+ try {
+ this.zkClient.close();
+ }
+ catch (ZkInterruptedException e) {
+ // do nothing
+ }
+ try {
+ this.zookeeper.shutdown();
+ }
+ catch (Exception e) {
+ // do nothing
+ }
+ }
+ }
+
+ @Override
+ public boolean isRunning() {
+ return this.running.get();
+ }
+
+ @Override
+ public int getPhase() {
+ return 0;
+ }
+ }
+
+ static class EmbeddedZookeeper {
+ private File snapshotDir = TestUtils.tempDir();
+ private File logDir = TestUtils.tempDir();
+ private int tickTime = 500;
+ private NIOServerCnxnFactory factory = new NIOServerCnxnFactory();
+ private ZooKeeperServer zookeeper;
+ private InetSocketAddress addr;
+ private int port;
+
+ public EmbeddedZookeeper(int port) throws Exception {
+ this.port = port;
+ zookeeper = new ZooKeeperServer(snapshotDir, logDir, tickTime);
+ addr = new InetSocketAddress("127.0.0.1", port);
+ factory.configure(addr, 0);
+ factory.startup(zookeeper);
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ void shutdown() throws Exception {
+ zookeeper.shutdown();
+ factory.shutdown();
+ Utils.delete(logDir);
+ Utils.delete(snapshotDir);
+ }
+ }
+}
diff --git a/spring-cloud-launcher/spring-cloud-launcher-kafka/src/main/resources/application.yml b/spring-cloud-launcher/spring-cloud-launcher-kafka/src/main/resources/application.yml
new file mode 100644
index 0000000..8890030
--- /dev/null
+++ b/spring-cloud-launcher/spring-cloud-launcher-kafka/src/main/resources/application.yml
@@ -0,0 +1,13 @@
+server:
+ port: 9091
+
+kafka:
+ port: 9092
+
+zk:
+ port: 2181
+
+info:
+ artifactId: @project.artifactId@
+ description: @project.description@
+ version: @project.version@
diff --git a/spring-cloud-launcher/spring-cloud-launcher-kafka/src/main/resources/bootstrap.yml b/spring-cloud-launcher/spring-cloud-launcher-kafka/src/main/resources/bootstrap.yml
new file mode 100644
index 0000000..fccd3ad
--- /dev/null
+++ b/spring-cloud-launcher/spring-cloud-launcher-kafka/src/main/resources/bootstrap.yml
@@ -0,0 +1,3 @@
+spring:
+ application:
+ name: kafka