Load application properties from <name>.yml

(also try config/<name>.yml). In this way user can easily launch config
server with custom uri, h2 with custom tcp endpoints, etc. The local
app deployer puts these properties in sys env vars (a bit yuck), but
that's not in our control here.
This commit is contained in:
Dave Syer
2016-08-15 15:34:52 +01:00
parent 0ca734895c
commit 1a28da5d83
2 changed files with 96 additions and 30 deletions

View File

@@ -9,7 +9,8 @@ eureka:
defaultZone: http://localhost:8761/eureka/ defaultZone: http://localhost:8761/eureka/
endpoints: endpoints:
restart: enabled restart:
enabled: true
ribbon: ribbon:
ConnectTimeout: 3000 ConnectTimeout: 3000

View File

@@ -22,6 +22,7 @@ import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@@ -44,9 +45,11 @@ import org.springframework.cloud.launcher.deployer.DeployerProperties.Deployable
import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.OrderComparator; import org.springframework.core.OrderComparator;
import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.EnumerablePropertySource;
import org.springframework.core.env.PropertySource; import org.springframework.core.env.PropertySource;
import org.springframework.core.env.StandardEnvironment; import org.springframework.core.env.StandardEnvironment;
import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader; import org.springframework.core.io.ResourceLoader;
import org.springframework.util.ClassUtils; import org.springframework.util.ClassUtils;
@@ -83,25 +86,16 @@ public class DeployerThread extends Thread {
} }
private void quiet() { private void quiet() {
LogbackLoggingSystem.get(ClassUtils.getDefaultClassLoader()).setLogLevel("ROOT", LogLevel.OFF); LogbackLoggingSystem.get(ClassUtils.getDefaultClassLoader()).setLogLevel("ROOT",
LogLevel.OFF);
} }
private void list() { private void list() {
StandardEnvironment environment = new StandardEnvironment(); StandardEnvironment environment = new StandardEnvironment();
String path = "/cloud.yml"; loadCloudProperties(environment);
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(); DeployerProperties properties = new DeployerProperties();
PropertiesConfigurationFactory<DeployerProperties> factory = new PropertiesConfigurationFactory<>(properties); PropertiesConfigurationFactory<DeployerProperties> factory = new PropertiesConfigurationFactory<>(
properties);
factory.setTargetName("spring.cloud.launcher"); factory.setTargetName("spring.cloud.launcher");
factory.setPropertySources(environment.getPropertySources()); factory.setPropertySources(environment.getPropertySources());
try { try {
@@ -119,11 +113,68 @@ public class DeployerThread extends Thread {
} }
} }
private void loadCloudProperties(StandardEnvironment environment) {
String path = "/cloud.yml";
PropertySource<?> source = extractPropertySource(path);
if (source != null) {
environment.getPropertySources().addLast(source);
}
}
private Map<String, String> extractProperties(String path) {
PropertySource<?> source = extractPropertySource(path);
Map<String, String> map = new LinkedHashMap<String, String>();
if (source instanceof EnumerablePropertySource) {
EnumerablePropertySource<?> enumerable = (EnumerablePropertySource<?>) source;
for (String name : enumerable.getPropertyNames()) {
map.put(name, source.getProperty(name) == null ? null
: source.getProperty(name).toString());
}
}
return map;
}
private PropertySource<?> extractPropertySource(String path) {
PropertySource<?> source = null;
Resource resource = new ClassPathResource("config/" + path, DeployerThread.class);
source = loadPropertySource(resource, path);
if (source==null) {
resource = new ClassPathResource(path, DeployerThread.class);
source = loadPropertySource(resource, path);
}
if (source==null) {
resource = new FileSystemResource("config/" + path);
source = loadPropertySource(resource, path);
}
if (source==null) {
resource = new FileSystemResource(path);
source = loadPropertySource(resource, path);
}
return source;
}
private PropertySource<?> loadPropertySource(Resource resource, String path) {
if (resource.exists()) {
try {
PropertySource<?> source = new YamlPropertySourceLoader().load(path, resource, null);
if (source!=null) {
logger.info("Loaded YAML properties from: " + resource);
}
return source;
}
catch (IOException e) {
}
}
return null;
}
private void launch() { private void launch() {
final ConfigurableApplicationContext context = new SpringApplicationBuilder( final ConfigurableApplicationContext context = new SpringApplicationBuilder(
PropertyPlaceholderAutoConfiguration.class, DeployerConfiguration.class).web(false) PropertyPlaceholderAutoConfiguration.class, DeployerConfiguration.class)
.properties("spring.config.name=cloud", "banner.location=launcher-banner.txt").run(this.args); .web(false).properties("spring.config.name=cloud",
"banner.location=launcher-banner.txt")
.run(this.args);
final AppDeployer deployer = context.getBean(AppDeployer.class); final AppDeployer deployer = context.getBean(AppDeployer.class);
@@ -137,7 +188,8 @@ public class DeployerThread extends Thread {
logger.debug("Deployables {}", properties.getDeployables()); logger.debug("Deployables {}", properties.getDeployables());
for (Deployable deployable : deployables) { for (Deployable deployable : deployables) {
deploy(deployer, resourceLoader, deployable, properties, context.getEnvironment()); deploy(deployer, resourceLoader, deployable, properties,
context.getEnvironment());
} }
Runtime.getRuntime().addShutdownHook(new Thread() { Runtime.getRuntime().addShutdownHook(new Thread() {
@@ -153,8 +205,10 @@ public class DeployerThread extends Thread {
}); });
for (Deployable deployable : deployables) { for (Deployable deployable : deployables) {
if (shouldDeploy(deployable, properties) && StringUtils.hasText(deployable.getMessage())) { if (shouldDeploy(deployable, properties)
System.out.println("\n\n" + deployable.getName() + ": " + deployable.getMessage() + "\n"); && StringUtils.hasText(deployable.getMessage())) {
System.out.println("\n\n" + deployable.getName() + ": "
+ deployable.getMessage() + "\n");
} }
} }
@@ -180,27 +234,35 @@ public class DeployerThread extends Thread {
} }
} }
private String deploy(AppDeployer deployer, ResourceLoader resourceLoader, Deployable deployable, private String deploy(AppDeployer deployer, ResourceLoader resourceLoader,
DeployerProperties properties, ConfigurableEnvironment environment) { Deployable deployable, DeployerProperties properties,
ConfigurableEnvironment environment) {
if (!shouldDeploy(deployable, properties)) { if (!shouldDeploy(deployable, properties)) {
return null; return null;
} }
logger.debug("getting resource {} = {}", deployable.getName(), deployable.getCoordinates()); logger.debug("getting resource {} = {}", deployable.getName(),
deployable.getCoordinates());
Resource resource = resourceLoader.getResource(deployable.getCoordinates()); Resource resource = resourceLoader.getResource(deployable.getCoordinates());
Map<String, String> appDefProps = new HashMap<>(); Map<String, String> appDefProps = new HashMap<>();
appDefProps.put("server.port", String.valueOf(deployable.getPort())); appDefProps.put("server.port", String.valueOf(deployable.getPort()));
// TODO: move to notDeployedProps or something // TODO: move to notDeployedProps or something
// these could be part of a collection of an interface to augment properties based on conditions // these could be part of a collection of an interface to augment properties based
// on conditions
if (!shouldDeploy("kafka", properties)) { if (!shouldDeploy("kafka", properties)) {
appDefProps.put("spring.cloud.bus.enabled", Boolean.FALSE.toString()); appDefProps.put("spring.cloud.bus.enabled", Boolean.FALSE.toString());
} }
if (!shouldDeploy("eureka", properties)) { if (!shouldDeploy("eureka", properties)) {
appDefProps.put("eureka.client.enabled", Boolean.FALSE.toString()); appDefProps.put("eureka.client.enabled", Boolean.FALSE.toString());
} }
if (deployable.getName().equals("configserver") && environment.containsProperty("git.uri")) { Map<String, String> map = extractProperties(deployable.getName() + ".yml");
for (String key : map.keySet()) {
appDefProps.put(key, map.get(key));
}
if (deployable.getName().equals("configserver")
&& environment.containsProperty("git.uri")) {
appDefProps.put("spring.profiles.active", "git"); appDefProps.put("spring.profiles.active", "git");
appDefProps.put("spring.cloud.config.server.git.uri", appDefProps.put("spring.cloud.config.server.git.uri",
environment.getRequiredProperty("git.uri")); environment.getRequiredProperty("git.uri"));
@@ -208,14 +270,16 @@ public class DeployerThread extends Thread {
AppDefinition definition = new AppDefinition(deployable.getName(), appDefProps); AppDefinition definition = new AppDefinition(deployable.getName(), appDefProps);
Map<String, String> environmentProperties = Collections.singletonMap(AppDeployer.GROUP_PROPERTY_KEY, Map<String, String> environmentProperties = Collections
"launcher"); .singletonMap(AppDeployer.GROUP_PROPERTY_KEY, "launcher");
AppDeploymentRequest request = new AppDeploymentRequest(definition, resource, environmentProperties); AppDeploymentRequest request = new AppDeploymentRequest(definition, resource,
environmentProperties);
logger.debug("deploying resource {} = {}", deployable.getName(), deployable.getCoordinates()); logger.debug("Deploying resource {} = {}", deployable.getName(),
deployable.getCoordinates());
logger.debug("Properties: {}", appDefProps);
String id = deployer.deploy(request); String id = deployer.deploy(request);
AppStatus appStatus = getAppStatus(deployer, id); 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()) { if (deployable.isWaitUntilStarted()) {
@@ -233,6 +297,7 @@ public class DeployerThread extends Thread {
logger.error("error updating status of " + id, e); logger.error("error updating status of " + id, e);
} }
} }
logger.info("Status of {}: {}", id, appStatus);
return id; return id;
} }