@@ -3,6 +3,7 @@
|
|||||||
:githubmaster: {github}/tree/master
|
:githubmaster: {github}/tree/master
|
||||||
:docslink: {githubmaster}/docs/src/main/asciidoc
|
:docslink: {githubmaster}/docs/src/main/asciidoc
|
||||||
:toc:
|
:toc:
|
||||||
|
:nofooter:
|
||||||
|
|
||||||
include::intro.adoc[]
|
include::intro.adoc[]
|
||||||
|
|
||||||
@@ -31,8 +32,8 @@ public class ConfigServer {
|
|||||||
|
|
||||||
Like all Spring Boot apps it runs on port 8080 by default, but you
|
Like all Spring Boot apps it runs on port 8080 by default, but you
|
||||||
can switch it to the conventional port 8888 in various ways. The
|
can switch it to the conventional port 8888 in various ways. The
|
||||||
easiest, which also sets a default configuration repository,
|
easiest, which also sets a default configuration repository,
|
||||||
is by launching it with `spring.config.name=configserver` (there
|
is by launching it with `spring.config.name=configserver` (there
|
||||||
is a `configserver.yml` in the Config Server jar). Another is
|
is a `configserver.yml` in the Config Server jar). Another is
|
||||||
to use your own `application.properties`, e.g.
|
to use your own `application.properties`, e.g.
|
||||||
|
|
||||||
@@ -46,12 +47,12 @@ spring.cloud.config.server.git.uri: file://${user.home}/config-repo
|
|||||||
where `${user.home}/config-repo` is a git repository containing
|
where `${user.home}/config-repo` is a git repository containing
|
||||||
YAML and properties files.
|
YAML and properties files.
|
||||||
|
|
||||||
NOTE: in Windows you need an extra "/" in the file URL if it is
|
NOTE: in Windows you need an extra "/" in the file URL if it is
|
||||||
absolute with a drive prefix, e.g. `file:///${user.home}/config-repo`.
|
absolute with a drive prefix, e.g. `file:///${user.home}/config-repo`.
|
||||||
|
|
||||||
[TIP]
|
[TIP]
|
||||||
====
|
====
|
||||||
Here's a recipe for creating the git repository in the example
|
Here's a recipe for creating the git repository in the example
|
||||||
above:
|
above:
|
||||||
|
|
||||||
----
|
----
|
||||||
@@ -66,7 +67,7 @@ $ git commit -m "Add application.properties"
|
|||||||
====
|
====
|
||||||
|
|
||||||
WARNING: using the local filesystem for your git repository is
|
WARNING: using the local filesystem for your git repository is
|
||||||
intended for testing only. Use a server to host your
|
intended for testing only. Use a server to host your
|
||||||
configuration repositories in production.
|
configuration repositories in production.
|
||||||
|
|
||||||
WARNING: the initial clone of your configuration repository will
|
WARNING: the initial clone of your configuration repository will
|
||||||
@@ -87,7 +88,7 @@ Server? The strategy that governs this behaviour is the
|
|||||||
|
|
||||||
* `{application}` maps to "spring.application.name" on the client side;
|
* `{application}` maps to "spring.application.name" on the client side;
|
||||||
|
|
||||||
* `{profile}` maps to "spring.profiles.active" on the client (comma separated list); and
|
* `{profile}` maps to "spring.profiles.active" on the client (comma separated list); and
|
||||||
|
|
||||||
* `{label}` which is a server side feature labelling a "versioned" set of config files.
|
* `{label}` which is a server side feature labelling a "versioned" set of config files.
|
||||||
|
|
||||||
@@ -112,7 +113,7 @@ spring:
|
|||||||
----
|
----
|
||||||
|
|
||||||
(as usual with a Spring Boot application, these properties could also
|
(as usual with a Spring Boot application, these properties could also
|
||||||
be set as environment variables or command line arguments).
|
be set as environment variables or command line arguments).
|
||||||
|
|
||||||
If the repository is file-based, the server will create an
|
If the repository is file-based, the server will create an
|
||||||
`Environment` from `application.yml` (shared between all clients), and
|
`Environment` from `application.yml` (shared between all clients), and
|
||||||
@@ -265,7 +266,7 @@ In this example the server searches for config files in the top level
|
|||||||
and in the "foo/" sub-directory and also any sub-directory whose name
|
and in the "foo/" sub-directory and also any sub-directory whose name
|
||||||
begins with "bar".
|
begins with "bar".
|
||||||
|
|
||||||
By default the server clones remote repositories when configuration
|
By default the server clones remote repositories when configuration
|
||||||
is first requested. The server can be configured to clone the repositories
|
is first requested. The server can be configured to clone the repositories
|
||||||
at startup. For example at the top level:
|
at startup. For example at the top level:
|
||||||
|
|
||||||
@@ -289,11 +290,11 @@ spring:
|
|||||||
team-c:
|
team-c:
|
||||||
pattern: team-c-*
|
pattern: team-c-*
|
||||||
uri: http://git/team-a/config-repo.git
|
uri: http://git/team-a/config-repo.git
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
In this example the server clones team-a's config-repo on startup before it
|
In this example the server clones team-a's config-repo on startup before it
|
||||||
accepts any requests. All other repositories will not be cloned until
|
accepts any requests. All other repositories will not be cloned until
|
||||||
configuration from the repository is requested.
|
configuration from the repository is requested.
|
||||||
|
|
||||||
NOTE: Setting a repository to be cloned when the Config Server starts up can
|
NOTE: Setting a repository to be cloned when the Config Server starts up can
|
||||||
@@ -305,7 +306,7 @@ not detect an error until an application requests configuration from that
|
|||||||
configuration source.
|
configuration source.
|
||||||
|
|
||||||
To use HTTP basic authentication on the remote repository add the
|
To use HTTP basic authentication on the remote repository add the
|
||||||
"username" and "password" properties separately (not in the URL),
|
"username" and "password" properties separately (not in the URL),
|
||||||
e.g.
|
e.g.
|
||||||
|
|
||||||
[source,yaml]
|
[source,yaml]
|
||||||
@@ -352,8 +353,8 @@ spring:
|
|||||||
----
|
----
|
||||||
|
|
||||||
searches the repository for files in the same name as the directory
|
searches the repository for files in the same name as the directory
|
||||||
(as well as the top level). Wildcards are also valid in a search
|
(as well as the top level). Wildcards are also valid in a search
|
||||||
path with placeholders (any matching directory is included in the
|
path with placeholders (any matching directory is included in the
|
||||||
search).
|
search).
|
||||||
|
|
||||||
==== Version Control Backend Filesystem Use
|
==== Version Control Backend Filesystem Use
|
||||||
@@ -367,7 +368,7 @@ Git, but just loads the config files from the local classpath or file
|
|||||||
system (any static URL you want to point to with
|
system (any static URL you want to point to with
|
||||||
"spring.cloud.config.server.native.searchLocations"). To use the
|
"spring.cloud.config.server.native.searchLocations"). To use the
|
||||||
native profile just launch the Config Server with
|
native profile just launch the Config Server with
|
||||||
"spring.profiles.active=native".
|
"spring.profiles.active=native".
|
||||||
|
|
||||||
NOTE: Remember to use the `file:` prefix for file resources (the
|
NOTE: Remember to use the `file:` prefix for file resources (the
|
||||||
default without a prefix is usually the classpath). Just as with any
|
default without a prefix is usually the classpath). Just as with any
|
||||||
@@ -383,7 +384,7 @@ property sources present in the server are removed before being sent
|
|||||||
to the client.
|
to the client.
|
||||||
|
|
||||||
TIP: A filesystem backend is great for getting started quickly and
|
TIP: A filesystem backend is great for getting started quickly and
|
||||||
for testing. To use it in production you need to be sure that the
|
for testing. To use it in production you need to be sure that the
|
||||||
file system is reliable, and shared across all instances of the
|
file system is reliable, and shared across all instances of the
|
||||||
Config Server.
|
Config Server.
|
||||||
|
|
||||||
@@ -622,7 +623,7 @@ You can disable the Health Indicator by setting `spring.cloud.config.server.heal
|
|||||||
You are free to secure your Config Server in any way that makes sense
|
You are free to secure your Config Server in any way that makes sense
|
||||||
to you (from physical network security to OAuth2 bearer
|
to you (from physical network security to OAuth2 bearer
|
||||||
tokens), and Spring Security and Spring Boot make it easy to do pretty
|
tokens), and Spring Security and Spring Boot make it easy to do pretty
|
||||||
much anything.
|
much anything.
|
||||||
|
|
||||||
To use the default Spring Boot configured HTTP Basic security, just
|
To use the default Spring Boot configured HTTP Basic security, just
|
||||||
include Spring Security on the classpath (e.g. through
|
include Spring Security on the classpath (e.g. through
|
||||||
@@ -699,14 +700,14 @@ are special characters ('+' is particularly tricky).
|
|||||||
|
|
||||||
Take the encrypted value and add the `{cipher}` prefix before you put
|
Take the encrypted value and add the `{cipher}` prefix before you put
|
||||||
it in the YAML or properties file, and before you commit and push it
|
it in the YAML or properties file, and before you commit and push it
|
||||||
to a remote, potentially insecure store.
|
to a remote, potentially insecure store.
|
||||||
|
|
||||||
The `/encrypt` and `/decrypt` endpoints also both accept paths of the
|
The `/encrypt` and `/decrypt` endpoints also both accept paths of the
|
||||||
form `/*/{name}/{profiles}` which can be used to control cryptography
|
form `/*/{name}/{profiles}` which can be used to control cryptography
|
||||||
per application (name) and profile when clients call into the main
|
per application (name) and profile when clients call into the main
|
||||||
Environment resource.
|
Environment resource.
|
||||||
|
|
||||||
NOTE: to control the cryptography in this granular way you must also
|
NOTE: to control the cryptography in this granular way you must also
|
||||||
provide a `@Bean` of type `TextEncryptorLocator` that creates a
|
provide a `@Bean` of type `TextEncryptorLocator` that creates a
|
||||||
different encryptor per name and profiles. The one that is provided
|
different encryptor per name and profiles. The one that is provided
|
||||||
by default does not do this (so all encryptions use the same key).
|
by default does not do this (so all encryptions use the same key).
|
||||||
@@ -747,8 +748,8 @@ PEM-encoded text value (in `encrypt.key`), or via a keystore (e.g. as
|
|||||||
created by the `keytool` utility that comes with the JDK). The
|
created by the `keytool` utility that comes with the JDK). The
|
||||||
keystore properties are `encrypt.keyStore.\*` with `*` equal to
|
keystore properties are `encrypt.keyStore.\*` with `*` equal to
|
||||||
|
|
||||||
* `location` (a `Resource` location),
|
* `location` (a `Resource` location),
|
||||||
* `password` (to unlock the keystore) and
|
* `password` (to unlock the keystore) and
|
||||||
* `alias` (to identify which key in the store is to be
|
* `alias` (to identify which key in the store is to be
|
||||||
used).
|
used).
|
||||||
|
|
||||||
@@ -1082,7 +1083,7 @@ an Exception.
|
|||||||
=== Config Client Retry
|
=== Config Client Retry
|
||||||
|
|
||||||
If you expect that the config server may occasionally be unavailable when
|
If you expect that the config server may occasionally be unavailable when
|
||||||
your app starts, you can ask it to keep trying after a failure. First you need
|
your app starts, you can ask it to keep trying after a failure. First you need
|
||||||
to set `spring.cloud.config.failFast=true`, and then you need to add
|
to set `spring.cloud.config.failFast=true`, and then you need to add
|
||||||
`spring-retry` and `spring-boot-starter-aop` to your classpath. The default
|
`spring-retry` and `spring-boot-starter-aop` to your classpath. The default
|
||||||
behaviour is to retry 6 times with an initial backoff interval of 1000ms and an
|
behaviour is to retry 6 times with an initial backoff interval of 1000ms and an
|
||||||
@@ -1105,10 +1106,10 @@ All of them can be overridden by setting `spring.cloud.config.\*`
|
|||||||
(where `*` is "name", "profile" or "label"). The "label" is useful for
|
(where `*` is "name", "profile" or "label"). The "label" is useful for
|
||||||
rolling back to previous versions of configuration; with the default
|
rolling back to previous versions of configuration; with the default
|
||||||
Config Server implementation it can be a git label, branch name or
|
Config Server implementation it can be a git label, branch name or
|
||||||
commit id. Label can also be provided as a comma-separated list, in
|
commit id. Label can also be provided as a comma-separated list, in
|
||||||
which case the items in the list are tried on-by-one until one succeeds.
|
which case the items in the list are tried on-by-one until one succeeds.
|
||||||
This can be useful when working on a feature branch, for instance,
|
This can be useful when working on a feature branch, for instance,
|
||||||
when you might want to align the config label with your branch, but
|
when you might want to align the config label with your branch, but
|
||||||
make it optional (e.g. `spring.cloud.config.label=myfeature,develop`).
|
make it optional (e.g. `spring.cloud.config.label=myfeature,develop`).
|
||||||
|
|
||||||
=== Security
|
=== Security
|
||||||
|
|||||||
35
mvnw
vendored
35
mvnw
vendored
@@ -46,15 +46,6 @@ if [ -z "$MAVEN_SKIP_RC" ] ; then
|
|||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
VERSION=$(awk '/<parent/ {l=4}; (l-- > 0) {$0=$0} 1' `dirname $0`/pom.xml| grep '<version' | head -1 | sed -e 's/.*>\(.*\)<.*/\1/')
|
|
||||||
if echo $VERSION | egrep -q 'M|RC'; then
|
|
||||||
echo Activating \"milestone\" profile for version=\"$VERSION\"
|
|
||||||
echo $MAVEN_ARGS | grep -q milestone || MAVEN_ARGS="$MAVEN_ARGS -Pmilestone"
|
|
||||||
else
|
|
||||||
echo Deactivating \"milestone\" profile for version=\"$VERSION\"
|
|
||||||
echo $MAVEN_ARGS | grep -q milestone && MAVEN_ARGS=$(echo $MAVEN_ARGS | sed -e 's/-Pmilestone//')
|
|
||||||
fi
|
|
||||||
|
|
||||||
# OS specific support. $var _must_ be set to either true or false.
|
# OS specific support. $var _must_ be set to either true or false.
|
||||||
cygwin=false;
|
cygwin=false;
|
||||||
darwin=false;
|
darwin=false;
|
||||||
@@ -66,27 +57,27 @@ case "`uname`" in
|
|||||||
#
|
#
|
||||||
# Look for the Apple JDKs first to preserve the existing behaviour, and then look
|
# Look for the Apple JDKs first to preserve the existing behaviour, and then look
|
||||||
# for the new JDKs provided by Oracle.
|
# for the new JDKs provided by Oracle.
|
||||||
#
|
#
|
||||||
if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK ] ; then
|
if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK ] ; then
|
||||||
#
|
#
|
||||||
# Apple JDKs
|
# Apple JDKs
|
||||||
#
|
#
|
||||||
export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home
|
export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Java/JavaVirtualMachines/CurrentJDK ] ; then
|
if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Java/JavaVirtualMachines/CurrentJDK ] ; then
|
||||||
#
|
#
|
||||||
# Apple JDKs
|
# Apple JDKs
|
||||||
#
|
#
|
||||||
export JAVA_HOME=/System/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home
|
export JAVA_HOME=/System/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$JAVA_HOME" ] && [ -L "/Library/Java/JavaVirtualMachines/CurrentJDK" ] ; then
|
if [ -z "$JAVA_HOME" ] && [ -L "/Library/Java/JavaVirtualMachines/CurrentJDK" ] ; then
|
||||||
#
|
#
|
||||||
# Oracle JDKs
|
# Oracle JDKs
|
||||||
#
|
#
|
||||||
export JAVA_HOME=/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home
|
export JAVA_HOME=/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$JAVA_HOME" ] && [ -x "/usr/libexec/java_home" ]; then
|
if [ -z "$JAVA_HOME" ] && [ -x "/usr/libexec/java_home" ]; then
|
||||||
#
|
#
|
||||||
@@ -228,16 +219,30 @@ concat_lines() {
|
|||||||
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-$(find_maven_basedir)}
|
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-$(find_maven_basedir)}
|
||||||
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
|
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
|
||||||
|
|
||||||
# Provide a "standardized" way to retrieve the CLI args that will
|
# Provide a "standardized" way to retrieve the CLI args that will
|
||||||
# work with both Windows and non-Windows executions.
|
# work with both Windows and non-Windows executions.
|
||||||
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
|
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
|
||||||
export MAVEN_CMD_LINE_ARGS
|
export MAVEN_CMD_LINE_ARGS
|
||||||
|
|
||||||
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
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 )
|
||||||
|
|
||||||
|
if echo $VERSION | egrep -q 'M|RC'; then
|
||||||
|
echo Activating \"milestone\" profile for version=\"$VERSION\"
|
||||||
|
echo $MAVEN_ARGS | grep -q milestone || MAVEN_ARGS="$MAVEN_ARGS -Pmilestone"
|
||||||
|
else
|
||||||
|
echo Deactivating \"milestone\" profile for version=\"$VERSION\"
|
||||||
|
echo $MAVEN_ARGS | grep -q milestone && MAVEN_ARGS=$(echo $MAVEN_ARGS | sed -e 's/-Pmilestone//')
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
exec "$JAVACMD" \
|
exec "$JAVACMD" \
|
||||||
$MAVEN_OPTS \
|
$MAVEN_OPTS \
|
||||||
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
|
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
|
||||||
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
|
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
|
||||||
${WRAPPER_LAUNCHER} ${MAVEN_ARGS} "$@"
|
${WRAPPER_LAUNCHER} ${MAVEN_ARGS} "$@"
|
||||||
|
|
||||||
|
|||||||
@@ -24,14 +24,18 @@ import java.util.HashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.eclipse.jgit.api.CloneCommand;
|
|
||||||
import org.eclipse.jgit.api.CheckoutCommand;
|
import org.eclipse.jgit.api.CheckoutCommand;
|
||||||
|
import org.eclipse.jgit.api.CloneCommand;
|
||||||
import org.eclipse.jgit.api.CreateBranchCommand.SetupUpstreamMode;
|
import org.eclipse.jgit.api.CreateBranchCommand.SetupUpstreamMode;
|
||||||
|
import org.eclipse.jgit.api.FetchCommand;
|
||||||
import org.eclipse.jgit.api.Git;
|
import org.eclipse.jgit.api.Git;
|
||||||
import org.eclipse.jgit.api.ListBranchCommand;
|
import org.eclipse.jgit.api.ListBranchCommand;
|
||||||
import org.eclipse.jgit.api.ListBranchCommand.ListMode;
|
import org.eclipse.jgit.api.ListBranchCommand.ListMode;
|
||||||
import org.eclipse.jgit.api.PullCommand;
|
import org.eclipse.jgit.api.PullCommand;
|
||||||
|
import org.eclipse.jgit.api.ResetCommand;
|
||||||
|
import org.eclipse.jgit.api.ResetCommand.ResetType;
|
||||||
import org.eclipse.jgit.api.Status;
|
import org.eclipse.jgit.api.Status;
|
||||||
|
import org.eclipse.jgit.api.StatusCommand;
|
||||||
import org.eclipse.jgit.api.TransportCommand;
|
import org.eclipse.jgit.api.TransportCommand;
|
||||||
import org.eclipse.jgit.api.errors.GitAPIException;
|
import org.eclipse.jgit.api.errors.GitAPIException;
|
||||||
import org.eclipse.jgit.api.errors.RefNotFoundException;
|
import org.eclipse.jgit.api.errors.RefNotFoundException;
|
||||||
@@ -55,6 +59,7 @@ import com.jcraft.jsch.Session;
|
|||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
* @author Roy Clarkson
|
* @author Roy Clarkson
|
||||||
* @author Marcos Barbero
|
* @author Marcos Barbero
|
||||||
|
* @author Daniel Lavoie
|
||||||
*/
|
*/
|
||||||
public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||||
implements EnvironmentRepository, SearchPathLocator, InitializingBean {
|
implements EnvironmentRepository, SearchPathLocator, InitializingBean {
|
||||||
@@ -166,6 +171,14 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
|||||||
Ref ref = checkout(git, label);
|
Ref ref = checkout(git, label);
|
||||||
if (shouldPull(git, ref)) {
|
if (shouldPull(git, ref)) {
|
||||||
pull(git, label, ref);
|
pull(git, label, ref);
|
||||||
|
|
||||||
|
if (!isClean(git)) {
|
||||||
|
logger.warn("The local repository is dirty. Reseting it to origin/"
|
||||||
|
+ label + ".");
|
||||||
|
|
||||||
|
fetch(git, label, "origin");
|
||||||
|
resetHard(git, label, "refs/remotes/origin/" + label);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
@@ -264,6 +277,36 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
|||||||
return isBranch(git, label) && !isLocalBranch(git, label);
|
return isBranch(git, label) && !isLocalBranch(git, label);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void fetch(Git git, String label, String remote) {
|
||||||
|
FetchCommand fetch = git.fetch().setRemote(remote);
|
||||||
|
setTimeout(fetch);
|
||||||
|
try {
|
||||||
|
if (hasText(getUsername())) {
|
||||||
|
setCredentialsProvider(fetch);
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch.call();
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
this.logger.warn("Could not fetch remote for " + label + " remote: " + git
|
||||||
|
.getRepository().getConfig().getString("remote", "origin", "url"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resetHard(Git git, String label, String ref) {
|
||||||
|
ResetCommand reset = git.reset();
|
||||||
|
reset.setRef(ref);
|
||||||
|
reset.setMode(ResetType.HARD);
|
||||||
|
try {
|
||||||
|
reset.call();
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
this.logger.warn("Could not reset to remote for " + label + " (current ref="
|
||||||
|
+ ref + "), remote: " + git.getRepository().getConfig()
|
||||||
|
.getString("remote", "origin", "url"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assumes we are on a tracking branch (should be safe)
|
* Assumes we are on a tracking branch (should be safe)
|
||||||
*/
|
*/
|
||||||
@@ -369,6 +412,20 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
|||||||
pull.setTimeout(this.timeout);
|
pull.setTimeout(this.timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isClean(Git git) {
|
||||||
|
StatusCommand status = git.status();
|
||||||
|
try {
|
||||||
|
return status.call().isClean();
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
this.logger
|
||||||
|
.warn("Could not execute status command on local repository. Cause: ("
|
||||||
|
+ e.getClass().getSimpleName() + ") " + e.getMessage());
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void trackBranch(Git git, CheckoutCommand checkout, String label) {
|
private void trackBranch(Git git, CheckoutCommand checkout, String label) {
|
||||||
checkout.setCreateBranch(true).setName(label)
|
checkout.setCreateBranch(true).setName(label)
|
||||||
.setUpstreamMode(SetupUpstreamMode.TRACK)
|
.setUpstreamMode(SetupUpstreamMode.TRACK)
|
||||||
|
|||||||
@@ -15,6 +15,9 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.cloud.config.server.test;
|
package org.springframework.cloud.config.server.test;
|
||||||
|
|
||||||
|
import org.eclipse.jgit.lib.Repository;
|
||||||
|
import org.eclipse.jgit.lib.RepositoryCache.FileKey;
|
||||||
|
import org.eclipse.jgit.util.FS;
|
||||||
import org.eclipse.jgit.util.FileUtils;
|
import org.eclipse.jgit.util.FileUtils;
|
||||||
import org.springframework.util.FileSystemUtils;
|
import org.springframework.util.FileSystemUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
@@ -24,8 +27,22 @@ import java.io.IOException;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
|
* @author Daniel Lavoie
|
||||||
*/
|
*/
|
||||||
public class ConfigServerTestUtils {
|
public class ConfigServerTestUtils {
|
||||||
|
public static Repository prepareBareRemote() throws IOException {
|
||||||
|
// Create a folder in the temp folder that will act as the remote repository
|
||||||
|
File remoteDir = File.createTempFile("remote", "");
|
||||||
|
remoteDir.delete();
|
||||||
|
remoteDir.mkdirs();
|
||||||
|
|
||||||
|
// Create a bare repository
|
||||||
|
FileKey fileKey = FileKey.exact(remoteDir, FS.DETECTED);
|
||||||
|
Repository remoteRepo = fileKey.open(false);
|
||||||
|
remoteRepo.create(true);
|
||||||
|
|
||||||
|
return remoteRepo;
|
||||||
|
}
|
||||||
|
|
||||||
public static String prepareLocalRepo() throws IOException {
|
public static String prepareLocalRepo() throws IOException {
|
||||||
return prepareLocalRepo("./", "target/repos", "config-repo", "target/config");
|
return prepareLocalRepo("./", "target/repos", "config-repo", "target/config");
|
||||||
|
|||||||
@@ -26,12 +26,21 @@ import java.io.File;
|
|||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.nio.file.StandardOpenOption;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import org.eclipse.jgit.api.Git;
|
import org.eclipse.jgit.api.Git;
|
||||||
|
import org.eclipse.jgit.api.ResetCommand.ResetType;
|
||||||
|
import org.eclipse.jgit.lib.Repository;
|
||||||
|
import org.eclipse.jgit.lib.StoredConfig;
|
||||||
import org.eclipse.jgit.util.FileUtils;
|
import org.eclipse.jgit.util.FileUtils;
|
||||||
import org.hamcrest.Matchers;
|
import org.hamcrest.Matchers;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
|
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
|
||||||
@@ -48,6 +57,7 @@ import org.springframework.util.StreamUtils;
|
|||||||
/**
|
/**
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
* @author Roy Clarkson
|
* @author Roy Clarkson
|
||||||
|
* @author Daniel Lavoie
|
||||||
*/
|
*/
|
||||||
public class JGitEnvironmentRepositoryIntegrationTests {
|
public class JGitEnvironmentRepositoryIntegrationTests {
|
||||||
|
|
||||||
@@ -108,6 +118,67 @@ public class JGitEnvironmentRepositoryIntegrationTests {
|
|||||||
environment.getPropertySources().get(0).getSource().get("foo"));
|
environment.getPropertySources().get(0).getSource().get("foo"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests a special use case where the remote repository has been updated with a forced
|
||||||
|
* push conflicting with the local repo of the Config Server. The Config Server has to
|
||||||
|
* reset hard on the new reference because a simple pull operation could result in a
|
||||||
|
* conflicting local repository.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void pullDirtyRepo() throws Exception {
|
||||||
|
ConfigServerTestUtils.prepareLocalRepo();
|
||||||
|
String uri = ConfigServerTestUtils.copyLocalRepo("config-copy");
|
||||||
|
|
||||||
|
// Create a remote bare repository.
|
||||||
|
Repository remote = ConfigServerTestUtils.prepareBareRemote();
|
||||||
|
|
||||||
|
Git git = Git.open(ResourceUtils.getFile(uri).getAbsoluteFile());
|
||||||
|
StoredConfig config = git.getRepository().getConfig();
|
||||||
|
config.setString("remote", "origin", "url",
|
||||||
|
remote.getDirectory().getAbsolutePath());
|
||||||
|
config.setString("remote", "origin", "fetch",
|
||||||
|
"+refs/heads/*:refs/remotes/origin/*");
|
||||||
|
config.save();
|
||||||
|
|
||||||
|
// Pushes the raw branch to remote repository.
|
||||||
|
git.push().call();
|
||||||
|
|
||||||
|
String commitToRevertBeforePull = git.log().setMaxCount(1).call().iterator()
|
||||||
|
.next().getName();
|
||||||
|
|
||||||
|
this.context = new SpringApplicationBuilder(TestConfiguration.class).web(false)
|
||||||
|
.run("--spring.cloud.config.server.git.uri=" + uri);
|
||||||
|
|
||||||
|
JGitEnvironmentRepository repository = this.context
|
||||||
|
.getBean(JGitEnvironmentRepository.class);
|
||||||
|
|
||||||
|
// Fetches the repository for the first time.
|
||||||
|
repository.getLocations("bar", "test", "raw");
|
||||||
|
|
||||||
|
// Resets to the original commit.
|
||||||
|
git.reset().setMode(ResetType.HARD).setRef("master").call();
|
||||||
|
|
||||||
|
// Generate a conflicting commit who will be forced on the origin.
|
||||||
|
Path applicationFilePath = Paths
|
||||||
|
.get(ResourceUtils.getFile(uri).getAbsoluteFile() + "/application.yml");
|
||||||
|
|
||||||
|
Files.write(applicationFilePath,
|
||||||
|
Arrays.asList("info:", " foo: bar", "raw: false"),
|
||||||
|
StandardCharsets.UTF_8, StandardOpenOption.TRUNCATE_EXISTING);
|
||||||
|
git.add().addFilepattern(".").call();
|
||||||
|
git.commit().setMessage("Conflicting commit.").call();
|
||||||
|
git.push().setForce(true).call();
|
||||||
|
|
||||||
|
// Reset to the raw branch.
|
||||||
|
git.reset().setMode(ResetType.HARD).setRef(commitToRevertBeforePull).call();
|
||||||
|
|
||||||
|
// Triggers the repository refresh.
|
||||||
|
repository.getLocations("bar", "test", "raw");
|
||||||
|
|
||||||
|
Assert.assertTrue("Local repository is not cleaned after retreiving resources.",
|
||||||
|
git.status().call().isClean());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void nested() throws IOException {
|
public void nested() throws IOException {
|
||||||
String uri = ConfigServerTestUtils.prepareLocalRepo("another-config-repo");
|
String uri = ConfigServerTestUtils.prepareLocalRepo("another-config-repo");
|
||||||
|
|||||||
Reference in New Issue
Block a user