Merge remote-tracking branch 'upstream/master'
updating fork from master
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
// Do not edit this file (e.g. go instead to src/main/asciidoc)
|
||||
|
||||
image::https://circleci.com/gh/spring-cloud/spring-cloud-config/tree/master.svg?style=svg["CircleCI", link="https://circleci.com/gh/spring-cloud/spring-cloud-config/tree/master"]
|
||||
image::https://codecov.io/gh/spring-cloud/spring-cloud-config/branch/master/graph/badge.svg["Codecov", link="https://codecov.io/gh/spring-cloud/spring-cloud-config/branch/master"]
|
||||
image::https://api.codacy.com/project/badge/Grade/f064024a072c477e97dca6ed5a70fccd?branch=master["Codacy code quality", link="https://www.codacy.com/app/Spring-Cloud/spring-cloud-config?branch=master&utm_source=github.com&utm_medium=referral&utm_content=spring-cloud/spring-cloud-config&utm_campaign=Badge_Grade"]
|
||||
|
||||
|
||||
Spring Cloud Config provides server and client-side support for externalized configuration in a distributed system. With the Config Server you have a central place to manage external properties for applications across all environments. The concepts on both client and server map identically to the Spring `Environment` and `PropertySource` abstractions, so they fit very well with Spring applications, but can be used with any application running in any language. As an application moves through the deployment pipeline from dev to test and into production you can manage the configuration between those environments and be certain that applications have everything they need to run when they migrate. The default implementation of the server storage backend uses git so it easily supports labelled versions of configuration environments, as well as being accessible to a wide range of tooling for managing the content. It is easy to add alternative implementations and plug them in with Spring configuration.
|
||||
|
||||
|
||||
26
circle.yml
Normal file
26
circle.yml
Normal file
@@ -0,0 +1,26 @@
|
||||
general:
|
||||
branches:
|
||||
ignore:
|
||||
- gh-pages # list of branches to ignore
|
||||
machine:
|
||||
java:
|
||||
version: openjdk8 #Open JDK has the JCE extentions installed by default
|
||||
environment:
|
||||
_JAVA_OPTIONS: "-Xms1024m -Xmx2048m"
|
||||
dependencies:
|
||||
override:
|
||||
- ./mvnw -s .settings.xml -U --fail-never dependency:go-offline || true
|
||||
test:
|
||||
override:
|
||||
- ./mvnw -s .settings.xml clean install org.jacoco:jacoco-maven-plugin:prepare-agent install -U -P sonar -nsu --batch-mode -Dmaven.test.redirectTestOutputToFile=true -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn
|
||||
post:
|
||||
- find . -type f -regex ".*/spring-cloud-*.*/target/*.*" | cpio -pdm $CIRCLE_ARTIFACTS
|
||||
- mkdir -p $CIRCLE_TEST_REPORTS/junit/
|
||||
- find . -type f -regex ".*/target/.*-reports/.*" -exec cp {} $CIRCLE_TEST_REPORTS/junit/ \;
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
|
||||
notify:
|
||||
webhooks:
|
||||
# A list of hook hashes, containing the url field
|
||||
# gitter hook
|
||||
- url: https://webhooks.gitter.im/e/5de9034d65b40fc39d61
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-config</artifactId>
|
||||
<version>1.2.0.BUILD-SNAPSHOT</version>
|
||||
<version>1.2.2.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
<packaging>pom</packaging>
|
||||
<name>Spring Cloud Config Docs</name>
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
image::https://circleci.com/gh/spring-cloud/spring-cloud-config/tree/master.svg?style=svg["CircleCI", link="https://circleci.com/gh/spring-cloud/spring-cloud-config/tree/master"]
|
||||
image::https://codecov.io/gh/spring-cloud/spring-cloud-config/branch/master/graph/badge.svg["Codecov", link="https://codecov.io/gh/spring-cloud/spring-cloud-config/branch/master"]
|
||||
image::https://api.codacy.com/project/badge/Grade/f064024a072c477e97dca6ed5a70fccd?branch=master["Codacy code quality", link="https://www.codacy.com/app/Spring-Cloud/spring-cloud-config?branch=master&utm_source=github.com&utm_medium=referral&utm_content=spring-cloud/spring-cloud-config&utm_campaign=Badge_Grade"]
|
||||
|
||||
include::intro.adoc[]
|
||||
|
||||
@@ -76,7 +79,7 @@ http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.ht
|
||||
|
||||
http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html[Java 7 JCE]
|
||||
|
||||
http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html[Java 8 JCE]
|
||||
http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html[Java 8 JCE]
|
||||
|
||||
Extract files into JDK/jre/lib/security folder (whichever version of JRE/JDK x64/x86 you are using).
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
:toc:
|
||||
:nofooter:
|
||||
|
||||
*{spring-cloud-version}*
|
||||
|
||||
include::intro.adoc[]
|
||||
|
||||
== Quick Start
|
||||
@@ -1160,10 +1162,58 @@ spring:
|
||||
|
||||
----
|
||||
|
||||
If you use another form of security you might need to provide a
|
||||
`RestTemplate` to the `ConfigServicePropertySourceLocator` (e.g. by
|
||||
If you use another form of security you might need to <<custom-rest-template,provide a
|
||||
`RestTemplate`>> to the `ConfigServicePropertySourceLocator` (e.g. by
|
||||
grabbing it in the bootstrap context and injecting one).
|
||||
|
||||
==== Health Indicator
|
||||
|
||||
The Config Client supplies a Spring Boot Health Indicator that attempts to load configuration from Config Server. The health indicator can be disabled by setting `health.config.enabled=false`. The response is also cached for performance reasons. The default cache time to live is 5 minutes. To change that value set the `health.config.time-to-live` property (in milliseconds).
|
||||
|
||||
[[custom-rest-template]]
|
||||
==== Providing A Custom RestTemplate
|
||||
|
||||
In some cases you might need to customize the requests made to the config server from
|
||||
the client. Typically this involves passing special `Authorization` headers to
|
||||
authenticate requests to the server. To provide a custom `RestTemplate` follow the
|
||||
steps below.
|
||||
|
||||
1. Set `spring.cloud.config.enabled=false` to disable the existing config server
|
||||
property source.
|
||||
|
||||
2. Create a new configuration bean with an implementation of `PropertySourceLocator`.
|
||||
|
||||
.CustomConfigServiceBootstrapConfiguration.java
|
||||
[source,java]
|
||||
----
|
||||
@Configuration
|
||||
public class CustomConfigServiceBootstrapConfiguration {
|
||||
@Bean
|
||||
public ConfigClientProperties configClientProperties() {
|
||||
ConfigClientProperties client = new ConfigClientProperties(this.environment);
|
||||
client.setEnabled(false);
|
||||
return client;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ConfigServicePropertySourceLocator configServicePropertySourceLocator() {
|
||||
ConfigClientProperties clientProperties = configClientProperties();
|
||||
ConfigServicePropertySourceLocator configServicePropertySourceLocator = new ConfigServicePropertySourceLocator(clientProperties);
|
||||
configServicePropertySourceLocator.setRestTemplate(customRestTemplate(clientProperties));
|
||||
return configServicePropertySourceLocator;
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
3. In `resources/META-INF` create a file called
|
||||
`spring.factories` and specify your custom configuration.
|
||||
|
||||
.spring.factorties
|
||||
[source,properties]
|
||||
----
|
||||
org.springframework.cloud.bootstrap.BootstrapConfiguration = com.my.config.client.CustomConfigServiceBootstrapConfiguration
|
||||
----
|
||||
|
||||
==== Vault
|
||||
|
||||
When using Vault as a backend to your config server the client will need to
|
||||
|
||||
9
mvnw
vendored
9
mvnw
vendored
@@ -226,11 +226,9 @@ export MAVEN_CMD_LINE_ARGS
|
||||
|
||||
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
VERSION=$(exec "$JAVACMD" \
|
||||
$MAVEN_OPTS \
|
||||
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
|
||||
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
|
||||
-Dexec.executable="echo" -Dexec.args='${project.version}' ${WRAPPER_LAUNCHER} -q --non-recursive org.codehaus.mojo:exec-maven-plugin:1.3.1:exec )
|
||||
echo "Running version check"
|
||||
VERSION=$( sed '\!<parent!,\!</parent!d' `dirname $0`/pom.xml | grep '<version' | head -1 | sed -e 's/.*<version>//' -e 's!</version>.*$!!' )
|
||||
echo "The found version is [${VERSION}]"
|
||||
|
||||
if echo $VERSION | egrep -q 'M|RC'; then
|
||||
echo Activating \"milestone\" profile for version=\"$VERSION\"
|
||||
@@ -240,7 +238,6 @@ else
|
||||
echo $MAVEN_ARGS | grep -q milestone && MAVEN_ARGS=$(echo $MAVEN_ARGS | sed -e 's/-Pmilestone//')
|
||||
fi
|
||||
|
||||
|
||||
exec "$JAVACMD" \
|
||||
$MAVEN_OPTS \
|
||||
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
|
||||
|
||||
54
pom.xml
54
pom.xml
@@ -3,7 +3,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-config</artifactId>
|
||||
<version>1.2.0.BUILD-SNAPSHOT</version>
|
||||
<version>1.2.2.BUILD-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>Spring Cloud Config</name>
|
||||
<description>Spring Cloud Config</description>
|
||||
@@ -11,7 +11,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-build</artifactId>
|
||||
<version>1.2.0.RELEASE</version>
|
||||
<version>1.2.2.BUILD-SNAPSHOT</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<scm>
|
||||
@@ -22,6 +22,7 @@
|
||||
</scm>
|
||||
<properties>
|
||||
<bintray.package>config</bintray.package>
|
||||
<spring-cloud-commons.version>1.1.5.BUILD-SNAPSHOT</spring-cloud-commons.version>
|
||||
</properties>
|
||||
<modules>
|
||||
<module>spring-cloud-config-dependencies</module>
|
||||
@@ -41,6 +42,13 @@
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-commons-dependencies</artifactId>
|
||||
<version>${spring-cloud-commons.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
<profiles>
|
||||
@@ -105,5 +113,47 @@
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>sonar</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.jacoco</groupId>
|
||||
<artifactId>jacoco-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>pre-unit-test</id>
|
||||
<goals>
|
||||
<goal>prepare-agent</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<propertyName>surefireArgLine</propertyName>
|
||||
<destFile>${project.build.directory}/jacoco.exec</destFile>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>post-unit-test</id>
|
||||
<phase>test</phase>
|
||||
<goals>
|
||||
<goal>report</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<!-- Sets the path to the file which contains the execution data. -->
|
||||
<dataFile>${project.build.directory}/jacoco.exec</dataFile>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<!-- Sets the VM argument line used when unit tests are run. -->
|
||||
<argLine>${surefireArgLine}</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-config</artifactId>
|
||||
<version>1.2.0.BUILD-SNAPSHOT</version>
|
||||
<version>1.2.2.BUILD-SNAPSHOT</version>
|
||||
<relativePath>..</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -53,6 +53,11 @@ public class ConfigClientAutoConfiguration {
|
||||
return client;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ConfigClientHealthProperties configClientHealthProperties() {
|
||||
return new ConfigClientHealthProperties();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnClass(HealthIndicator.class)
|
||||
@ConditionalOnBean(ConfigServicePropertySourceLocator.class)
|
||||
@@ -61,24 +66,9 @@ public class ConfigClientAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
public ConfigServerHealthIndicator configServerHealthIndicator(
|
||||
ConfigServicePropertySourceLocator locator, Environment environment) {
|
||||
return new ConfigServerHealthIndicator(locator, environment);
|
||||
}
|
||||
}
|
||||
|
||||
@ConfigurationProperties("health.config")
|
||||
public static class Health {
|
||||
/**
|
||||
* Flag to indicate that the config server health indicator should be installed.
|
||||
*/
|
||||
boolean enabled;
|
||||
|
||||
public boolean isEnabled() {
|
||||
return this.enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
ConfigServicePropertySourceLocator locator,
|
||||
ConfigClientHealthProperties properties, Environment environment) {
|
||||
return new ConfigServerHealthIndicator(locator, environment, properties);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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.config.client;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@ConfigurationProperties("health.config")
|
||||
public class ConfigClientHealthProperties {
|
||||
/**
|
||||
* Flag to indicate that the config server health indicator should be installed.
|
||||
*/
|
||||
boolean enabled;
|
||||
|
||||
/**
|
||||
* Time to live for cached result, in milliseconds. Default 300000 (5 min).
|
||||
*/
|
||||
private long timeToLive = 60 * 5 * 1000;
|
||||
|
||||
public boolean isEnabled() {
|
||||
return this.enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public long getTimeToLive() {
|
||||
return timeToLive;
|
||||
}
|
||||
|
||||
public void setTimeToLive(long timeToLive) {
|
||||
this.timeToLive = timeToLive;
|
||||
}
|
||||
}
|
||||
@@ -16,17 +16,23 @@ import org.springframework.core.env.PropertySource;
|
||||
public class ConfigServerHealthIndicator extends AbstractHealthIndicator {
|
||||
|
||||
private ConfigServicePropertySourceLocator locator;
|
||||
private ConfigClientHealthProperties properties;
|
||||
private Environment environment;
|
||||
|
||||
private long lastAccess = 0;
|
||||
|
||||
private PropertySource<?> cached;
|
||||
|
||||
public ConfigServerHealthIndicator(ConfigServicePropertySourceLocator locator,
|
||||
Environment environment) {
|
||||
Environment environment, ConfigClientHealthProperties properties) {
|
||||
this.environment = environment;
|
||||
this.locator = locator;
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doHealthCheck(Builder builder) throws Exception {
|
||||
PropertySource<?> propertySource = locator.locate(this.environment);
|
||||
PropertySource<?> propertySource = getPropertySource();
|
||||
builder.up();
|
||||
if (propertySource instanceof CompositePropertySource) {
|
||||
List<String> sources = new ArrayList<>();
|
||||
@@ -40,4 +46,21 @@ public class ConfigServerHealthIndicator extends AbstractHealthIndicator {
|
||||
builder.unknown().withDetail("error", "no property sources located");
|
||||
}
|
||||
}
|
||||
|
||||
private PropertySource<?> getPropertySource() {
|
||||
long accessTime = System.currentTimeMillis();
|
||||
if (isCacheStale(accessTime)) {
|
||||
this.lastAccess = accessTime;
|
||||
this.cached = locator.locate(this.environment);
|
||||
}
|
||||
return this.cached;
|
||||
}
|
||||
|
||||
private boolean isCacheStale(long accessTime) {
|
||||
if (this.cached == null) {
|
||||
return true;
|
||||
}
|
||||
return (accessTime - this.lastAccess) >= this.properties.getTimeToLive();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,11 +17,16 @@
|
||||
package org.springframework.cloud.config.client;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Mockito.any;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.boot.actuate.health.Status;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.MapPropertySource;
|
||||
@@ -34,11 +39,11 @@ import org.springframework.core.env.PropertySource;
|
||||
*/
|
||||
public class ConfigServerHealthIndicatorTests {
|
||||
|
||||
private ConfigServicePropertySourceLocator locator = Mockito
|
||||
.mock(ConfigServicePropertySourceLocator.class);
|
||||
private Environment environment = Mockito.mock(Environment.class);
|
||||
private ConfigServicePropertySourceLocator locator =
|
||||
mock(ConfigServicePropertySourceLocator.class);
|
||||
private Environment environment = mock(Environment.class);
|
||||
private ConfigServerHealthIndicator indicator = new ConfigServerHealthIndicator(
|
||||
locator, environment);
|
||||
locator, environment, new ConfigClientHealthProperties());
|
||||
|
||||
@Test
|
||||
public void testDefaultStatus() {
|
||||
@@ -48,15 +53,32 @@ public class ConfigServerHealthIndicatorTests {
|
||||
|
||||
@Test
|
||||
public void testExceptionStatus() {
|
||||
Mockito.doThrow(new IllegalStateException()).when(locator).locate(Mockito.any(Environment.class));
|
||||
doThrow(new IllegalStateException()).when(locator).locate(any(Environment.class));
|
||||
assertEquals(Status.DOWN, indicator.health().getStatus());
|
||||
verify(locator, times(1)).locate(any(Environment.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServerUp() {
|
||||
PropertySource<?> source = new MapPropertySource("foo", Collections.<String,Object>emptyMap());
|
||||
Mockito.doReturn(source).when(locator).locate(Mockito.any(Environment.class));
|
||||
doReturn(source).when(locator).locate(any(Environment.class));
|
||||
assertEquals(Status.UP, indicator.health().getStatus());
|
||||
verify(locator, times(1)).locate(any(Environment.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void healthIsCached() {
|
||||
PropertySource<?> source = new MapPropertySource("foo", Collections.<String,Object>emptyMap());
|
||||
doReturn(source).when(locator).locate(any(Environment.class));
|
||||
|
||||
// not cached
|
||||
assertEquals(Status.UP, indicator.health().getStatus());
|
||||
|
||||
// cached
|
||||
assertEquals(Status.UP, indicator.health().getStatus());
|
||||
|
||||
verify(locator, times(1)).locate(any(Environment.class));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -5,45 +5,35 @@
|
||||
<parent>
|
||||
<artifactId>spring-cloud-dependencies-parent</artifactId>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<version>1.2.0.BUILD-SNAPSHOT</version>
|
||||
<version>1.2.2.BUILD-SNAPSHOT</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
<artifactId>spring-cloud-config-dependencies</artifactId>
|
||||
<version>1.2.0.BUILD-SNAPSHOT</version>
|
||||
<version>1.2.2.BUILD-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>spring-cloud-config-dependencies</name>
|
||||
<description>Spring Cloud Config Dependencies</description>
|
||||
<properties>
|
||||
<spring-cloud-commons.version>1.1.2.BUILD-SNAPSHOT</spring-cloud-commons.version>
|
||||
</properties>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-commons-dependencies</artifactId>
|
||||
<version>${spring-cloud-commons.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-config</artifactId>
|
||||
<version>1.2.0.BUILD-SNAPSHOT</version>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-config-client</artifactId>
|
||||
<version>1.2.0.BUILD-SNAPSHOT</version>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-config-server</artifactId>
|
||||
<version>1.2.0.BUILD-SNAPSHOT</version>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-config-monitor</artifactId>
|
||||
<version>1.2.0.BUILD-SNAPSHOT</version>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jgit</groupId>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-config</artifactId>
|
||||
<version>1.2.0.BUILD-SNAPSHOT</version>
|
||||
<version>1.2.2.BUILD-SNAPSHOT</version>
|
||||
<relativePath>..</relativePath>
|
||||
</parent>
|
||||
<artifactId>spring-cloud-config-monitor</artifactId>
|
||||
@@ -13,7 +13,7 @@
|
||||
<description>Spring Cloud Config Monitor</description>
|
||||
<properties>
|
||||
<main.basedir>${basedir}/../..</main.basedir>
|
||||
<spring-cloud-bus.version>1.2.0.BUILD-SNAPSHOT</spring-cloud-bus.version>
|
||||
<spring-cloud-bus.version>1.2.2.BUILD-SNAPSHOT</spring-cloud-bus.version>
|
||||
</properties>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
|
||||
@@ -36,7 +36,8 @@ public class BitbucketPropertyPathNotificationExtractor
|
||||
@Override
|
||||
public PropertyPathNotification extract(MultiValueMap<String, String> headers,
|
||||
Map<String, Object> request) {
|
||||
if ("repo:push".equals(headers.getFirst("X-Event-Key")) &&
|
||||
if (("repo:push".equals(headers.getFirst("X-Event-Key")) ||
|
||||
"pullrequest:fulfilled".equals(headers.getFirst("X-Event-Key"))) &&
|
||||
StringUtils.hasText(headers.getFirst("X-Hook-UUID"))) {
|
||||
Object push = request.get("push");
|
||||
if (push instanceof Map && ((Map<?,?>)push).get("changes") instanceof Collection) {
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* @author Will Boyd
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@@ -42,22 +43,27 @@ public class EnvironmentMonitorAutoConfiguration {
|
||||
return new PropertyPathEndpoint(new CompositePropertyPathNotificationExtractor(this.extractors));
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(value="spring.cloud.config.server.monitor.github.enabled", havingValue="true", matchIfMissing=true)
|
||||
public GithubPropertyPathNotificationExtractor githubPropertyPathNotificationExtractor() {
|
||||
return new GithubPropertyPathNotificationExtractor();
|
||||
}
|
||||
@Configuration
|
||||
protected static class PropertyPathNotificationExtractorConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(value="spring.cloud.config.server.monitor.gitlab.enabled", havingValue="true", matchIfMissing=true)
|
||||
public GitlabPropertyPathNotificationExtractor gitlabPropertyPathNotificationExtractor() {
|
||||
return new GitlabPropertyPathNotificationExtractor();
|
||||
}
|
||||
@Bean
|
||||
@ConditionalOnProperty(value="spring.cloud.config.server.monitor.github.enabled", havingValue="true", matchIfMissing=true)
|
||||
public GithubPropertyPathNotificationExtractor githubPropertyPathNotificationExtractor() {
|
||||
return new GithubPropertyPathNotificationExtractor();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(value="spring.cloud.config.server.monitor.gitlab.enabled", havingValue="true", matchIfMissing=true)
|
||||
public GitlabPropertyPathNotificationExtractor gitlabPropertyPathNotificationExtractor() {
|
||||
return new GitlabPropertyPathNotificationExtractor();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(value="spring.cloud.config.server.monitor.bitbucket.enabled", havingValue="true", matchIfMissing=true)
|
||||
public BitbucketPropertyPathNotificationExtractor bitbucketPropertyPathNotificationExtractor() {
|
||||
return new BitbucketPropertyPathNotificationExtractor();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(value="spring.cloud.config.server.monitor.bitbucket.enabled", havingValue="true", matchIfMissing=true)
|
||||
public BitbucketPropertyPathNotificationExtractor bitbucketPropertyPathNotificationExtractor() {
|
||||
return new BitbucketPropertyPathNotificationExtractor();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -200,7 +200,7 @@ public class FileMonitorConfiguration implements SmartLifecycle, ResourceLoaderA
|
||||
try {
|
||||
paths.add(Paths.get(resource.getURI()));
|
||||
}
|
||||
catch (IOException e) {
|
||||
catch (Exception e) {
|
||||
log.error("Cannot resolve URI for path: " + path);
|
||||
}
|
||||
}
|
||||
@@ -301,8 +301,14 @@ public class FileMonitorConfiguration implements SmartLifecycle, ResourceLoaderA
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("registering: " + dir + " for file creation events");
|
||||
}
|
||||
try {
|
||||
dir.register(this.watcher, StandardWatchEventKinds.ENTRY_CREATE,
|
||||
StandardWatchEventKinds.ENTRY_MODIFY);
|
||||
} catch (IOException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new IOException("Cannot register watcher for " + dir, e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -50,6 +50,16 @@ public class BitbucketPropertyPathNotificationExtractorTests {
|
||||
assertNotNull(extracted);
|
||||
assertEquals("application.yml", extracted.getPaths()[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bitbucketPullRequestFulfillmentDetected() throws Exception {
|
||||
// https://confluence.atlassian.com/bitbucket/event-payloads-740262817.html#EventPayloads-Merged
|
||||
Map<String, Object> value = readPayload("bitbucket.json");
|
||||
setHeaders("pullrequest:fulfilled");
|
||||
PropertyPathNotification extracted = this.extractor.extract(this.headers, value);
|
||||
assertNotNull(extracted);
|
||||
assertEquals("application.yml", extracted.getPaths()[0]);
|
||||
}
|
||||
|
||||
private void setHeaders(String eventKey) {
|
||||
this.headers.set("X-Event-Key", eventKey);
|
||||
@@ -57,7 +67,7 @@ public class BitbucketPropertyPathNotificationExtractorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void notAPushNotDetected() throws Exception {
|
||||
public void notAPushOrPullRequestNotDetected() throws Exception {
|
||||
assertNotExtracted("bitbucket.json", "issue:created");
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.springframework.cloud.config.monitor;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
|
||||
@@ -26,7 +27,10 @@ import org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoCo
|
||||
import org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
@@ -48,5 +52,34 @@ public class EnvironmentMonitorAutoConfigurationTests {
|
||||
"extractors")).size());
|
||||
context.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCanAddCustomPropertyPathNotificationExtractor() {
|
||||
ConfigurableApplicationContext context = new SpringApplicationBuilder(
|
||||
CustomPropertyPathNotificationExtractorConfig.class,
|
||||
EnvironmentMonitorAutoConfiguration.class,
|
||||
EmbeddedServletContainerAutoConfiguration.class, ServerPropertiesAutoConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class).properties("server.port=-1")
|
||||
.run();
|
||||
PropertyPathEndpoint endpoint = context.getBean(PropertyPathEndpoint.class);
|
||||
assertEquals(5,
|
||||
((Collection<?>) ReflectionTestUtils.getField(
|
||||
ReflectionTestUtils.getField(endpoint, "extractor"),
|
||||
"extractors")).size());
|
||||
context.close();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class CustomPropertyPathNotificationExtractorConfig {
|
||||
@Bean
|
||||
public PropertyPathNotificationExtractor customNotificationExtractor() {
|
||||
return new PropertyPathNotificationExtractor() {
|
||||
@Override
|
||||
public PropertyPathNotification extract(MultiValueMap<String, String> headers, Map<String, Object> payload) {
|
||||
throw new UnsupportedOperationException("doesn't do anything");
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-config</artifactId>
|
||||
<version>1.2.0.BUILD-SNAPSHOT</version>
|
||||
<version>1.2.2.BUILD-SNAPSHOT</version>
|
||||
<relativePath>..</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-config</artifactId>
|
||||
<version>1.2.0.BUILD-SNAPSHOT</version>
|
||||
<version>1.2.2.BUILD-SNAPSHOT</version>
|
||||
<relativePath>..</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ import org.springframework.context.annotation.Import;
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Import({ EnvironmentRepositoryConfiguration.class, ResourceRepositoryConfiguration.class,
|
||||
@Import({ ResourceRepositoryConfiguration.class, EnvironmentRepositoryConfiguration.class,
|
||||
ConfigServerEncryptionConfiguration.class, ConfigServerMvcConfiguration.class })
|
||||
public @interface EnableConfigServer {
|
||||
|
||||
|
||||
@@ -80,4 +80,4 @@ public class ConfigServerMvcConfiguration extends WebMvcConfigurerAdapter {
|
||||
encrypted.setOverrides(this.server.getOverrides());
|
||||
return encrypted;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,133 +1,133 @@
|
||||
/*
|
||||
* 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.config.server.config;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.config.server.environment.ConsulEnvironmentWatch;
|
||||
import org.springframework.cloud.config.server.environment.EnvironmentRepository;
|
||||
import org.springframework.cloud.config.server.environment.EnvironmentWatch;
|
||||
import org.springframework.cloud.config.server.environment.MultipleJGitEnvironmentRepository;
|
||||
import org.springframework.cloud.config.server.environment.NativeEnvironmentRepository;
|
||||
import org.springframework.cloud.config.server.environment.SvnKitEnvironmentRepository;
|
||||
import org.springframework.cloud.config.server.environment.VaultEnvironmentRepository;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnMissingBean(EnvironmentRepository.class)
|
||||
@EnableConfigurationProperties(ConfigServerProperties.class)
|
||||
public class EnvironmentRepositoryConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(value = "spring.cloud.config.server.health.enabled", matchIfMissing = true)
|
||||
public ConfigServerHealthIndicator configServerHealthIndicator(EnvironmentRepository repository) {
|
||||
return new ConfigServerHealthIndicator(repository);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Profile("native")
|
||||
protected static class NativeRepositoryConfiguration {
|
||||
|
||||
@Autowired
|
||||
private ConfigurableEnvironment environment;
|
||||
|
||||
@Bean
|
||||
public EnvironmentRepository environmentRepository() {
|
||||
return new NativeEnvironmentRepository(this.environment);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnMissingBean(EnvironmentRepository.class)
|
||||
protected static class GitRepositoryConfiguration {
|
||||
|
||||
@Autowired
|
||||
private ConfigurableEnvironment environment;
|
||||
|
||||
@Autowired
|
||||
private ConfigServerProperties server;
|
||||
|
||||
@Bean
|
||||
public EnvironmentRepository environmentRepository() {
|
||||
MultipleJGitEnvironmentRepository repository = new MultipleJGitEnvironmentRepository(this.environment);
|
||||
if (this.server.getDefaultLabel()!=null) {
|
||||
repository.setDefaultLabel(this.server.getDefaultLabel());
|
||||
}
|
||||
return repository;
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Profile("subversion")
|
||||
protected static class SvnRepositoryConfiguration {
|
||||
@Autowired
|
||||
private ConfigurableEnvironment environment;
|
||||
|
||||
@Autowired
|
||||
private ConfigServerProperties server;
|
||||
|
||||
@Bean
|
||||
public EnvironmentRepository environmentRepository() {
|
||||
SvnKitEnvironmentRepository repository = new SvnKitEnvironmentRepository(this.environment);
|
||||
if (this.server.getDefaultLabel()!=null) {
|
||||
repository.setDefaultLabel(this.server.getDefaultLabel());
|
||||
}
|
||||
return repository;
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Profile("vault")
|
||||
protected static class VaultConfiguration {
|
||||
@Bean
|
||||
public EnvironmentRepository environmentRepository(HttpServletRequest request, EnvironmentWatch watch) {
|
||||
return new VaultEnvironmentRepository(request, watch, new RestTemplate());
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnProperty(value = "spring.cloud.config.server.consul.watch.enabled")
|
||||
protected static class ConsulEnvironmentWatchConfiguration {
|
||||
|
||||
@Bean
|
||||
public EnvironmentWatch environmentWatch() {
|
||||
return new ConsulEnvironmentWatch();
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnMissingBean(EnvironmentWatch.class)
|
||||
protected static class DefaultEnvironmentWatch {
|
||||
|
||||
@Bean
|
||||
public EnvironmentWatch environmentWatch() {
|
||||
return new EnvironmentWatch.Default();
|
||||
}
|
||||
}
|
||||
/*
|
||||
* 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.config.server.config;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.config.server.environment.ConsulEnvironmentWatch;
|
||||
import org.springframework.cloud.config.server.environment.EnvironmentRepository;
|
||||
import org.springframework.cloud.config.server.environment.EnvironmentWatch;
|
||||
import org.springframework.cloud.config.server.environment.MultipleJGitEnvironmentRepository;
|
||||
import org.springframework.cloud.config.server.environment.NativeEnvironmentRepository;
|
||||
import org.springframework.cloud.config.server.environment.SvnKitEnvironmentRepository;
|
||||
import org.springframework.cloud.config.server.environment.VaultEnvironmentRepository;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnMissingBean(EnvironmentRepository.class)
|
||||
@EnableConfigurationProperties(ConfigServerProperties.class)
|
||||
public class EnvironmentRepositoryConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(value = "spring.cloud.config.server.health.enabled", matchIfMissing = true)
|
||||
public ConfigServerHealthIndicator configServerHealthIndicator(EnvironmentRepository repository) {
|
||||
return new ConfigServerHealthIndicator(repository);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Profile("native")
|
||||
protected static class NativeRepositoryConfiguration {
|
||||
|
||||
@Autowired
|
||||
private ConfigurableEnvironment environment;
|
||||
|
||||
@Bean
|
||||
public NativeEnvironmentRepository environmentRepository() {
|
||||
return new NativeEnvironmentRepository(this.environment);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnMissingBean(EnvironmentRepository.class)
|
||||
protected static class GitRepositoryConfiguration {
|
||||
|
||||
@Autowired
|
||||
private ConfigurableEnvironment environment;
|
||||
|
||||
@Autowired
|
||||
private ConfigServerProperties server;
|
||||
|
||||
@Bean
|
||||
public MultipleJGitEnvironmentRepository environmentRepository() {
|
||||
MultipleJGitEnvironmentRepository repository = new MultipleJGitEnvironmentRepository(this.environment);
|
||||
if (this.server.getDefaultLabel()!=null) {
|
||||
repository.setDefaultLabel(this.server.getDefaultLabel());
|
||||
}
|
||||
return repository;
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Profile("subversion")
|
||||
protected static class SvnRepositoryConfiguration {
|
||||
@Autowired
|
||||
private ConfigurableEnvironment environment;
|
||||
|
||||
@Autowired
|
||||
private ConfigServerProperties server;
|
||||
|
||||
@Bean
|
||||
public SvnKitEnvironmentRepository environmentRepository() {
|
||||
SvnKitEnvironmentRepository repository = new SvnKitEnvironmentRepository(this.environment);
|
||||
if (this.server.getDefaultLabel()!=null) {
|
||||
repository.setDefaultLabel(this.server.getDefaultLabel());
|
||||
}
|
||||
return repository;
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Profile("vault")
|
||||
protected static class VaultConfiguration {
|
||||
@Bean
|
||||
public EnvironmentRepository environmentRepository(HttpServletRequest request, EnvironmentWatch watch) {
|
||||
return new VaultEnvironmentRepository(request, watch, new RestTemplate());
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnProperty(value = "spring.cloud.config.server.consul.watch.enabled")
|
||||
protected static class ConsulEnvironmentWatchConfiguration {
|
||||
|
||||
@Bean
|
||||
public EnvironmentWatch environmentWatch() {
|
||||
return new ConsulEnvironmentWatch();
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnMissingBean(EnvironmentWatch.class)
|
||||
protected static class DefaultEnvironmentWatch {
|
||||
|
||||
@Bean
|
||||
public EnvironmentWatch environmentWatch() {
|
||||
return new EnvironmentWatch.Default();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,41 +1,41 @@
|
||||
/*
|
||||
* 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.config.server.config;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.config.server.environment.SearchPathLocator;
|
||||
import org.springframework.cloud.config.server.resource.GenericResourceRepository;
|
||||
import org.springframework.cloud.config.server.resource.ResourceRepository;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnMissingBean(ResourceRepository.class)
|
||||
@EnableConfigurationProperties(ConfigServerProperties.class)
|
||||
public class ResourceRepositoryConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnBean(SearchPathLocator.class)
|
||||
public ResourceRepository resourceRepository(SearchPathLocator service) {
|
||||
return new GenericResourceRepository(service);
|
||||
}
|
||||
/*
|
||||
* 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.config.server.config;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.config.server.environment.SearchPathLocator;
|
||||
import org.springframework.cloud.config.server.resource.GenericResourceRepository;
|
||||
import org.springframework.cloud.config.server.resource.ResourceRepository;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(ConfigServerProperties.class)
|
||||
@ConditionalOnMissingBean(ResourceRepository.class)
|
||||
public class ResourceRepositoryConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnBean(SearchPathLocator.class)
|
||||
public ResourceRepository resourceRepository(SearchPathLocator service) {
|
||||
return new GenericResourceRepository(service);
|
||||
}
|
||||
}
|
||||
@@ -1,38 +1,38 @@
|
||||
/*
|
||||
* 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.config.server.environment;
|
||||
|
||||
import org.springframework.cloud.config.environment.Environment;
|
||||
import org.springframework.cloud.config.environment.PropertySource;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* @author Michael Prankl
|
||||
*/
|
||||
public class EnvironmentCleaner {
|
||||
|
||||
public Environment clean(Environment value, String workingDir, String uri) {
|
||||
Environment result = new Environment(value);
|
||||
for (PropertySource source : value.getPropertySources()) {
|
||||
String name = source.getName().replace(workingDir, "");
|
||||
name = name.replace("applicationConfig: [", "");
|
||||
name = uri + "/" + name.replace("]", "");
|
||||
result.add(new PropertySource(name, source.getSource()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.config.server.environment;
|
||||
|
||||
import org.springframework.cloud.config.environment.Environment;
|
||||
import org.springframework.cloud.config.environment.PropertySource;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* @author Michael Prankl
|
||||
*/
|
||||
public class EnvironmentCleaner {
|
||||
|
||||
public Environment clean(Environment value, String workingDir, String uri) {
|
||||
Environment result = new Environment(value);
|
||||
for (PropertySource source : value.getPropertySources()) {
|
||||
String name = source.getName().replace(workingDir, "");
|
||||
name = name.replace("applicationConfig: [", "");
|
||||
name = uri + "/" + name.replace("]", "");
|
||||
result.add(new PropertySource(name, source.getSource()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -152,7 +152,7 @@ public class EnvironmentController {
|
||||
throws Exception {
|
||||
validateProfiles(profiles);
|
||||
Environment environment = labelled(name, profiles, label);
|
||||
Map<String, Object> properties = convertToMap(environment);
|
||||
Map<String, Object> properties = convertToMap(environment, resolvePlaceholders);
|
||||
String json = this.objectMapper.writeValueAsString(properties);
|
||||
if (resolvePlaceholders) {
|
||||
json = resolvePlaceholders(prepareEnvironment(environment), json);
|
||||
@@ -188,7 +188,7 @@ public class EnvironmentController {
|
||||
throws Exception {
|
||||
validateProfiles(profiles);
|
||||
Environment environment = labelled(name, profiles, label);
|
||||
Map<String, Object> result = convertToMap(environment);
|
||||
Map<String, Object> result = convertToMap(environment, resolvePlaceholders);
|
||||
if (this.stripDocument && result.size() == 1
|
||||
&& result.keySet().iterator().next().equals("document")) {
|
||||
Object value = result.get("document");
|
||||
@@ -208,10 +208,13 @@ public class EnvironmentController {
|
||||
return getSuccess(yaml);
|
||||
}
|
||||
|
||||
private Map<String, Object> convertToMap(Environment input) throws BindException {
|
||||
private Map<String, Object> convertToMap(Environment input, boolean resolvePlaceholders) throws BindException {
|
||||
Map<String, Object> target = new LinkedHashMap<>();
|
||||
PropertiesConfigurationFactory<Map<String, Object>> factory = new PropertiesConfigurationFactory<>(
|
||||
target);
|
||||
if (!resolvePlaceholders) {
|
||||
factory.setResolvePlaceholders(false);
|
||||
}
|
||||
Map<String, Object> data = convertToProperties(input);
|
||||
LinkedHashMap<String, Object> properties = new LinkedHashMap<>();
|
||||
for (String key : data.keySet()) {
|
||||
|
||||
@@ -1,196 +1,196 @@
|
||||
/*
|
||||
* Copyright 2013-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.config.server.environment;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.tmatesoft.svn.core.SVNURL;
|
||||
import org.tmatesoft.svn.core.internal.wc.DefaultSVNAuthenticationManager;
|
||||
import org.tmatesoft.svn.core.wc.SVNClientManager;
|
||||
import org.tmatesoft.svn.core.wc.SVNStatus;
|
||||
import org.tmatesoft.svn.core.wc2.SvnCheckout;
|
||||
import org.tmatesoft.svn.core.wc2.SvnOperationFactory;
|
||||
import org.tmatesoft.svn.core.wc2.SvnTarget;
|
||||
import org.tmatesoft.svn.core.wc2.SvnUpdate;
|
||||
|
||||
import static org.springframework.util.StringUtils.hasText;
|
||||
|
||||
/**
|
||||
* Subversion-backed {@link EnvironmentRepository}.
|
||||
*
|
||||
* @author Michael Prankl
|
||||
* @author Roy Clarkson
|
||||
*/
|
||||
@ConfigurationProperties("spring.cloud.config.server.svn")
|
||||
public class SvnKitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
implements EnvironmentRepository, InitializingBean {
|
||||
|
||||
private static Log logger = LogFactory.getLog(SvnKitEnvironmentRepository.class);
|
||||
|
||||
private static final String DEFAULT_LABEL = "trunk";
|
||||
|
||||
/**
|
||||
* The default label for environment properties requests.
|
||||
*/
|
||||
private String defaultLabel = DEFAULT_LABEL;
|
||||
|
||||
public String getDefaultLabel() {
|
||||
return this.defaultLabel;
|
||||
}
|
||||
|
||||
public void setDefaultLabel(String defaultLabel) {
|
||||
this.defaultLabel = defaultLabel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Locations getLocations(String application, String profile,
|
||||
String label) {
|
||||
if (label == null) {
|
||||
label = this.defaultLabel;
|
||||
}
|
||||
SvnOperationFactory svnOperationFactory = new SvnOperationFactory();
|
||||
if (hasText(getUsername())) {
|
||||
svnOperationFactory
|
||||
.setAuthenticationManager(new DefaultSVNAuthenticationManager(null,
|
||||
false, getUsername(), getPassword()));
|
||||
}
|
||||
try {
|
||||
String version;
|
||||
if (new File(getWorkingDirectory(), ".svn").exists()) {
|
||||
version = update(svnOperationFactory, label);
|
||||
}
|
||||
else {
|
||||
version = checkout(svnOperationFactory);
|
||||
}
|
||||
return new Locations(application, profile, label, version,
|
||||
getPaths(application, profile, label));
|
||||
}
|
||||
catch (SVNException e) {
|
||||
throw new IllegalStateException("Cannot checkout repository", e);
|
||||
}
|
||||
finally {
|
||||
svnOperationFactory.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private String[] getPaths(String application, String profile, String label) {
|
||||
String[] locations = getSearchLocations(getSvnPath(getWorkingDirectory(), label), application, profile, label);
|
||||
boolean exists = false;
|
||||
for (String location : locations) {
|
||||
location = StringUtils.cleanPath(location);
|
||||
URI locationUri = URI.create(location);
|
||||
if (new File(locationUri).exists()) {
|
||||
exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!exists) {
|
||||
throw new NoSuchLabelException("No label found for: " + label);
|
||||
}
|
||||
return locations;
|
||||
}
|
||||
|
||||
private String checkout(SvnOperationFactory svnOperationFactory) throws SVNException {
|
||||
logger.debug("Checking out " + getUri() + " to: "
|
||||
+ getWorkingDirectory().getAbsolutePath());
|
||||
final SvnCheckout checkout = svnOperationFactory.createCheckout();
|
||||
checkout.setSource(SvnTarget.fromURL(SVNURL.parseURIEncoded(getUri())));
|
||||
checkout.setSingleTarget(SvnTarget.fromFile(getWorkingDirectory()));
|
||||
Long id = checkout.run();
|
||||
if (id == null) {
|
||||
return null;
|
||||
}
|
||||
return id.toString();
|
||||
}
|
||||
|
||||
private String update(SvnOperationFactory svnOperationFactory, String label) throws SVNException {
|
||||
logger.debug("Repo already checked out - updating instead.");
|
||||
|
||||
try {
|
||||
final SvnUpdate update = svnOperationFactory.createUpdate();
|
||||
update.setSingleTarget(SvnTarget.fromFile(getWorkingDirectory()));
|
||||
long[] ids = update.run();
|
||||
StringBuilder version = new StringBuilder();
|
||||
for (long id : ids) {
|
||||
if (version.length() > 0) {
|
||||
version.append(",");
|
||||
}
|
||||
version.append(id);
|
||||
}
|
||||
return version.toString();
|
||||
}
|
||||
catch (Exception e) {
|
||||
this.logger.warn("Could not update remote for " + label + " (current local="
|
||||
+ getWorkingDirectory().getPath() + "), remote: " + this.getUri()
|
||||
+ ")");
|
||||
}
|
||||
|
||||
final SVNStatus status = SVNClientManager.newInstance().getStatusClient()
|
||||
.doStatus(getWorkingDirectory(), false);
|
||||
return status != null ? status.getRevision().toString() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.state(getUri() != null,
|
||||
"You need to configure a uri for the subversion repository (e.g. 'http://example.com/svn/')");
|
||||
resolveRelativeFileUri();
|
||||
}
|
||||
|
||||
private void resolveRelativeFileUri() {
|
||||
if (getUri().startsWith("file:///./")) {
|
||||
String path = getUri().substring(8);
|
||||
String absolutePath = new File(path).getAbsolutePath();
|
||||
setUri("file:///" + StringUtils.cleanPath(absolutePath));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public SvnKitEnvironmentRepository(ConfigurableEnvironment environment) {
|
||||
super(environment);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected File getWorkingDirectory() {
|
||||
return this.getBasedir();
|
||||
}
|
||||
|
||||
private File getSvnPath(File workingDirectory, String label) {
|
||||
// use label as path relative to repository root
|
||||
// if it doesn't exists check branches and then tags folders
|
||||
File svnPath = new File(workingDirectory, label);
|
||||
if(!svnPath.exists()) {
|
||||
svnPath = new File(workingDirectory, "branches" + File.separator + label);
|
||||
if(!svnPath.exists()) {
|
||||
svnPath = new File(workingDirectory, "tags" + File.separator + label);
|
||||
if(!svnPath.exists()) {
|
||||
throw new NoSuchLabelException("No label found for: " + label);
|
||||
}
|
||||
}
|
||||
}
|
||||
return svnPath;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright 2013-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.config.server.environment;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.tmatesoft.svn.core.SVNURL;
|
||||
import org.tmatesoft.svn.core.internal.wc.DefaultSVNAuthenticationManager;
|
||||
import org.tmatesoft.svn.core.wc.SVNClientManager;
|
||||
import org.tmatesoft.svn.core.wc.SVNStatus;
|
||||
import org.tmatesoft.svn.core.wc2.SvnCheckout;
|
||||
import org.tmatesoft.svn.core.wc2.SvnOperationFactory;
|
||||
import org.tmatesoft.svn.core.wc2.SvnTarget;
|
||||
import org.tmatesoft.svn.core.wc2.SvnUpdate;
|
||||
|
||||
import static org.springframework.util.StringUtils.hasText;
|
||||
|
||||
/**
|
||||
* Subversion-backed {@link EnvironmentRepository}.
|
||||
*
|
||||
* @author Michael Prankl
|
||||
* @author Roy Clarkson
|
||||
*/
|
||||
@ConfigurationProperties("spring.cloud.config.server.svn")
|
||||
public class SvnKitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
implements EnvironmentRepository, InitializingBean {
|
||||
|
||||
private static Log logger = LogFactory.getLog(SvnKitEnvironmentRepository.class);
|
||||
|
||||
private static final String DEFAULT_LABEL = "trunk";
|
||||
|
||||
/**
|
||||
* The default label for environment properties requests.
|
||||
*/
|
||||
private String defaultLabel = DEFAULT_LABEL;
|
||||
|
||||
public String getDefaultLabel() {
|
||||
return this.defaultLabel;
|
||||
}
|
||||
|
||||
public void setDefaultLabel(String defaultLabel) {
|
||||
this.defaultLabel = defaultLabel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Locations getLocations(String application, String profile,
|
||||
String label) {
|
||||
if (label == null) {
|
||||
label = this.defaultLabel;
|
||||
}
|
||||
SvnOperationFactory svnOperationFactory = new SvnOperationFactory();
|
||||
if (hasText(getUsername())) {
|
||||
svnOperationFactory
|
||||
.setAuthenticationManager(new DefaultSVNAuthenticationManager(null,
|
||||
false, getUsername(), getPassword()));
|
||||
}
|
||||
try {
|
||||
String version;
|
||||
if (new File(getWorkingDirectory(), ".svn").exists()) {
|
||||
version = update(svnOperationFactory, label);
|
||||
}
|
||||
else {
|
||||
version = checkout(svnOperationFactory);
|
||||
}
|
||||
return new Locations(application, profile, label, version,
|
||||
getPaths(application, profile, label));
|
||||
}
|
||||
catch (SVNException e) {
|
||||
throw new IllegalStateException("Cannot checkout repository", e);
|
||||
}
|
||||
finally {
|
||||
svnOperationFactory.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private String[] getPaths(String application, String profile, String label) {
|
||||
String[] locations = getSearchLocations(getSvnPath(getWorkingDirectory(), label), application, profile, label);
|
||||
boolean exists = false;
|
||||
for (String location : locations) {
|
||||
location = StringUtils.cleanPath(location);
|
||||
URI locationUri = URI.create(location);
|
||||
if (new File(locationUri).exists()) {
|
||||
exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!exists) {
|
||||
throw new NoSuchLabelException("No label found for: " + label);
|
||||
}
|
||||
return locations;
|
||||
}
|
||||
|
||||
private String checkout(SvnOperationFactory svnOperationFactory) throws SVNException {
|
||||
logger.debug("Checking out " + getUri() + " to: "
|
||||
+ getWorkingDirectory().getAbsolutePath());
|
||||
final SvnCheckout checkout = svnOperationFactory.createCheckout();
|
||||
checkout.setSource(SvnTarget.fromURL(SVNURL.parseURIEncoded(getUri())));
|
||||
checkout.setSingleTarget(SvnTarget.fromFile(getWorkingDirectory()));
|
||||
Long id = checkout.run();
|
||||
if (id == null) {
|
||||
return null;
|
||||
}
|
||||
return id.toString();
|
||||
}
|
||||
|
||||
private String update(SvnOperationFactory svnOperationFactory, String label) throws SVNException {
|
||||
logger.debug("Repo already checked out - updating instead.");
|
||||
|
||||
try {
|
||||
final SvnUpdate update = svnOperationFactory.createUpdate();
|
||||
update.setSingleTarget(SvnTarget.fromFile(getWorkingDirectory()));
|
||||
long[] ids = update.run();
|
||||
StringBuilder version = new StringBuilder();
|
||||
for (long id : ids) {
|
||||
if (version.length() > 0) {
|
||||
version.append(",");
|
||||
}
|
||||
version.append(id);
|
||||
}
|
||||
return version.toString();
|
||||
}
|
||||
catch (Exception e) {
|
||||
this.logger.warn("Could not update remote for " + label + " (current local="
|
||||
+ getWorkingDirectory().getPath() + "), remote: " + this.getUri()
|
||||
+ ")");
|
||||
}
|
||||
|
||||
final SVNStatus status = SVNClientManager.newInstance().getStatusClient()
|
||||
.doStatus(getWorkingDirectory(), false);
|
||||
return status != null ? status.getRevision().toString() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.state(getUri() != null,
|
||||
"You need to configure a uri for the subversion repository (e.g. 'http://example.com/svn/')");
|
||||
resolveRelativeFileUri();
|
||||
}
|
||||
|
||||
private void resolveRelativeFileUri() {
|
||||
if (getUri().startsWith("file:///./")) {
|
||||
String path = getUri().substring(8);
|
||||
String absolutePath = new File(path).getAbsolutePath();
|
||||
setUri("file:///" + StringUtils.cleanPath(absolutePath));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public SvnKitEnvironmentRepository(ConfigurableEnvironment environment) {
|
||||
super(environment);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected File getWorkingDirectory() {
|
||||
return this.getBasedir();
|
||||
}
|
||||
|
||||
private File getSvnPath(File workingDirectory, String label) {
|
||||
// use label as path relative to repository root
|
||||
// if it doesn't exists check branches and then tags folders
|
||||
File svnPath = new File(workingDirectory, label);
|
||||
if(!svnPath.exists()) {
|
||||
svnPath = new File(workingDirectory, "branches" + File.separator + label);
|
||||
if(!svnPath.exists()) {
|
||||
svnPath = new File(workingDirectory, "tags" + File.separator + label);
|
||||
if(!svnPath.exists()) {
|
||||
throw new NoSuchLabelException("No label found for: " + label);
|
||||
}
|
||||
}
|
||||
}
|
||||
return svnPath;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 2012-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.config.server.config;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.context.embedded.LocalServerPort;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||
import org.springframework.cloud.config.environment.Environment;
|
||||
import org.springframework.cloud.config.server.EnableConfigServer;
|
||||
import org.springframework.cloud.config.server.config.CustomEnvironmentRepositoryTests.TestApplication;
|
||||
import org.springframework.cloud.config.server.environment.EnvironmentRepository;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = TestApplication.class, properties = { "server.port:0",
|
||||
"spring.config.name:configserver" }, webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||
@ActiveProfiles("test")
|
||||
@DirtiesContext
|
||||
public class CustomEnvironmentRepositoryTests {
|
||||
|
||||
@LocalServerPort
|
||||
private int port;
|
||||
|
||||
@Test
|
||||
public void contextLoads() {
|
||||
Environment environment = new TestRestTemplate().getForObject(
|
||||
"http://localhost:" + port + "/foo/development/", Environment.class);
|
||||
assertFalse(environment.getPropertySources().isEmpty());
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
@EnableConfigServer
|
||||
protected static class TestApplication {
|
||||
|
||||
@Bean
|
||||
public EnvironmentRepository environmentRepository() {
|
||||
return new EnvironmentRepository() {
|
||||
|
||||
@Override
|
||||
public Environment findOne(String application, String profile,
|
||||
String label) {
|
||||
return new Environment("test", new String[0], "label", "version",
|
||||
"state");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
SpringApplication.run(CustomEnvironmentRepositoryTests.TestApplication.class,
|
||||
args);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -138,7 +138,15 @@ public class EnvironmentControllerTests {
|
||||
public void placeholdersNotResolvedInYamlFromSystemPropertiesWhenNotFlaggedWithDefault() throws Exception {
|
||||
whenPlaceholdersSystemPropsWithDefault();
|
||||
String yaml = this.controller.yaml("foo", "bar", false).getBody();
|
||||
// If there is a default value we can't prevent the placeholder being resolved
|
||||
// If there is a default value we prevent the placeholder being resolved
|
||||
assertEquals("a:\n b:\n c: ${foo:spam}\n", yaml);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void placeholdersResolvedInYamlFromSystemPropertiesWhenFlagged() throws Exception {
|
||||
whenPlaceholdersSystemPropsWithDefault();
|
||||
String yaml = this.controller.yaml("foo", "bar", true).getBody();
|
||||
// If there is a default value we do not prevent the placeholder being resolved
|
||||
assertEquals("a:\n b:\n c: spam\n", yaml);
|
||||
}
|
||||
|
||||
@@ -335,10 +343,18 @@ public class EnvironmentControllerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void placeholdersResolvedInJsonFromSystemPropertiesWhenNotFlaggedWithDefault() throws Exception {
|
||||
public void placeholdersNotResolvedInJsonFromSystemPropertiesWhenNotFlaggedWithDefault() throws Exception {
|
||||
whenPlaceholdersSystemPropsWithDefault();
|
||||
String json = this.controller.jsonProperties("foo", "bar", false).getBody();
|
||||
// If there is a default value we can't prevent the placeholder being resolved
|
||||
// If there is a default value we prevent the placeholder being resolved
|
||||
assertEquals("{\"a\":{\"b\":{\"c\":\"${foo:spam}\"}}}", json);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void placeholdersResolvedInJsonFromSystemPropertiesWhenFlagged() throws Exception {
|
||||
whenPlaceholdersSystemPropsWithDefault();
|
||||
String json = this.controller.jsonProperties("foo", "bar", true).getBody();
|
||||
// If there is a default value we do not prevent the placeholder being resolved
|
||||
assertEquals("{\"a\":{\"b\":{\"c\":\"spam\"}}}", json);
|
||||
}
|
||||
|
||||
@@ -392,7 +408,6 @@ public class EnvironmentControllerTests {
|
||||
mvc.perform(MockMvcRequestBuilders.get("/foo-bar.json"))
|
||||
.andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(MockMvcResultMatchers.content().string("{}"));
|
||||
;
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-config</artifactId>
|
||||
<version>1.2.0.BUILD-SNAPSHOT</version>
|
||||
<version>1.2.2.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>spring-cloud-starter-config</artifactId>
|
||||
<version>1.2.0.BUILD-SNAPSHOT</version>
|
||||
<version>1.2.2.BUILD-SNAPSHOT</version>
|
||||
<name>spring-cloud-starter-config</name>
|
||||
<description>Spring Cloud Starter</description>
|
||||
<url>https://projects.spring.io/spring-cloud</url>
|
||||
|
||||
Reference in New Issue
Block a user