From 6aee631561884d49b8c343e89fa2f4907acf1aa7 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 8 Jul 2016 09:42:46 +0100 Subject: [PATCH] Add a bunch of new things * support for zipkin server * if eureka isn't running disable the client * add --list option to list deployables --- spring-cloud-launcher/pom.xml | 7 +- .../spring-cloud-launcher-cli/pom.xml | 1 - .../cloud/launcher/cli/LauncherCommand.java | 164 +++++++++++++----- .../launcher/cli/LauncherCommandFactory.java | 35 ++++ ...gframework.boot.cli.command.CommandFactory | 1 + .../pom.xml | 1 - .../src/main/resources/application.yml | 6 +- .../spring-cloud-launcher-dataflow/pom.xml | 9 +- .../src/main/resources/application.yml | 6 +- .../spring-cloud-launcher-deployer/pom.xml | 1 - .../launcher/deployer/DeployerProperties.java | 46 +++-- .../launcher/deployer/DeployerThread.java | 97 +++++++++-- .../src/main/resources/cloud.yml | 7 +- .../spring-cloud-launcher-eureka/pom.xml | 1 - .../src/main/resources/application.yml | 6 +- .../spring-cloud-launcher-h2/pom.xml | 9 +- .../cloud/launcher/h2/H2Application.java | 18 +- .../src/main/resources/application.yml | 11 +- .../pom.xml | 1 - .../src/main/resources/application.yml | 6 +- .../spring-cloud-launcher-kafka/pom.xml | 1 - .../src/main/resources/application.yml | 6 +- .../spring-cloud-launcher-zipkin/.jdk8 | 0 .../spring-cloud-launcher-zipkin/pom.xml | 55 ++++++ .../zipkin/ZipkinServerApplication.java | 36 ++++ .../src/main/resources/application.yml | 11 ++ .../main/resources/launcher/application.yml | 29 ++++ 27 files changed, 449 insertions(+), 122 deletions(-) create mode 100644 spring-cloud-launcher/spring-cloud-launcher-cli/src/main/java/org/springframework/cloud/launcher/cli/LauncherCommandFactory.java create mode 100644 spring-cloud-launcher/spring-cloud-launcher-cli/src/main/resources/META-INF/services/org.springframework.boot.cli.command.CommandFactory create mode 100644 spring-cloud-launcher/spring-cloud-launcher-zipkin/.jdk8 create mode 100644 spring-cloud-launcher/spring-cloud-launcher-zipkin/pom.xml create mode 100644 spring-cloud-launcher/spring-cloud-launcher-zipkin/src/main/java/org/springframework/cloud/launcher/zipkin/ZipkinServerApplication.java create mode 100644 spring-cloud-launcher/spring-cloud-launcher-zipkin/src/main/resources/application.yml create mode 100644 spring-cloud-launcher/spring-cloud-launcher-zipkin/src/main/resources/launcher/application.yml diff --git a/spring-cloud-launcher/pom.xml b/spring-cloud-launcher/pom.xml index fd6d3e5..e0ec992 100644 --- a/spring-cloud-launcher/pom.xml +++ b/spring-cloud-launcher/pom.xml @@ -26,10 +26,11 @@ spring-cloud-launcher-h2 spring-cloud-launcher-hystrixdashboard spring-cloud-launcher-kafka + spring-cloud-launcher-zipkin - 1.1.0.BUILD-SNAPSHOT + Camden.BUILD-SNAPSHOT 1.0.0.BUILD-SNAPSHOT 1.0.0.BUILD-SNAPSHOT @@ -38,8 +39,8 @@ org.springframework.cloud - spring-cloud-bus - ${spring-cloud-bus.version} + spring-cloud-dependencies + ${spring-cloud.version} pom import diff --git a/spring-cloud-launcher/spring-cloud-launcher-cli/pom.xml b/spring-cloud-launcher/spring-cloud-launcher-cli/pom.xml index 76ac8dd..f29d8dc 100644 --- a/spring-cloud-launcher/spring-cloud-launcher-cli/pom.xml +++ b/spring-cloud-launcher/spring-cloud-launcher-cli/pom.xml @@ -5,7 +5,6 @@ org.springframework.cloud.launcher spring-cloud-launcher-cli - 1.2.0.BUILD-SNAPSHOT jar spring-cloud-launcher-cli 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 index 1b5e33d..724fcbe 100644 --- 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 @@ -21,89 +21,159 @@ import java.lang.reflect.Constructor; import java.net.MalformedURLException; import java.net.URI; import java.net.URLClassLoader; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; 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.HelpExample; +import org.springframework.boot.cli.command.OptionParsingCommand; +import org.springframework.boot.cli.command.options.OptionHandler; 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 org.springframework.util.StringUtils; import groovy.lang.GroovyClassLoader; +import joptsimple.OptionSet; +import joptsimple.OptionSpec; /** * @author Spencer Gibb */ -public class LauncherCommand extends AbstractCommand { +public class LauncherCommand extends OptionParsingCommand { public static final Log log = LogFactory.getLog(LauncherCommand.class); + private static final String DEFAULT_VERSION = "1.2.0.BUILD-SNAPSHOT"; + + private static final Collection EXAMPLES = new ArrayList<>(); + + static { + EXAMPLES.add(new HelpExample("Launch Eureka", "spring cloud eureka")); + EXAMPLES.add(new HelpExample("Launch Config Server and Eureka", "spring cloud configserver eureka")); + EXAMPLES.add(new HelpExample("List deployable apps", "spring cloud --list")); + } + public LauncherCommand() { - super("cloud", "Start Spring Cloud Launcher"); + super("cloud", "Start Spring Cloud services, like Eureka, Config Server, etc.", new LauncherOptionHandler()); } @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; + public Collection getExamples() { + return EXAMPLES; } - URLClassLoader populateClassloader() throws MalformedURLException { - DependencyResolutionContext resolutionContext = new DependencyResolutionContext(); + private static class LauncherOptionHandler extends OptionHandler { - GroovyClassLoader loader = new GroovyClassLoader(Thread.currentThread().getContextClassLoader(), new CompilerConfiguration()); + private OptionSpec debugOption; + private OptionSpec listOption; - List repositoryConfiguration = RepositoryConfigurationFactory - .createDefaultRepositoryConfiguration(); - repositoryConfiguration.add(0, new RepositoryConfiguration("local", - new File("repository").toURI(), true)); - - String[] classpaths = {"."}; - for (String classpath : classpaths) { - loader.addClasspath(classpath); + @Override + protected void options() { + this.debugOption = option(Arrays.asList("debug", "d"), "Debug logging for the deployer"); + this.listOption = option(Arrays.asList("list", "l"), "List the deployables (don't launch anything)"); } - System.setProperty("groovy.grape.report.downloads", "true"); - //System.setProperty("grape.root", "."); + @Override + protected synchronized ExitStatus run(OptionSet options) throws Exception { - AetherGrapeEngine grapeEngine = AetherGrapeEngineFactory.create(loader, - repositoryConfiguration, resolutionContext); + try { + URLClassLoader classLoader = populateClassloader(); - //GrapeEngineInstaller.install(grapeEngine); + String name = "org.springframework.cloud.launcher.deployer.DeployerThread"; + Class threadClass = classLoader.loadClass(name); - //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()); + Constructor constructor = threadClass.getConstructor(ClassLoader.class, String[].class); + Thread thread = (Thread) constructor.newInstance(classLoader, getArgs(options)); + thread.start(); + thread.join(); + } + catch (Exception e) { + e.printStackTrace(); + } + + return ExitStatus.OK; } - log.debug("resolved URI's " + Arrays.asList(loader.getURLs())); - return loader; + + private String[] getArgs(OptionSet options) { + List args = new ArrayList<>(); + List apps = new ArrayList<>(); + int sourceArgCount = 0; + for (Object option : options.nonOptionArguments()) { + if (option instanceof String) { + String filename = (String) option; + if ("--".equals(filename)) { + break; + } + sourceArgCount++; + apps.add(option.toString()); + } + } + if (options.has(this.debugOption)) { + args.add("--debug=true"); + } + if (options.has(this.listOption)) { + args.add("--launcher.list=true"); + } + else { + if (!apps.isEmpty()) { + args.add("--launcher.deploy=" + StringUtils.collectionToCommaDelimitedString(apps)); + } + } + args.addAll(options.nonOptionArguments().subList(sourceArgCount, options.nonOptionArguments().size())); + return args.toArray(new String[args.size()]); + } + + 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", getVersion()); + 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; + } + + private String getVersion() { + Package pkg = LauncherCommand.class.getPackage(); + return (pkg != null ? pkg.getImplementationVersion() : DEFAULT_VERSION); + } + } } diff --git a/spring-cloud-launcher/spring-cloud-launcher-cli/src/main/java/org/springframework/cloud/launcher/cli/LauncherCommandFactory.java b/spring-cloud-launcher/spring-cloud-launcher-cli/src/main/java/org/springframework/cloud/launcher/cli/LauncherCommandFactory.java new file mode 100644 index 0000000..5fcb140 --- /dev/null +++ b/spring-cloud-launcher/spring-cloud-launcher-cli/src/main/java/org/springframework/cloud/launcher/cli/LauncherCommandFactory.java @@ -0,0 +1,35 @@ +/* + * Copyright 2013-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.launcher.cli; + +import java.util.Arrays; +import java.util.Collection; + +import org.springframework.boot.cli.command.Command; +import org.springframework.boot.cli.command.CommandFactory; + +/** + * @author Dave Syer + * + */ +public class LauncherCommandFactory implements CommandFactory { + + @Override + public Collection getCommands() { + return Arrays.asList(new LauncherCommand()); + } + +} diff --git a/spring-cloud-launcher/spring-cloud-launcher-cli/src/main/resources/META-INF/services/org.springframework.boot.cli.command.CommandFactory b/spring-cloud-launcher/spring-cloud-launcher-cli/src/main/resources/META-INF/services/org.springframework.boot.cli.command.CommandFactory new file mode 100644 index 0000000..89f281e --- /dev/null +++ b/spring-cloud-launcher/spring-cloud-launcher-cli/src/main/resources/META-INF/services/org.springframework.boot.cli.command.CommandFactory @@ -0,0 +1 @@ +org.springframework.cloud.launcher.cli.LauncherCommandFactory diff --git a/spring-cloud-launcher/spring-cloud-launcher-configserver/pom.xml b/spring-cloud-launcher/spring-cloud-launcher-configserver/pom.xml index 1cf9fed..7a22c22 100644 --- a/spring-cloud-launcher/spring-cloud-launcher-configserver/pom.xml +++ b/spring-cloud-launcher/spring-cloud-launcher-configserver/pom.xml @@ -5,7 +5,6 @@ org.springframework.cloud.launcher spring-cloud-launcher-configserver - 1.2.0.BUILD-SNAPSHOT jar spring-cloud-launcher-configserver 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 index 513b02a..3de90b1 100644 --- 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 @@ -21,6 +21,6 @@ eureka: status-page-url-path: ${management.context-path}/info info: - artifactId: @project.artifactId@ - description: @project.description@ - version: @project.version@ \ No newline at end of file + artifactId: "@project.artifactId@" + description: "@project.description@" + version: "@project.version@" \ No newline at end of file diff --git a/spring-cloud-launcher/spring-cloud-launcher-dataflow/pom.xml b/spring-cloud-launcher/spring-cloud-launcher-dataflow/pom.xml index 1944cff..fcf4e93 100644 --- a/spring-cloud-launcher/spring-cloud-launcher-dataflow/pom.xml +++ b/spring-cloud-launcher/spring-cloud-launcher-dataflow/pom.xml @@ -5,7 +5,6 @@ org.springframework.cloud.launcher spring-cloud-launcher-dataflow - 1.2.0.BUILD-SNAPSHOT jar spring-cloud-launcher-dataflow @@ -30,6 +29,10 @@ org.springframework.cloud spring-cloud-starter-eureka + + org.springframework.cloud + spring-cloud-task-batch + org.springframework.cloud spring-cloud-deployer-local @@ -38,6 +41,10 @@ org.springframework.cloud spring-cloud-dataflow-server-core + + org.springframework.cloud + spring-cloud-dataflow-server-core + org.springframework.boot spring-boot-starter-test 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 index cfbe078..3fe5331 100644 --- 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 @@ -6,9 +6,9 @@ eureka: 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@ + artifactId: "@project.artifactId@" + description: "@project.description@" + version: "@project.version@" security: basic: diff --git a/spring-cloud-launcher/spring-cloud-launcher-deployer/pom.xml b/spring-cloud-launcher/spring-cloud-launcher-deployer/pom.xml index 0652015..aa852b6 100644 --- a/spring-cloud-launcher/spring-cloud-launcher-deployer/pom.xml +++ b/spring-cloud-launcher/spring-cloud-launcher-deployer/pom.xml @@ -5,7 +5,6 @@ org.springframework.cloud.launcher spring-cloud-launcher-deployer - 1.2.0.BUILD-SNAPSHOT jar spring-cloud-launcher-deployer 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 index e63c1e5..b0cc736 100644 --- 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 @@ -37,10 +37,20 @@ public class DeployerProperties { @NotNull private List deploy = new ArrayList<>(); + private boolean list = false; + private int statusSleepMillis = 300; + public boolean isList() { + return this.list; + } + + public void setList(boolean list) { + this.list = list; + } + public List getDeployables() { - return deployables; + return this.deployables; } public void setDeployables(List deployables) { @@ -48,7 +58,7 @@ public class DeployerProperties { } public List getDeploy() { - return deploy; + return this.deploy; } public void setDeploy(List deploy) { @@ -56,7 +66,7 @@ public class DeployerProperties { } public int getStatusSleepMillis() { - return statusSleepMillis; + return this.statusSleepMillis; } public void setStatusSleepMillis(int statusSleepMillis) { @@ -66,9 +76,9 @@ public class DeployerProperties { @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("deployables=").append(this.deployables); + sb.append("deploy=").append(this.deploy); + sb.append("statusSleepMillis=").append(this.statusSleepMillis); sb.append('}'); return sb.toString(); } @@ -84,7 +94,7 @@ public class DeployerProperties { private String message; public String getCoordinates() { - return coordinates; + return this.coordinates; } public void setCoordinates(String coordinates) { @@ -92,7 +102,7 @@ public class DeployerProperties { } public String getName() { - return name; + return this.name; } public void setName(String name) { @@ -100,7 +110,7 @@ public class DeployerProperties { } public int getPort() { - return port; + return this.port; } public void setPort(int port) { @@ -108,7 +118,7 @@ public class DeployerProperties { } public boolean isWaitUntilStarted() { - return waitUntilStarted; + return this.waitUntilStarted; } public void setWaitUntilStarted(boolean waitUntilStarted) { @@ -117,7 +127,7 @@ public class DeployerProperties { @Override public int getOrder() { - return order; + return this.order; } public void setOrder(int order) { @@ -125,7 +135,7 @@ public class DeployerProperties { } public String getMessage() { - return message; + return this.message; } public void setMessage(String message) { @@ -135,12 +145,12 @@ public class DeployerProperties { @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("coordinates='").append(this.coordinates).append('\''); + sb.append(", name='").append(this.name).append('\''); + sb.append(", port=").append(this.port); + sb.append(", waitUntilStarted=").append(this.waitUntilStarted); + sb.append(", order=").append(this.order); + sb.append(", message=").append(this.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 index 506029b..55de321 100644 --- 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 @@ -16,16 +16,24 @@ package org.springframework.cloud.launcher.deployer; +import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.List; 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.bind.PropertiesConfigurationFactory; import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.env.YamlPropertySourceLoader; +import org.springframework.boot.logging.LogLevel; +import org.springframework.boot.logging.logback.LogbackLoggingSystem; import org.springframework.cloud.deployer.resource.support.DelegatingResourceLoader; import org.springframework.cloud.deployer.spi.app.AppDeployer; import org.springframework.cloud.deployer.spi.app.AppStatus; @@ -35,14 +43,17 @@ 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.env.PropertySource; +import org.springframework.core.env.StandardEnvironment; +import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; +import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; /** * @author Spencer Gibb */ -@SuppressWarnings("unused") public class DeployerThread extends Thread { private static final Logger logger = LoggerFactory.getLogger(DeployerThread.class); @@ -60,10 +71,58 @@ public class DeployerThread extends Thread { @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); + List list = Arrays.asList(this.args); + if (list.contains("--launcher.list=true")) { + quiet(); + list(); + } + else { + launch(); + } + } + + private void quiet() { + LogbackLoggingSystem.get(ClassUtils.getDefaultClassLoader()).setLogLevel("ROOT", LogLevel.OFF); + } + + private void list() { + StandardEnvironment environment = new StandardEnvironment(); + String path = "/cloud.yml"; + ClassPathResource resource = new ClassPathResource(path, DeployerThread.class); + if (resource.exists()) { + try { + PropertySource source = new YamlPropertySourceLoader().load(path, resource, null); + if (source != null) { + environment.getPropertySources().addLast(source); + } + } + catch (IOException e) { + } + } + DeployerProperties properties = new DeployerProperties(); + PropertiesConfigurationFactory factory = new PropertiesConfigurationFactory<>(properties); + factory.setTargetName("spring.cloud.launcher"); + factory.setPropertySources(environment.getPropertySources()); + try { + factory.afterPropertiesSet(); + properties = factory.getObject(); + } + catch (Exception e) { + } + if (!properties.getDeployables().isEmpty()) { + Collection names = new ArrayList<>(); + for (Deployable deployable : properties.getDeployables()) { + names.add(deployable.getName()); + } + System.out.println(StringUtils.collectionToDelimitedString(names, " ")); + } + } + + private void launch() { + + final ConfigurableApplicationContext context = new SpringApplicationBuilder( + PropertyPlaceholderAutoConfiguration.class, DeployerConfiguration.class).web(false) + .properties("spring.config.name=cloud", "banner.location=launcher-banner.txt").run(this.args); final AppDeployer deployer = context.getBean(AppDeployer.class); @@ -74,7 +133,7 @@ public class DeployerThread extends Thread { ArrayList deployables = new ArrayList<>(properties.getDeployables()); OrderComparator.sort(deployables); - logger.debug("toDeploy {}", properties.getDeployables()); + logger.debug("Deployables {}", properties.getDeployables()); for (Deployable deployable : deployables) { deploy(deployer, resourceLoader, deployable, properties); @@ -94,11 +153,11 @@ public class DeployerThread extends Thread { for (Deployable deployable : deployables) { if (shouldDeploy(deployable, properties) && StringUtils.hasText(deployable.getMessage())) { - logger.info("\n\n{}: {}\n", deployable.getName(), deployable.getMessage()); + System.out.println("\n\n" + deployable.getName() + ": " + deployable.getMessage() + "\n"); } } - logger.info("\n\nType Ctrl-C to quit.\n"); + System.out.println("\n\nType Ctrl-C to quit.\n"); while (true) { for (Map.Entry entry : this.deployed.entrySet()) { @@ -113,16 +172,16 @@ public class DeployerThread extends Thread { } try { Thread.sleep(properties.getStatusSleepMillis()); - } catch (InterruptedException e) { + } + catch (InterruptedException e) { logger.error("error sleeping", e); } } } - private String deploy(AppDeployer deployer, ResourceLoader resourceLoader, Deployable deployable, DeployerProperties properties) { + 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; } @@ -132,21 +191,25 @@ public class DeployerThread extends Thread { Map appDefProps = new HashMap<>(); appDefProps.put("server.port", String.valueOf(deployable.getPort())); - //TODO: move to notDeployedProps or something + // TODO: move to notDeployedProps or something if (!shouldDeploy("kafka", properties)) { appDefProps.put("spring.cloud.bus.enabled", Boolean.FALSE.toString()); } + if (!shouldDeploy("eureka", properties)) { + appDefProps.put("eureka.client.enabled", Boolean.FALSE.toString()); + } AppDefinition definition = new AppDefinition(deployable.getName(), appDefProps); - Map environmentProperties = Collections.singletonMap(AppDeployer.GROUP_PROPERTY_KEY, "launcher"); + 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) + // TODO: stream stdout/stderr like docker-compose (with colors and prefix) if (deployable.isWaitUntilStarted()) { try { @@ -158,7 +221,8 @@ public class DeployerThread extends Thread { appStatus = getAppStatus(deployer, id); logger.debug("State of {} = {}", id, appStatus.getState()); } - } catch (Exception e) { + } + catch (Exception e) { logger.error("error updating status of " + id, e); } } @@ -182,5 +246,4 @@ public class DeployerThread extends Thread { 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 index 63c61be..d7dc9bb 100644 --- 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 @@ -20,6 +20,7 @@ spring: - name: h2 coordinates: ${dt.pre}h2:${dt.ver} port: 9095 + message: Connect on jdbc:h2:tcp://localhost:9096/./target/test, web console at http://localhost:9095 waitUntilStarted: true order: -50 - name: hystrixdashboard @@ -30,4 +31,8 @@ spring: port: 9091 waitUntilStarted: true order: -200 - deploy: ${launch:configserver,eureka, hystrixdashboard} + - name: zipkin + coordinates: ${dt.pre}zipkin:${dt.ver} + port: 9411 + order: 0 + deploy: ${launcher.deploy:configserver,eureka} diff --git a/spring-cloud-launcher/spring-cloud-launcher-eureka/pom.xml b/spring-cloud-launcher/spring-cloud-launcher-eureka/pom.xml index b7ea80e..5d74679 100644 --- a/spring-cloud-launcher/spring-cloud-launcher-eureka/pom.xml +++ b/spring-cloud-launcher/spring-cloud-launcher-eureka/pom.xml @@ -5,7 +5,6 @@ org.springframework.cloud.launcher spring-cloud-launcher-eureka - 1.2.0.BUILD-SNAPSHOT jar spring-cloud-launcher-eureka 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 index b79d75c..71e0bab 100644 --- 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 @@ -10,6 +10,6 @@ eureka: waitTimeInMsWhenSyncEmpty: 0 info: - artifactId: @project.artifactId@ - description: @project.description@ - version: @project.version@ + artifactId: "@project.artifactId@" + description: "@project.description@" + version: "@project.version@" \ No newline at end of file diff --git a/spring-cloud-launcher/spring-cloud-launcher-h2/pom.xml b/spring-cloud-launcher/spring-cloud-launcher-h2/pom.xml index bed2405..e0e14da 100644 --- a/spring-cloud-launcher/spring-cloud-launcher-h2/pom.xml +++ b/spring-cloud-launcher/spring-cloud-launcher-h2/pom.xml @@ -5,7 +5,6 @@ org.springframework.cloud.launcher spring-cloud-launcher-h2 - 1.2.0.BUILD-SNAPSHOT jar spring-cloud-launcher-h2 @@ -22,6 +21,10 @@ com.h2database h2 + + org.springframework.boot + spring-boot-starter-web + org.springframework.boot spring-boot-starter-actuator @@ -34,10 +37,6 @@ org.springframework.cloud spring-cloud-starter-eureka - - org.springframework.cloud - spring-cloud-starter-bus-kafka - org.springframework.boot spring-boot-starter-test 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 index 653ba95..2b7c731 100644 --- 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 @@ -20,12 +20,15 @@ import java.util.concurrent.atomic.AtomicBoolean; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.h2.server.web.WebServlet; 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.boot.context.embedded.ServletRegistrationBean; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.context.SmartLifecycle; +import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Controller; import org.springframework.stereotype.Service; import org.springframework.util.Assert; @@ -39,20 +42,27 @@ import org.springframework.util.StringUtils; @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") + @Bean + public ServletRegistrationBean h2Console() { + String urlMapping = "/*"; + ServletRegistrationBean registration = new ServletRegistrationBean(new WebServlet(), urlMapping); + registration.addInitParameter("-webAllowOthers", ""); + return registration; + } @Service static class H2Server implements SmartLifecycle { private AtomicBoolean running = new AtomicBoolean(false); private Console console; - @Value("${spring.datasource.url:9096}") + @Value("${spring.datasource.url:jdbc:h2:tcp://localhost:9096/./target/test}") private String dataSourceUrl; @Override @@ -72,7 +82,7 @@ public class H2Application { try { log.info("Starting H2 Server"); this.console = new Console(); - this.console.runTool("-tcp", "-pg", "-web", "-tcpAllowOthers", "-tcpPort", getH2Port(dataSourceUrl)); + this.console.runTool("-tcp", "-tcpAllowOthers", "-tcpPort", getH2Port(this.dataSourceUrl)); } catch (Exception e) { ReflectionUtils.rethrowRuntimeException(e); } @@ -88,7 +98,7 @@ public class H2Application { @Override public void stop() { if (this.running.compareAndSet(true, false)) { - log.info("Stoping H2 Server"); + log.info("Stopping H2 Server"); this.console.shutdown(); } } 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 index 6994fba..5246752 100644 --- 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 @@ -2,12 +2,13 @@ server: port: 9095 info: - artifactId: @project.artifactId@ - description: @project.description@ - version: @project.version@ + 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 + non-secure-port: 9095 + status-page-url-path: / #allows you to click on the link in eureka dashboard + diff --git a/spring-cloud-launcher/spring-cloud-launcher-hystrixdashboard/pom.xml b/spring-cloud-launcher/spring-cloud-launcher-hystrixdashboard/pom.xml index 030c474..40e2e17 100644 --- a/spring-cloud-launcher/spring-cloud-launcher-hystrixdashboard/pom.xml +++ b/spring-cloud-launcher/spring-cloud-launcher-hystrixdashboard/pom.xml @@ -5,7 +5,6 @@ org.springframework.cloud.launcher spring-cloud-launcher-hystrixdashboard - 1.2.0.BUILD-SNAPSHOT jar spring-cloud-launcher-hystrixdashboard 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 index b6cd473..9813c16 100644 --- 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 @@ -6,6 +6,6 @@ eureka: 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@ + artifactId: "@project.artifactId@" + description: "@project.description@" + version: "@project.version@" \ No newline at end of file diff --git a/spring-cloud-launcher/spring-cloud-launcher-kafka/pom.xml b/spring-cloud-launcher/spring-cloud-launcher-kafka/pom.xml index 7ac132b..9c5a9cb 100644 --- a/spring-cloud-launcher/spring-cloud-launcher-kafka/pom.xml +++ b/spring-cloud-launcher/spring-cloud-launcher-kafka/pom.xml @@ -5,7 +5,6 @@ org.springframework.cloud.launcher spring-cloud-launcher-kafka - 1.2.0.BUILD-SNAPSHOT jar spring-cloud-launcher-kafka 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 index 8890030..528e258 100644 --- 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 @@ -8,6 +8,6 @@ zk: port: 2181 info: - artifactId: @project.artifactId@ - description: @project.description@ - version: @project.version@ + artifactId: "@project.artifactId@" + description: "@project.description@" + version: "@project.version@" \ No newline at end of file diff --git a/spring-cloud-launcher/spring-cloud-launcher-zipkin/.jdk8 b/spring-cloud-launcher/spring-cloud-launcher-zipkin/.jdk8 new file mode 100644 index 0000000..e69de29 diff --git a/spring-cloud-launcher/spring-cloud-launcher-zipkin/pom.xml b/spring-cloud-launcher/spring-cloud-launcher-zipkin/pom.xml new file mode 100644 index 0000000..6d27686 --- /dev/null +++ b/spring-cloud-launcher/spring-cloud-launcher-zipkin/pom.xml @@ -0,0 +1,55 @@ + + + 4.0.0 + + org.springframework.cloud.launcher + spring-cloud-launcher-zipkin + jar + + spring-cloud-launcher-zipkin + Spring Cloud Launcher ConfigServer + + + 1.8 + + + + 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 + + + io.zipkin.java + zipkin-autoconfigure-ui + + + io.zipkin.java + zipkin-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-zipkin/src/main/java/org/springframework/cloud/launcher/zipkin/ZipkinServerApplication.java b/spring-cloud-launcher/spring-cloud-launcher-zipkin/src/main/java/org/springframework/cloud/launcher/zipkin/ZipkinServerApplication.java new file mode 100644 index 0000000..e7ff302 --- /dev/null +++ b/spring-cloud-launcher/spring-cloud-launcher-zipkin/src/main/java/org/springframework/cloud/launcher/zipkin/ZipkinServerApplication.java @@ -0,0 +1,36 @@ +/* + * 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.zipkin; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; + +import zipkin.server.EnableZipkinServer; + +/** + * @author Spencer Gibb + */ +@EnableZipkinServer +@EnableDiscoveryClient +@SpringBootApplication +public class ZipkinServerApplication { + + public static void main(String[] args) { + SpringApplication.run(ZipkinServerApplication.class, args); + } +} diff --git a/spring-cloud-launcher/spring-cloud-launcher-zipkin/src/main/resources/application.yml b/spring-cloud-launcher/spring-cloud-launcher-zipkin/src/main/resources/application.yml new file mode 100644 index 0000000..6e31a29 --- /dev/null +++ b/spring-cloud-launcher/spring-cloud-launcher-zipkin/src/main/resources/application.yml @@ -0,0 +1,11 @@ +spring: + application: + name: zipkin + +server: + port: 9411 + +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-zipkin/src/main/resources/launcher/application.yml b/spring-cloud-launcher/spring-cloud-launcher-zipkin/src/main/resources/launcher/application.yml new file mode 100644 index 0000000..c6ba723 --- /dev/null +++ b/spring-cloud-launcher/spring-cloud-launcher-zipkin/src/main/resources/launcher/application.yml @@ -0,0 +1,29 @@ +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 + +h2.datasource.url: jdbc:h2:tcp://localhost:9096/~/launcher +#spring: +# datasource: +# url: ${h2.datasource.url} + +logging: + level: + kafka: WARN + org.apache.zookeeper: WARN + org.apache.zookeeper.ClientCnxn: ERROR + org.apache.kafka: WARN + org.I0Itec: WARN