Merge branch 'master' into 2.0.x
There are still issues with the encryptor in bootstrap mode.
This commit is contained in:
@@ -14,7 +14,7 @@
|
||||
<properties>
|
||||
<docs.main>spring-cloud-config</docs.main>
|
||||
<main.basedir>${basedir}/..</main.basedir>
|
||||
<docs.whitelisted.branches>1.1.x</docs.whitelisted.branches>
|
||||
<docs.whitelisted.branches>1.3.x</docs.whitelisted.branches>
|
||||
</properties>
|
||||
<build>
|
||||
<plugins>
|
||||
|
||||
@@ -479,8 +479,9 @@ on the search path, so properties files are loaded from each search
|
||||
location *and* a subdirectory with the same name as the label (the
|
||||
labelled properties take precedence in the Spring Environment). Thus
|
||||
the default behaviour with no placeholders is the same as adding a
|
||||
search location ending with `/{label}/. For example `file:/tmp/config`
|
||||
is the same as `file:/tmp/config,file:/tmp/config/{label}`
|
||||
search location ending with `/{label}/`. For example `file:/tmp/config`
|
||||
is the same as `file:/tmp/config,file:/tmp/config/{label}`. This behavior can be
|
||||
disabled by setting `spring.cloud.config.server.native.addLabelLocations=false`.
|
||||
|
||||
==== Vault Backend
|
||||
|
||||
@@ -1308,23 +1309,13 @@ 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`.
|
||||
1. 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();
|
||||
@@ -1335,10 +1326,10 @@ public class CustomConfigServiceBootstrapConfiguration {
|
||||
}
|
||||
----
|
||||
|
||||
3. In `resources/META-INF` create a file called
|
||||
2. In `resources/META-INF` create a file called
|
||||
`spring.factories` and specify your custom configuration.
|
||||
|
||||
.spring.factorties
|
||||
.spring.factories
|
||||
[source,properties]
|
||||
----
|
||||
org.springframework.cloud.bootstrap.BootstrapConfiguration = com.my.config.client.CustomConfigServiceBootstrapConfiguration
|
||||
|
||||
286
mvnw.cmd
vendored
286
mvnw.cmd
vendored
@@ -1,145 +1,145 @@
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Licensed to the Apache Software Foundation (ASF) under one
|
||||
@REM or more contributor license agreements. See the NOTICE file
|
||||
@REM distributed with this work for additional information
|
||||
@REM regarding copyright ownership. The ASF licenses this file
|
||||
@REM to you under the Apache License, Version 2.0 (the
|
||||
@REM "License"); you may not use this file except in compliance
|
||||
@REM with the License. You may obtain a copy of the License at
|
||||
@REM
|
||||
@REM http://www.apache.org/licenses/LICENSE-2.0
|
||||
@REM
|
||||
@REM Unless required by applicable law or agreed to in writing,
|
||||
@REM software distributed under the License is distributed on an
|
||||
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
@REM KIND, either express or implied. See the License for the
|
||||
@REM specific language governing permissions and limitations
|
||||
@REM under the License.
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Maven2 Start Up Batch script
|
||||
@REM
|
||||
@REM Required ENV vars:
|
||||
@REM JAVA_HOME - location of a JDK home dir
|
||||
@REM
|
||||
@REM Optional ENV vars
|
||||
@REM M2_HOME - location of maven2's installed home dir
|
||||
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
|
||||
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
|
||||
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
@REM e.g. to debug Maven itself, use
|
||||
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
|
||||
@echo off
|
||||
@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
|
||||
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
|
||||
|
||||
@REM set %HOME% to equivalent of $HOME
|
||||
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
|
||||
|
||||
@REM Execute a user defined script before this one
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
|
||||
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
|
||||
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
|
||||
:skipRcPre
|
||||
|
||||
@setlocal
|
||||
|
||||
set ERROR_CODE=0
|
||||
|
||||
@REM To isolate internal variables from possible post scripts, we use another setlocal
|
||||
@setlocal
|
||||
|
||||
@REM ==== START VALIDATION ====
|
||||
if not "%JAVA_HOME%" == "" goto OkJHome
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME not found in your environment. >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
:OkJHome
|
||||
if exist "%JAVA_HOME%\bin\java.exe" goto init
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME is set to an invalid directory. >&2
|
||||
echo JAVA_HOME = "%JAVA_HOME%" >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
@REM ==== END VALIDATION ====
|
||||
|
||||
:init
|
||||
|
||||
set MAVEN_CMD_LINE_ARGS=%*
|
||||
|
||||
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
|
||||
@REM Fallback to current working directory if not found.
|
||||
|
||||
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
|
||||
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
|
||||
|
||||
set EXEC_DIR=%CD%
|
||||
set WDIR=%EXEC_DIR%
|
||||
:findBaseDir
|
||||
IF EXIST "%WDIR%"\.mvn goto baseDirFound
|
||||
cd ..
|
||||
IF "%WDIR%"=="%CD%" goto baseDirNotFound
|
||||
set WDIR=%CD%
|
||||
goto findBaseDir
|
||||
|
||||
:baseDirFound
|
||||
set MAVEN_PROJECTBASEDIR=%WDIR%
|
||||
cd "%EXEC_DIR%"
|
||||
goto endDetectBaseDir
|
||||
|
||||
:baseDirNotFound
|
||||
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
|
||||
cd "%EXEC_DIR%"
|
||||
|
||||
:endDetectBaseDir
|
||||
|
||||
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
|
||||
|
||||
@setlocal EnableExtensions EnableDelayedExpansion
|
||||
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
|
||||
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
|
||||
|
||||
:endReadAdditionalConfig
|
||||
|
||||
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Licensed to the Apache Software Foundation (ASF) under one
|
||||
@REM or more contributor license agreements. See the NOTICE file
|
||||
@REM distributed with this work for additional information
|
||||
@REM regarding copyright ownership. The ASF licenses this file
|
||||
@REM to you under the Apache License, Version 2.0 (the
|
||||
@REM "License"); you may not use this file except in compliance
|
||||
@REM with the License. You may obtain a copy of the License at
|
||||
@REM
|
||||
@REM http://www.apache.org/licenses/LICENSE-2.0
|
||||
@REM
|
||||
@REM Unless required by applicable law or agreed to in writing,
|
||||
@REM software distributed under the License is distributed on an
|
||||
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
@REM KIND, either express or implied. See the License for the
|
||||
@REM specific language governing permissions and limitations
|
||||
@REM under the License.
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Maven2 Start Up Batch script
|
||||
@REM
|
||||
@REM Required ENV vars:
|
||||
@REM JAVA_HOME - location of a JDK home dir
|
||||
@REM
|
||||
@REM Optional ENV vars
|
||||
@REM M2_HOME - location of maven2's installed home dir
|
||||
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
|
||||
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
|
||||
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
@REM e.g. to debug Maven itself, use
|
||||
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
|
||||
@echo off
|
||||
@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
|
||||
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
|
||||
|
||||
@REM set %HOME% to equivalent of $HOME
|
||||
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
|
||||
|
||||
@REM Execute a user defined script before this one
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
|
||||
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
|
||||
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
|
||||
:skipRcPre
|
||||
|
||||
@setlocal
|
||||
|
||||
set ERROR_CODE=0
|
||||
|
||||
@REM To isolate internal variables from possible post scripts, we use another setlocal
|
||||
@setlocal
|
||||
|
||||
@REM ==== START VALIDATION ====
|
||||
if not "%JAVA_HOME%" == "" goto OkJHome
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME not found in your environment. >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
:OkJHome
|
||||
if exist "%JAVA_HOME%\bin\java.exe" goto init
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME is set to an invalid directory. >&2
|
||||
echo JAVA_HOME = "%JAVA_HOME%" >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
@REM ==== END VALIDATION ====
|
||||
|
||||
:init
|
||||
|
||||
set MAVEN_CMD_LINE_ARGS=%*
|
||||
|
||||
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
|
||||
@REM Fallback to current working directory if not found.
|
||||
|
||||
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
|
||||
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
|
||||
|
||||
set EXEC_DIR=%CD%
|
||||
set WDIR=%EXEC_DIR%
|
||||
:findBaseDir
|
||||
IF EXIST "%WDIR%"\.mvn goto baseDirFound
|
||||
cd ..
|
||||
IF "%WDIR%"=="%CD%" goto baseDirNotFound
|
||||
set WDIR=%CD%
|
||||
goto findBaseDir
|
||||
|
||||
:baseDirFound
|
||||
set MAVEN_PROJECTBASEDIR=%WDIR%
|
||||
cd "%EXEC_DIR%"
|
||||
goto endDetectBaseDir
|
||||
|
||||
:baseDirNotFound
|
||||
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
|
||||
cd "%EXEC_DIR%"
|
||||
|
||||
:endDetectBaseDir
|
||||
|
||||
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
|
||||
|
||||
@setlocal EnableExtensions EnableDelayedExpansion
|
||||
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
|
||||
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
|
||||
|
||||
:endReadAdditionalConfig
|
||||
|
||||
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
|
||||
|
||||
set WRAPPER_JAR="".\.mvn\wrapper\maven-wrapper.jar""
|
||||
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS%
|
||||
if ERRORLEVEL 1 goto error
|
||||
goto end
|
||||
|
||||
:error
|
||||
set ERROR_CODE=1
|
||||
|
||||
:end
|
||||
@endlocal & set ERROR_CODE=%ERROR_CODE%
|
||||
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
|
||||
@REM check for post script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
|
||||
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
|
||||
:skipRcPost
|
||||
|
||||
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
|
||||
if "%MAVEN_BATCH_PAUSE%" == "on" pause
|
||||
|
||||
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
|
||||
|
||||
exit /B %ERROR_CODE%
|
||||
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS%
|
||||
if ERRORLEVEL 1 goto error
|
||||
goto end
|
||||
|
||||
:error
|
||||
set ERROR_CODE=1
|
||||
|
||||
:end
|
||||
@endlocal & set ERROR_CODE=%ERROR_CODE%
|
||||
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
|
||||
@REM check for post script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
|
||||
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
|
||||
:skipRcPost
|
||||
|
||||
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
|
||||
if "%MAVEN_BATCH_PAUSE%" == "on" pause
|
||||
|
||||
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
|
||||
|
||||
exit /B %ERROR_CODE%
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
* Copyright 2013-2017 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.
|
||||
@@ -34,6 +34,7 @@ import org.springframework.retry.interceptor.RetryOperationsInterceptor;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* @author Tristan Hanson
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@@ -50,6 +51,7 @@ public class ConfigServiceBootstrapConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(ConfigServicePropertySourceLocator.class)
|
||||
@ConditionalOnProperty(value = "spring.cloud.config.enabled", matchIfMissing = true)
|
||||
public ConfigServicePropertySourceLocator configServicePropertySource(ConfigClientProperties properties) {
|
||||
ConfigServicePropertySourceLocator locator = new ConfigServicePropertySourceLocator(
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2013-2017 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.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.util.EnvironmentTestUtils;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Tristan Hanson
|
||||
*
|
||||
*/
|
||||
public class ConfigServiceBootstrapConfigurationTest {
|
||||
|
||||
private AnnotationConfigApplicationContext context;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
this.context = new AnnotationConfigApplicationContext();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
if (this.context != null) {
|
||||
this.context.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void overrideConfigServicePropertySourceLocatorWhenBeanIsProvided() {
|
||||
EnvironmentTestUtils.addEnvironment(this.context, "spring.cloud.config.enabled=true");
|
||||
this.context.register(ConfigServicePropertySourceLocatorOverrideConfig.class);
|
||||
this.context.register(ConfigServiceBootstrapConfiguration.class);
|
||||
this.context.refresh();
|
||||
|
||||
ConfigServicePropertySourceLocator locator = this.context.getBean(ConfigServicePropertySourceLocator.class);
|
||||
|
||||
Field restTemplateField = ReflectionUtils.findField(ConfigServicePropertySourceLocator.class, "restTemplate");
|
||||
restTemplateField.setAccessible(true);
|
||||
|
||||
RestTemplate restTemplate = (RestTemplate) ReflectionUtils.getField(restTemplateField, locator);
|
||||
|
||||
assertThat(restTemplate).isNotNull();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
protected static class ConfigServicePropertySourceLocatorOverrideConfig {
|
||||
|
||||
@Autowired
|
||||
private Environment environment;
|
||||
|
||||
@Bean
|
||||
public ConfigServicePropertySourceLocator locator() {
|
||||
ConfigServicePropertySourceLocator locator = new ConfigServicePropertySourceLocator(new ConfigClientProperties(environment));
|
||||
locator.setRestTemplate(new RestTemplate());
|
||||
return locator;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,17 +15,24 @@
|
||||
*/
|
||||
package org.springframework.cloud.config.server.bootstrap;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.config.client.ConfigClientProperties;
|
||||
import org.springframework.cloud.config.server.config.ConfigServerProperties;
|
||||
import org.springframework.cloud.config.server.config.EncryptionAutoConfiguration;
|
||||
import org.springframework.cloud.config.server.config.EnvironmentRepositoryConfiguration;
|
||||
import org.springframework.cloud.config.server.encryption.LocatorTextEncryptor;
|
||||
import org.springframework.cloud.config.server.environment.EnvironmentRepository;
|
||||
import org.springframework.cloud.config.server.environment.EnvironmentRepositoryPropertySourceLocator;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.security.crypto.encrypt.TextEncryptor;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -39,9 +46,28 @@ import org.springframework.util.StringUtils;
|
||||
* @author Roy Clarkson
|
||||
*/
|
||||
@Configuration
|
||||
public class ConfigServerBootstrapConfiguration {
|
||||
@ConditionalOnProperty("spring.cloud.config.server.bootstrap")
|
||||
@AutoConfigureBefore(EncryptionAutoConfiguration.class)
|
||||
public class ConfigServerBootstrapConfiguration implements BeanPostProcessor {
|
||||
|
||||
@Autowired
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
@Override
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName)
|
||||
throws BeansException {
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName)
|
||||
throws BeansException {
|
||||
if (bean instanceof TextEncryptor && !(bean instanceof LocatorTextEncryptor)) {
|
||||
return new LocatorTextEncryptor(beanFactory);
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
@ConditionalOnProperty("spring.cloud.config.server.bootstrap")
|
||||
@EnableConfigurationProperties(ConfigServerProperties.class)
|
||||
@Import(EnvironmentRepositoryConfiguration.class)
|
||||
protected static class LocalPropertySourceLocatorConfiguration {
|
||||
|
||||
@@ -17,6 +17,7 @@ package org.springframework.cloud.config.server.config;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.eclipse.jgit.api.TransportConfigCallback;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
@@ -83,10 +84,14 @@ class DefaultRepositoryConfiguration {
|
||||
@Autowired
|
||||
private ConfigServerProperties server;
|
||||
|
||||
@Autowired(required = false)
|
||||
private TransportConfigCallback transportConfigCallback;
|
||||
|
||||
@Bean
|
||||
public MultipleJGitEnvironmentRepository defaultEnvironmentRepository() {
|
||||
MultipleJGitEnvironmentRepository repository = new MultipleJGitEnvironmentRepository(
|
||||
this.environment);
|
||||
repository.setTransportConfigCallback(this.transportConfigCallback);
|
||||
if (this.server.getDefaultLabel() != null) {
|
||||
repository.setDefaultLabel(this.server.getDefaultLabel());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.encryption;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.security.crypto.encrypt.TextEncryptor;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class LocatorTextEncryptor implements TextEncryptor {
|
||||
|
||||
private EnvironmentPrefixHelper helper = new EnvironmentPrefixHelper();
|
||||
|
||||
private TextEncryptorLocator locator;
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
public LocatorTextEncryptor(BeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String encrypt(String text) {
|
||||
Map<String, String> keys = helper.getEncryptorKeys("configserver", "default",
|
||||
text);
|
||||
return getLocator().locate(keys).encrypt(helper.stripPrefix(text));
|
||||
}
|
||||
|
||||
private TextEncryptorLocator getLocator() {
|
||||
if (locator == null) {
|
||||
locator = beanFactory.getBean(TextEncryptorLocator.class);
|
||||
}
|
||||
return locator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String decrypt(String encryptedText) {
|
||||
Map<String, String> keys = helper.getEncryptorKeys("configserver", "default",
|
||||
encryptedText);
|
||||
return getLocator().locate(keys).decrypt(helper.stripPrefix(encryptedText));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -41,8 +41,15 @@ public class CompositeEnvironmentRepository implements EnvironmentRepository {
|
||||
@Override
|
||||
public Environment findOne(String application, String profile, String label) {
|
||||
Environment env = new Environment(application, new String[]{profile}, label, null, null);
|
||||
for(EnvironmentRepository repo : environmentRepositories) {
|
||||
env.addAll(repo.findOne(application, profile, label).getPropertySources());
|
||||
if(environmentRepositories.size() == 1) {
|
||||
Environment envRepo = environmentRepositories.get(0).findOne(application, profile, label);
|
||||
env.addAll(envRepo.getPropertySources());
|
||||
env.setVersion(envRepo.getVersion());
|
||||
env.setState(envRepo.getState());
|
||||
} else {
|
||||
for (EnvironmentRepository repo : environmentRepositories) {
|
||||
env.addAll(repo.findOne(application, profile, label).getPropertySources());
|
||||
}
|
||||
}
|
||||
return env;
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.yaml.snakeyaml.DumperOptions.FlowStyle;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
@@ -223,7 +224,7 @@ public class EnvironmentController {
|
||||
return rootMap;
|
||||
}
|
||||
|
||||
@ExceptionHandler(NoSuchLabelException.class)
|
||||
@ExceptionHandler(RepositoryException.class)
|
||||
public void noSuchLabel(HttpServletResponse response) throws IOException {
|
||||
response.sendError(HttpStatus.NOT_FOUND.value());
|
||||
}
|
||||
|
||||
@@ -36,8 +36,10 @@ import org.eclipse.jgit.api.ResetCommand.ResetType;
|
||||
import org.eclipse.jgit.api.Status;
|
||||
import org.eclipse.jgit.api.StatusCommand;
|
||||
import org.eclipse.jgit.api.TransportCommand;
|
||||
import org.eclipse.jgit.api.TransportConfigCallback;
|
||||
import org.eclipse.jgit.api.errors.GitAPIException;
|
||||
import org.eclipse.jgit.api.errors.RefNotFoundException;
|
||||
import org.eclipse.jgit.errors.NoRemoteRepositoryException;
|
||||
import org.eclipse.jgit.lib.Ref;
|
||||
import org.eclipse.jgit.transport.CredentialsProvider;
|
||||
import org.eclipse.jgit.transport.FetchResult;
|
||||
@@ -74,31 +76,36 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
private static final String FILE_URI_PREFIX = "file:";
|
||||
|
||||
/**
|
||||
* Timeout (in seconds) for obtaining HTTP or SSH connection (if applicable). Default
|
||||
* 5 seconds.
|
||||
* Timeout (in seconds) for obtaining HTTP or SSH connection (if
|
||||
* applicable). Default 5 seconds.
|
||||
*/
|
||||
private int timeout = 5;
|
||||
|
||||
private boolean initialized;
|
||||
|
||||
/**
|
||||
* Flag to indicate that the repository should be cloned on startup (not on demand).
|
||||
* Generally leads to slower startup but faster first query.
|
||||
* Flag to indicate that the repository should be cloned on startup (not on
|
||||
* demand). Generally leads to slower startup but faster first query.
|
||||
*/
|
||||
private boolean cloneOnStart = false;
|
||||
|
||||
private JGitEnvironmentRepository.JGitFactory gitFactory = new JGitEnvironmentRepository.JGitFactory();
|
||||
|
||||
private String defaultLabel = DEFAULT_LABEL;
|
||||
|
||||
|
||||
/**
|
||||
* The credentials provider to use to connect to the Git repository.
|
||||
*/
|
||||
private CredentialsProvider gitCredentialsProvider;
|
||||
|
||||
/**
|
||||
* Flag to indicate that the repository should force pull. If true discard any local
|
||||
* changes and take from remote repository.
|
||||
* Transport configuration callback for JGit commands.
|
||||
*/
|
||||
private TransportConfigCallback transportConfigCallback;
|
||||
|
||||
/**
|
||||
* Flag to indicate that the repository should force pull. If true discard
|
||||
* any local changes and take from remote repository.
|
||||
*/
|
||||
private boolean forcePull;
|
||||
|
||||
@@ -122,6 +129,14 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
public TransportConfigCallback getTransportConfigCallback() {
|
||||
return transportConfigCallback;
|
||||
}
|
||||
|
||||
public void setTransportConfigCallback(TransportConfigCallback transportConfigCallback) {
|
||||
this.transportConfigCallback = transportConfigCallback;
|
||||
}
|
||||
|
||||
public JGitFactory getGitFactory() {
|
||||
return this.gitFactory;
|
||||
}
|
||||
@@ -147,8 +162,7 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Locations getLocations(String application, String profile,
|
||||
String label) {
|
||||
public synchronized Locations getLocations(String application, String profile, String label) {
|
||||
if (label == null) {
|
||||
label = this.defaultLabel;
|
||||
}
|
||||
@@ -159,8 +173,7 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.state(getUri() != null,
|
||||
"You need to configure a uri for the git repository");
|
||||
Assert.state(getUri() != null, "You need to configure a uri for the git repository");
|
||||
initialize();
|
||||
if (this.cloneOnStart) {
|
||||
initClonedRepository();
|
||||
@@ -177,41 +190,37 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
git = createGitClient();
|
||||
if (shouldPull(git)) {
|
||||
fetch(git, label);
|
||||
//checkout after fetch so we can get any new branches, tags, ect.
|
||||
// checkout after fetch so we can get any new branches, tags,
|
||||
// ect.
|
||||
checkout(git, label);
|
||||
if(isBranch(git, label)) {
|
||||
//merge results from fetch
|
||||
if (isBranch(git, label)) {
|
||||
// merge results from fetch
|
||||
merge(git, label);
|
||||
if (!isClean(git)) {
|
||||
logger.warn("The local repository is dirty. Resetting it to origin/"
|
||||
+ label + ".");
|
||||
logger.warn("The local repository is dirty. Resetting it to origin/" + label + ".");
|
||||
resetHard(git, label, "refs/remotes/origin/" + label);
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
//nothing to update so just checkout
|
||||
} else {
|
||||
// nothing to update so just checkout
|
||||
checkout(git, label);
|
||||
}
|
||||
//always return what is currently HEAD as the version
|
||||
return git.getRepository().getRef("HEAD").getObjectId().getName();
|
||||
}
|
||||
catch (RefNotFoundException e) {
|
||||
// always return what is currently HEAD as the version
|
||||
return git.getRepository().findRef("HEAD").getObjectId().getName();
|
||||
} catch (RefNotFoundException e) {
|
||||
throw new NoSuchLabelException("No such label: " + label, e);
|
||||
}
|
||||
catch (GitAPIException e) {
|
||||
throw new IllegalStateException("Cannot clone or checkout repository", e);
|
||||
}
|
||||
catch (Exception e) {
|
||||
} catch (NoRemoteRepositoryException e) {
|
||||
throw new NoSuchRepositoryException("No such repository: " + getUri(), e);
|
||||
} catch (GitAPIException e) {
|
||||
throw new NoSuchRepositoryException("Cannot clone or checkout repository: " + getUri(), e);
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException("Cannot load environment", e);
|
||||
}
|
||||
finally {
|
||||
} finally {
|
||||
try {
|
||||
if (git != null) {
|
||||
git.close();
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
} catch (Exception e) {
|
||||
this.logger.warn("Could not close git repository", e);
|
||||
}
|
||||
}
|
||||
@@ -219,6 +228,7 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
|
||||
/**
|
||||
* Clones the remote repository and then opens a connection to it.
|
||||
*
|
||||
* @throws GitAPIException
|
||||
* @throws IOException
|
||||
*/
|
||||
@@ -241,41 +251,35 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
CheckoutCommand checkout = git.checkout();
|
||||
if (shouldTrack(git, label)) {
|
||||
trackBranch(git, checkout, label);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// works for tags and local branches
|
||||
checkout.setName(label);
|
||||
}
|
||||
return checkout.call();
|
||||
}
|
||||
|
||||
|
||||
public /*public for testing*/ boolean shouldPull(Git git) throws GitAPIException {
|
||||
protected boolean shouldPull(Git git) throws GitAPIException {
|
||||
boolean shouldPull;
|
||||
Status gitStatus = git.status().call();
|
||||
boolean isWorkingTreeClean = gitStatus.isClean();
|
||||
String originUrl = git.getRepository().getConfig().getString("remote", "origin",
|
||||
"url");
|
||||
String originUrl = git.getRepository().getConfig().getString("remote", "origin", "url");
|
||||
|
||||
if (this.forcePull && !isWorkingTreeClean) {
|
||||
shouldPull = true;
|
||||
logDirty(gitStatus);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
shouldPull = isWorkingTreeClean && originUrl != null;
|
||||
}
|
||||
if (!isWorkingTreeClean && !this.forcePull) {
|
||||
this.logger.info("Cannot pull from remote " + originUrl
|
||||
+ ", the working tree is not clean.");
|
||||
this.logger.info("Cannot pull from remote " + originUrl + ", the working tree is not clean.");
|
||||
}
|
||||
return shouldPull;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void logDirty(Status status) {
|
||||
Set<String> dirties = dirties(status.getAdded(), status.getChanged(),
|
||||
status.getRemoved(), status.getMissing(), status.getModified(),
|
||||
status.getConflicting(), status.getUntracked());
|
||||
Set<String> dirties = dirties(status.getAdded(), status.getChanged(), status.getRemoved(), status.getMissing(),
|
||||
status.getModified(), status.getConflicting(), status.getUntracked());
|
||||
this.logger.warn(String.format("Dirty files found: %s", dirties));
|
||||
}
|
||||
|
||||
@@ -292,24 +296,22 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
return isBranch(git, label) && !isLocalBranch(git, label);
|
||||
}
|
||||
|
||||
private FetchResult fetch(Git git, String label) {
|
||||
protected FetchResult fetch(Git git, String label) {
|
||||
FetchCommand fetch = git.fetch();
|
||||
fetch.setRemote("origin");
|
||||
fetch.setTagOpt(TagOpt.FETCH_TAGS);
|
||||
|
||||
setTimeout(fetch);
|
||||
configureCommand(fetch);
|
||||
try {
|
||||
setCredentialsProvider(fetch);
|
||||
FetchResult result = fetch.call();
|
||||
if(result.getTrackingRefUpdates() != null && result.getTrackingRefUpdates().size() > 0) {
|
||||
if (result.getTrackingRefUpdates() != null && result.getTrackingRefUpdates().size() > 0) {
|
||||
logger.info("Fetched for remote " + label + " and found " + result.getTrackingRefUpdates().size()
|
||||
+ " updates");
|
||||
+ " updates");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
String message = "Could not fetch remote for " + label + " remote: " + git
|
||||
.getRepository().getConfig().getString("remote", "origin", "url");
|
||||
} catch (Exception ex) {
|
||||
String message = "Could not fetch remote for " + label + " remote: "
|
||||
+ git.getRepository().getConfig().getString("remote", "origin", "url");
|
||||
warn(message, ex);
|
||||
return null;
|
||||
}
|
||||
@@ -318,16 +320,15 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
private MergeResult merge(Git git, String label) {
|
||||
try {
|
||||
MergeCommand merge = git.merge();
|
||||
merge.include(git.getRepository().getRef("origin/" + label));
|
||||
merge.include(git.getRepository().findRef("origin/" + label));
|
||||
MergeResult result = merge.call();
|
||||
if(!result.getMergeStatus().isSuccessful()) {
|
||||
if (!result.getMergeStatus().isSuccessful()) {
|
||||
this.logger.warn("Merged from remote " + label + " with result " + result.getMergeStatus());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
String message = "Could not merge remote for " + label + " remote: " + git
|
||||
.getRepository().getConfig().getString("remote", "origin", "url");
|
||||
} catch (Exception ex) {
|
||||
String message = "Could not merge remote for " + label + " remote: "
|
||||
+ git.getRepository().getConfig().getString("remote", "origin", "url");
|
||||
warn(message, ex);
|
||||
return null;
|
||||
}
|
||||
@@ -339,31 +340,38 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
reset.setMode(ResetType.HARD);
|
||||
try {
|
||||
Ref resetRef = reset.call();
|
||||
if(resetRef != null) {
|
||||
if (resetRef != null) {
|
||||
this.logger.info("Reset label " + label + " to version " + resetRef.getObjectId());
|
||||
}
|
||||
return resetRef;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
String message = "Could not reset to remote for " + label + " (current ref="
|
||||
+ ref + "), remote: " + git.getRepository().getConfig()
|
||||
.getString("remote", "origin", "url");
|
||||
} catch (Exception ex) {
|
||||
String message = "Could not reset to remote for " + label + " (current ref=" + ref + "), remote: "
|
||||
+ git.getRepository().getConfig().getString("remote", "origin", "url");
|
||||
warn(message, ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Git createGitClient() throws IOException, GitAPIException {
|
||||
if (new File(getBasedir(), ".git").exists()) {
|
||||
return openGitRepository();
|
||||
File lock = new File(getWorkingDirectory(), ".git/index.lock");
|
||||
if (lock.exists()) {
|
||||
// The only way this can happen is if another JVM (e.g. one that
|
||||
// crashed earlier) created the lock. We can attempt to recover by
|
||||
// wiping the slate clean.
|
||||
logger.info("Deleting stale JGit lock file at " + lock);
|
||||
lock.delete();
|
||||
}
|
||||
else {
|
||||
if (new File(getWorkingDirectory(), ".git").exists()) {
|
||||
return openGitRepository();
|
||||
} else {
|
||||
return copyRepository();
|
||||
}
|
||||
}
|
||||
|
||||
// Synchronize here so that multiple requests don't all try and delete the base dir
|
||||
// together (this is a once only operation, so it only holds things up on the first
|
||||
// Synchronize here so that multiple requests don't all try and delete the
|
||||
// base dir
|
||||
// together (this is a once only operation, so it only holds things up on
|
||||
// the first
|
||||
// request).
|
||||
private synchronized Git copyRepository() throws IOException, GitAPIException {
|
||||
deleteBaseDirIfExists();
|
||||
@@ -371,8 +379,7 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
Assert.state(getBasedir().exists(), "Could not create basedir: " + getBasedir());
|
||||
if (getUri().startsWith(FILE_URI_PREFIX)) {
|
||||
return copyFromLocalRepository();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return cloneToBasedir();
|
||||
}
|
||||
}
|
||||
@@ -394,14 +401,12 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
}
|
||||
|
||||
private Git cloneToBasedir() throws GitAPIException {
|
||||
CloneCommand clone = this.gitFactory.getCloneCommandByCloneRepository()
|
||||
.setURI(getUri()).setDirectory(getBasedir());
|
||||
setTimeout(clone);
|
||||
setCredentialsProvider(clone);
|
||||
CloneCommand clone = this.gitFactory.getCloneCommandByCloneRepository().setURI(getUri())
|
||||
.setDirectory(getBasedir());
|
||||
configureCommand(clone);
|
||||
try {
|
||||
return clone.call();
|
||||
}
|
||||
catch (GitAPIException e) {
|
||||
} catch (GitAPIException e) {
|
||||
deleteBaseDirIfExists();
|
||||
throw e;
|
||||
}
|
||||
@@ -411,8 +416,7 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
if (getBasedir().exists()) {
|
||||
try {
|
||||
FileUtils.delete(getBasedir(), FileUtils.RECURSIVE);
|
||||
}
|
||||
catch (IOException e) {
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException("Failed to initialize base directory", e);
|
||||
}
|
||||
}
|
||||
@@ -430,28 +434,38 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
}
|
||||
}
|
||||
|
||||
private void setCredentialsProvider(TransportCommand<?, ?> cmd) {
|
||||
if (gitCredentialsProvider != null) {
|
||||
cmd.setCredentialsProvider(gitCredentialsProvider);
|
||||
} else if (hasText(getUsername())) {
|
||||
cmd.setCredentialsProvider(
|
||||
new UsernamePasswordCredentialsProvider(getUsername(), getPassword()));
|
||||
} else if (hasText(getPassphrase())) {
|
||||
cmd.setCredentialsProvider(
|
||||
new PassphraseCredentialsProvider(getPassphrase()));
|
||||
private void configureCommand(TransportCommand<?, ?> command) {
|
||||
command.setTimeout(this.timeout);
|
||||
if (this.transportConfigCallback != null) {
|
||||
command.setTransportConfigCallback(this.transportConfigCallback);
|
||||
}
|
||||
CredentialsProvider credentialsProvider = getCredentialsProvider();
|
||||
if (credentialsProvider != null) {
|
||||
command.setCredentialsProvider(credentialsProvider);
|
||||
}
|
||||
}
|
||||
|
||||
private void setTimeout(TransportCommand<?, ?> pull) {
|
||||
pull.setTimeout(this.timeout);
|
||||
private CredentialsProvider getCredentialsProvider() {
|
||||
if (this.gitCredentialsProvider != null) {
|
||||
return this.gitCredentialsProvider;
|
||||
}
|
||||
|
||||
if (hasText(getUsername()) && hasText(getPassword())) {
|
||||
return new UsernamePasswordCredentialsProvider(getUsername(), getPassword());
|
||||
}
|
||||
|
||||
if (hasText(getPassphrase())) {
|
||||
return new PassphraseCredentialsProvider(getPassphrase());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isClean(Git git) {
|
||||
StatusCommand status = git.status();
|
||||
try {
|
||||
return status.call().isClean();
|
||||
}
|
||||
catch (Exception e) {
|
||||
} catch (Exception e) {
|
||||
String message = "Could not execute status command on local repository. Cause: ("
|
||||
+ e.getClass().getSimpleName() + ") " + e.getMessage();
|
||||
warn(message, e);
|
||||
@@ -460,8 +474,7 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
}
|
||||
|
||||
private void trackBranch(Git git, CheckoutCommand checkout, String label) {
|
||||
checkout.setCreateBranch(true).setName(label)
|
||||
.setUpstreamMode(SetupUpstreamMode.TRACK)
|
||||
checkout.setCreateBranch(true).setName(label).setUpstreamMode(SetupUpstreamMode.TRACK)
|
||||
.setStartPoint("origin/" + label);
|
||||
}
|
||||
|
||||
@@ -473,8 +486,7 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
return containsBranch(git, label, null);
|
||||
}
|
||||
|
||||
private boolean containsBranch(Git git, String label, ListMode listMode)
|
||||
throws GitAPIException {
|
||||
private boolean containsBranch(Git git, String label, ListMode listMode) throws GitAPIException {
|
||||
ListBranchCommand command = git.branchList();
|
||||
if (listMode != null) {
|
||||
command.setListMode(listMode);
|
||||
@@ -497,7 +509,8 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
|
||||
/**
|
||||
* Wraps the static method calls to {@link org.eclipse.jgit.api.Git} and
|
||||
* {@link org.eclipse.jgit.api.CloneCommand} allowing for easier unit testing.
|
||||
* {@link org.eclipse.jgit.api.CloneCommand} allowing for easier unit
|
||||
* testing.
|
||||
*/
|
||||
static class JGitFactory {
|
||||
|
||||
@@ -520,7 +533,8 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
}
|
||||
|
||||
/**
|
||||
* @param gitCredentialsProvider the gitCredentialsProvider to set
|
||||
* @param gitCredentialsProvider
|
||||
* the gitCredentialsProvider to set
|
||||
*/
|
||||
public void setGitCredentialsProvider(CredentialsProvider gitCredentialsProvider) {
|
||||
this.gitCredentialsProvider = gitCredentialsProvider;
|
||||
|
||||
@@ -63,7 +63,7 @@ public class MultipleJGitEnvironmentRepository extends JGitEnvironmentRepository
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
GitCredentialsProviderFactory credentialFactory = new GitCredentialsProviderFactory();
|
||||
super.setGitCredentialsProvider(credentialFactory.createFor(getUri(),
|
||||
super.setGitCredentialsProvider(credentialFactory.createFor(getUri(),
|
||||
getUsername(), getPassword(), getPassphrase()));
|
||||
super.afterPropertiesSet();
|
||||
for (String name : this.repos.keySet()) {
|
||||
@@ -75,6 +75,9 @@ public class MultipleJGitEnvironmentRepository extends JGitEnvironmentRepository
|
||||
if (repo.getPattern() == null || repo.getPattern().length == 0) {
|
||||
repo.setPattern(new String[] { name });
|
||||
}
|
||||
if (repo.getTransportConfigCallback() == null) {
|
||||
repo.setTransportConfigCallback(getTransportConfigCallback());
|
||||
}
|
||||
if (getTimeout() != 0 && repo.getTimeout() == 0) {
|
||||
repo.setTimeout(getTimeout());
|
||||
}
|
||||
@@ -88,10 +91,20 @@ public class MultipleJGitEnvironmentRepository extends JGitEnvironmentRepository
|
||||
if (passphrase == null) {
|
||||
passphrase = getPassphrase();
|
||||
}
|
||||
repo.setGitCredentialsProvider(credentialFactory.createFor(repo.getUri(),
|
||||
user, pass, passphrase));
|
||||
repo.setGitCredentialsProvider(
|
||||
credentialFactory.createFor(repo.getUri(), user, pass, passphrase));
|
||||
repo.afterPropertiesSet();
|
||||
}
|
||||
if (!getBasedir().exists() &&
|
||||
!getBasedir().mkdirs()) {
|
||||
throw new IllegalStateException(
|
||||
"Basedir does not exist and can not be created: " + getBasedir());
|
||||
}
|
||||
if (!getBasedir().getParentFile().canWrite()) {
|
||||
throw new IllegalStateException(
|
||||
"Cannot write parent of basedir (please configure a writable location): "
|
||||
+ getBasedir());
|
||||
}
|
||||
}
|
||||
|
||||
public void setRepos(Map<String, PatternMatchingJGitEnvironmentRepository> repos) {
|
||||
@@ -119,7 +132,8 @@ public class MultipleJGitEnvironmentRepository extends JGitEnvironmentRepository
|
||||
if (logger.isDebugEnabled()) {
|
||||
this.logger.debug("Cannot retrieve resource locations from "
|
||||
+ candidate.getUri() + ", cause: ("
|
||||
+ e.getClass().getSimpleName() + ") " + e.getMessage(), e);
|
||||
+ e.getClass().getSimpleName() + ") "
|
||||
+ e.getMessage(), e);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -141,7 +155,7 @@ public class MultipleJGitEnvironmentRepository extends JGitEnvironmentRepository
|
||||
for (JGitEnvironmentRepository candidate : getRepositories(repository,
|
||||
application, profile, label)) {
|
||||
try {
|
||||
if (label==null) {
|
||||
if (label == null) {
|
||||
label = candidate.getDefaultLabel();
|
||||
}
|
||||
Environment source = candidate.findOne(application, profile,
|
||||
@@ -152,9 +166,11 @@ public class MultipleJGitEnvironmentRepository extends JGitEnvironmentRepository
|
||||
}
|
||||
catch (Exception e) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
this.logger.debug("Cannot load configuration from "
|
||||
+ candidate.getUri() + ", cause: ("
|
||||
+ e.getClass().getSimpleName() + ") " + e.getMessage(), e);
|
||||
this.logger.debug(
|
||||
"Cannot load configuration from " + candidate.getUri()
|
||||
+ ", cause: (" + e.getClass().getSimpleName()
|
||||
+ ") " + e.getMessage(),
|
||||
e);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -163,7 +179,7 @@ public class MultipleJGitEnvironmentRepository extends JGitEnvironmentRepository
|
||||
}
|
||||
JGitEnvironmentRepository candidate = getRepository(this, application, profile,
|
||||
label);
|
||||
if (label==null) {
|
||||
if (label == null) {
|
||||
label = candidate.getDefaultLabel();
|
||||
}
|
||||
if (candidate == this) {
|
||||
@@ -191,7 +207,8 @@ public class MultipleJGitEnvironmentRepository extends JGitEnvironmentRepository
|
||||
}
|
||||
String key = repository.getUri();
|
||||
|
||||
// cover the case where label is in the uri, but no label was sent with the request
|
||||
// cover the case where label is in the uri, but no label was sent with the
|
||||
// request
|
||||
if (key.contains("{label}") && label == null) {
|
||||
label = repository.getDefaultLabel();
|
||||
}
|
||||
@@ -216,7 +233,8 @@ public class MultipleJGitEnvironmentRepository extends JGitEnvironmentRepository
|
||||
File basedir = repository.getBasedir();
|
||||
BeanUtils.copyProperties(source, repository);
|
||||
repository.setUri(uri);
|
||||
repository.setBasedir(basedir);
|
||||
repository.setBasedir(
|
||||
new File(source.getBasedir().getParentFile(), basedir.getName()));
|
||||
return repository;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2015 the original author or authors.
|
||||
* Copyright 2013-2017 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.
|
||||
@@ -19,12 +19,13 @@ package org.springframework.cloud.config.server.environment;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.boot.Banner.Mode;
|
||||
import org.springframework.boot.WebApplicationType;
|
||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
||||
@@ -48,6 +49,7 @@ import org.springframework.util.StringUtils;
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Roy Clarkson
|
||||
* @author Venil Noronha
|
||||
*/
|
||||
@ConfigurationProperties("spring.cloud.config.server.native")
|
||||
public class NativeEnvironmentRepository implements EnvironmentRepository, SearchPathLocator, Ordered {
|
||||
@@ -67,6 +69,11 @@ public class NativeEnvironmentRepository implements EnvironmentRepository, Searc
|
||||
*/
|
||||
private boolean failOnError = false;
|
||||
|
||||
/**
|
||||
* Flag to determine whether label locations should be added.
|
||||
*/
|
||||
private boolean addLabelLocations = true;
|
||||
|
||||
/**
|
||||
* Version string to be reported for native repository
|
||||
*/
|
||||
@@ -91,6 +98,14 @@ public class NativeEnvironmentRepository implements EnvironmentRepository, Searc
|
||||
return this.failOnError;
|
||||
}
|
||||
|
||||
public void setAddLabelLocations(boolean addLabelLocations) {
|
||||
this.addLabelLocations = addLabelLocations;
|
||||
}
|
||||
|
||||
public boolean isAddLabelLocations() {
|
||||
return this.addLabelLocations;
|
||||
}
|
||||
|
||||
public String getDefaultLabel() {
|
||||
return DEFAULT_LABEL;
|
||||
}
|
||||
@@ -128,7 +143,7 @@ public class NativeEnvironmentRepository implements EnvironmentRepository, Searc
|
||||
if (this.searchLocations == null || this.searchLocations.length == 0) {
|
||||
locations = DEFAULT_LOCATIONS;
|
||||
}
|
||||
List<String> output = new ArrayList<String>();
|
||||
Collection<String> output = new LinkedHashSet<String>();
|
||||
for (String location : locations) {
|
||||
String[] profiles = new String[] { profile };
|
||||
if (profile != null) {
|
||||
@@ -159,11 +174,13 @@ public class NativeEnvironmentRepository implements EnvironmentRepository, Searc
|
||||
}
|
||||
}
|
||||
}
|
||||
for (String location : locations) {
|
||||
if (StringUtils.hasText(label)) {
|
||||
String labelled = location + label.trim() + "/";
|
||||
if (isDirectory(labelled)) {
|
||||
output.add(labelled);
|
||||
if (this.addLabelLocations) {
|
||||
for (String location : locations) {
|
||||
if (StringUtils.hasText(label)) {
|
||||
String labelled = location + label.trim() + "/";
|
||||
if (isDirectory(labelled)) {
|
||||
output.add(labelled);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 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;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class NoSuchRepositoryException extends RepositoryException {
|
||||
|
||||
public NoSuchRepositoryException(String string) {
|
||||
super(string);
|
||||
}
|
||||
|
||||
public NoSuchRepositoryException(String string, Exception e) {
|
||||
super(string, e);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,6 +19,7 @@ package org.springframework.cloud.config.server.support;
|
||||
import static org.springframework.util.StringUtils.hasText;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.text.SimpleDateFormat;
|
||||
@@ -326,7 +327,8 @@ public class AwsCodeCommitCredentialProvider extends CredentialsProvider {
|
||||
}
|
||||
|
||||
try {
|
||||
URI u = new URI(uri.toLowerCase());
|
||||
URL url = new URL(uri);
|
||||
URI u = new URI(url.getProtocol(), url.getUserInfo(), url.getHost(), url.getPort(), url.getPath(), url.getQuery(), url.getRef());
|
||||
if (u.getScheme().equals("https")) {
|
||||
String host = u.getHost();
|
||||
if (host.endsWith(".amazonaws.com") && host.startsWith("git-codecommit.")) {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
# Bootstrap components
|
||||
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
|
||||
org.springframework.cloud.config.server.bootstrap.ConfigServerBootstrapConfiguration
|
||||
org.springframework.cloud.config.server.bootstrap.ConfigServerBootstrapConfiguration,\
|
||||
org.springframework.cloud.config.server.config.EncryptionAutoConfiguration,\
|
||||
org.springframework.cloud.config.server.config.SingleEncryptorAutoConfiguration
|
||||
|
||||
# Application listeners
|
||||
org.springframework.context.ApplicationListener=\
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package org.springframework.cloud.config.server;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Suite;
|
||||
import org.junit.runners.Suite.SuiteClasses;
|
||||
import org.springframework.cloud.config.server.environment.EnvironmentEncryptorEnvironmentRepositoryTests;
|
||||
import org.springframework.cloud.config.server.environment.JGitEnvironmentRepositoryIntegrationTests;
|
||||
import org.springframework.cloud.config.server.environment.MultipleJGitEnvironmentRepositoryIntegrationTests;
|
||||
import org.springframework.cloud.config.server.environment.NativeEnvironmentRepositoryTests;
|
||||
import org.springframework.cloud.config.server.environment.SVNKitEnvironmentRepositoryIntegrationTests;
|
||||
|
||||
/**
|
||||
* A test suite for probing weird ordering problems in the tests.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@RunWith(Suite.class)
|
||||
@SuiteClasses({ MultipleJGitEnvironmentRepositoryIntegrationTests.class,
|
||||
JGitEnvironmentRepositoryIntegrationTests.class, EnvironmentEncryptorEnvironmentRepositoryTests.class,
|
||||
NativeEnvironmentRepositoryTests.class, SVNKitEnvironmentRepositoryIntegrationTests.class })
|
||||
@Ignore
|
||||
public class AdhocTestSuite {
|
||||
|
||||
}
|
||||
@@ -20,7 +20,7 @@ import static org.junit.Assert.assertFalse;
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = ConfigServerApplication.class, properties = "spring.cloud.bootstrap.name:enable-bootstrap",
|
||||
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
@ActiveProfiles("test")
|
||||
@ActiveProfiles({"test", "encrypt"})
|
||||
public class BootstrapConfigServerIntegrationTests {
|
||||
|
||||
@LocalServerPort
|
||||
@@ -29,9 +29,12 @@ public class BootstrapConfigServerIntegrationTests {
|
||||
@Value("${info.foo}")
|
||||
private String foo;
|
||||
|
||||
@Value("${config.foo}")
|
||||
private String config;
|
||||
|
||||
@BeforeClass
|
||||
public static void init() throws IOException {
|
||||
ConfigServerTestUtils.prepareLocalRepo();
|
||||
ConfigServerTestUtils.prepareLocalRepo("encrypt-repo");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -46,6 +49,7 @@ public class BootstrapConfigServerIntegrationTests {
|
||||
@Test
|
||||
public void environmentBootstraps() throws Exception {
|
||||
assertEquals("bar", foo);
|
||||
assertEquals("foo", config);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ public class AwsCodeCommitCredentialsProviderTests {
|
||||
private static final String USER = "test";
|
||||
private static final String AWS_REPO = "https://git-codecommit.us-east-1.amazonaws.com/v1/repos/test";
|
||||
private static final String BAD_REPO = "https://amazonaws.com/v1/repos/test";
|
||||
private static final String CURLY_BRACES_REPO = "https://git-codecommit.us-east-1.amazonaws.com/v1/repos/{application}";
|
||||
|
||||
private AwsCodeCommitCredentialProvider provider;
|
||||
|
||||
@@ -111,6 +112,15 @@ public class AwsCodeCommitCredentialsProviderTests {
|
||||
assertFalse(provider.get(new URIish(BAD_REPO), credentialItems));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUriWithCurlyBracesReturnsTrue() throws UnsupportedCredentialItem, URISyntaxException {
|
||||
GitCredentialsProviderFactory factory = new GitCredentialsProviderFactory();
|
||||
provider = (AwsCodeCommitCredentialProvider)
|
||||
factory.createFor(CURLY_BRACES_REPO, USER, PASSWORD, null);
|
||||
CredentialItem[] credentialItems = makeCredentialItems();
|
||||
assertTrue(provider.get(new URIish(CURLY_BRACES_REPO), credentialItems));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThrowsUnsupportedCredentialException() throws URISyntaxException {
|
||||
CredentialItem[] goodCredentialItems = makeCredentialItems();
|
||||
|
||||
@@ -110,4 +110,38 @@ public class CompositeEnvironmentRepositoryTests {
|
||||
assertEquals(sLoc4, locationStrings[3]);
|
||||
assertEquals(sLoc1, locationStrings[4]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVersion() {
|
||||
PropertySource p1 = mock(PropertySource.class);
|
||||
doReturn("p1").when(p1).getName();
|
||||
PropertySource p2 = mock(PropertySource.class);
|
||||
doReturn("p2").when(p2).getName();
|
||||
String sLoc1 = "loc1";
|
||||
String sLoc2 = "loc2";
|
||||
Environment e1 = new Environment("app", "dev");
|
||||
e1.add(p1);
|
||||
e1.setVersion("1");
|
||||
e1.setState("state");
|
||||
Environment e2 = new Environment("app", "dev");
|
||||
e2.add(p2);
|
||||
e2.setVersion("2");
|
||||
e2.setState("state2");
|
||||
SearchPathLocator.Locations loc1 = new SearchPathLocator.Locations("app", "dev", "label", "version", new String[]{sLoc1});
|
||||
SearchPathLocator.Locations loc2 = new SearchPathLocator.Locations("app", "dev", "label", "version", new String[]{sLoc1, sLoc2});
|
||||
List<EnvironmentRepository> repos = new ArrayList<EnvironmentRepository>();
|
||||
repos.add(new TestOrderedEnvironmentRepository(3, e1, loc1));
|
||||
List<EnvironmentRepository> repos2 = new ArrayList<EnvironmentRepository>();
|
||||
repos2.add(new TestOrderedEnvironmentRepository(3, e1, loc1));
|
||||
repos2.add(new TestOrderedEnvironmentRepository(3, e2, loc2));
|
||||
SearchPathCompositeEnvironmentRepository compositeRepo = new SearchPathCompositeEnvironmentRepository(repos);
|
||||
SearchPathCompositeEnvironmentRepository multiCompositeRepo = new SearchPathCompositeEnvironmentRepository(repos2);
|
||||
Environment env = compositeRepo.findOne("app", "dev", "label");
|
||||
assertEquals("1", env.getVersion());
|
||||
assertEquals("state", env.getState());
|
||||
Environment multiEnv = multiCompositeRepo.findOne("app", "dev", "label");
|
||||
assertEquals(null, multiEnv.getVersion());
|
||||
assertEquals(null, multiEnv.getState());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,71 +61,83 @@ public class EnvironmentControllerIntegrationTests {
|
||||
|
||||
@Test
|
||||
public void environmentNoLabel() throws Exception {
|
||||
Mockito.when(this.repository.findOne("foo", "default", null)).thenReturn(
|
||||
new Environment("foo", "default"));
|
||||
this.mvc.perform(MockMvcRequestBuilders.get("/foo/default")).andExpect(
|
||||
MockMvcResultMatchers.status().isOk());
|
||||
Mockito.when(this.repository.findOne("foo", "default", null)).thenReturn(new Environment("foo", "default"));
|
||||
this.mvc.perform(MockMvcRequestBuilders.get("/foo/default")).andExpect(MockMvcResultMatchers.status().isOk());
|
||||
Mockito.verify(this.repository).findOne("foo", "default", null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void propertiesNoLabel() throws Exception {
|
||||
Mockito.when(this.repository.findOne("foo", "default", null)).thenReturn(
|
||||
new Environment("foo", "default"));
|
||||
this.mvc.perform(MockMvcRequestBuilders.get("/foo-default.properties")).andExpect(
|
||||
MockMvcResultMatchers.status().isOk());
|
||||
Mockito.when(this.repository.findOne("foo", "default", null)).thenReturn(new Environment("foo", "default"));
|
||||
this.mvc.perform(MockMvcRequestBuilders.get("/foo-default.properties"))
|
||||
.andExpect(MockMvcResultMatchers.status().isOk());
|
||||
Mockito.verify(this.repository).findOne("foo", "default", null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void propertiesLabel() throws Exception {
|
||||
Mockito.when(this.repository.findOne("foo", "default", "label")).thenReturn(
|
||||
new Environment("foo", "default"));
|
||||
this.mvc.perform(MockMvcRequestBuilders.get("/label/foo-default.properties")).andExpect(
|
||||
MockMvcResultMatchers.status().isOk());
|
||||
Mockito.when(this.repository.findOne("foo", "default", "label")).thenReturn(new Environment("foo", "default"));
|
||||
this.mvc.perform(MockMvcRequestBuilders.get("/label/foo-default.properties"))
|
||||
.andExpect(MockMvcResultMatchers.status().isOk());
|
||||
Mockito.verify(this.repository).findOne("foo", "default", "label");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void propertiesLabelWhenApplicationNameContainsHyphen() throws Exception {
|
||||
Mockito.when(this.repository.findOne("foo-bar", "default", "label")).thenReturn(new Environment("foo-bar", "default"));
|
||||
this.mvc.perform(MockMvcRequestBuilders.get("/label/foo-bar-default.properties")).andExpect(
|
||||
MockMvcResultMatchers.status().isOk());
|
||||
Mockito.when(this.repository.findOne("foo-bar", "default", "label"))
|
||||
.thenReturn(new Environment("foo-bar", "default"));
|
||||
this.mvc.perform(MockMvcRequestBuilders.get("/label/foo-bar-default.properties"))
|
||||
.andExpect(MockMvcResultMatchers.status().isOk());
|
||||
Mockito.verify(this.repository).findOne("foo-bar", "default", "label");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void propertiesLabelWithSlash() throws Exception {
|
||||
Mockito.when(this.repository.findOne("foo", "default", "label/spam")).thenReturn(
|
||||
new Environment("foo", "default"));
|
||||
this.mvc.perform(MockMvcRequestBuilders.get("/label(_)spam/foo-default.properties")).andExpect(
|
||||
MockMvcResultMatchers.status().isOk());
|
||||
Mockito.when(this.repository.findOne("foo", "default", "label/spam"))
|
||||
.thenReturn(new Environment("foo", "default"));
|
||||
this.mvc.perform(MockMvcRequestBuilders.get("/label(_)spam/foo-default.properties"))
|
||||
.andExpect(MockMvcResultMatchers.status().isOk());
|
||||
Mockito.verify(this.repository).findOne("foo", "default", "label/spam");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void environmentWithLabel() throws Exception {
|
||||
Mockito.when(this.repository.findOne("foo", "default", "awesome")).thenReturn(
|
||||
new Environment("foo", "default"));
|
||||
this.mvc.perform(MockMvcRequestBuilders.get("/foo/default/awesome")).andExpect(
|
||||
MockMvcResultMatchers.status().isOk());
|
||||
Mockito.when(this.repository.findOne("foo", "default", "awesome"))
|
||||
.thenReturn(new Environment("foo", "default"));
|
||||
this.mvc.perform(MockMvcRequestBuilders.get("/foo/default/awesome"))
|
||||
.andExpect(MockMvcResultMatchers.status().isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void environmentWithMissingLabel() throws Exception {
|
||||
Mockito.when(this.repository.findOne("foo", "default", "missing"))
|
||||
.thenThrow(new NoSuchLabelException("Planned"));
|
||||
this.mvc.perform(MockMvcRequestBuilders.get("/foo/default/missing"))
|
||||
.andExpect(MockMvcResultMatchers.status().isNotFound());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void environmentWithMissingRepo() throws Exception {
|
||||
Mockito.when(this.repository.findOne("foo", "default", "missing"))
|
||||
.thenThrow(new NoSuchRepositoryException("Planned"));
|
||||
this.mvc.perform(MockMvcRequestBuilders.get("/foo/default/missing"))
|
||||
.andExpect(MockMvcResultMatchers.status().isNotFound());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void environmentWithLabelContainingPeriod() throws Exception {
|
||||
Mockito.when(this.repository.findOne("foo", "default", "1.0.0")).thenReturn(
|
||||
new Environment("foo", "default"));
|
||||
this.mvc.perform(MockMvcRequestBuilders.get("/foo/default/1.0.0")).andExpect(
|
||||
MockMvcResultMatchers.status().isOk());
|
||||
Mockito.when(this.repository.findOne("foo", "default", "1.0.0")).thenReturn(new Environment("foo", "default"));
|
||||
this.mvc.perform(MockMvcRequestBuilders.get("/foo/default/1.0.0"))
|
||||
.andExpect(MockMvcResultMatchers.status().isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void environmentWithLabelContainingSlash() throws Exception {
|
||||
Mockito.when(this.repository.findOne("foo", "default", "feature/puff"))
|
||||
.thenReturn(new Environment("foo", "default"));
|
||||
.thenReturn(new Environment("foo", "default"));
|
||||
this.mvc.perform(MockMvcRequestBuilders.get("/foo/default/feature(_)puff"))
|
||||
.andExpect(MockMvcResultMatchers.status().isOk())
|
||||
.andExpect(MockMvcResultMatchers.content().string(Matchers.containsString("\"propertySources\":")));
|
||||
.andExpect(MockMvcResultMatchers.status().isOk())
|
||||
.andExpect(MockMvcResultMatchers.content().string(Matchers.containsString("\"propertySources\":")));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
||||
@@ -16,6 +16,14 @@
|
||||
|
||||
package org.springframework.cloud.config.server.environment;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
@@ -30,6 +38,7 @@ import java.util.Arrays;
|
||||
import org.eclipse.jgit.api.CheckoutCommand;
|
||||
import org.eclipse.jgit.api.Git;
|
||||
import org.eclipse.jgit.api.ResetCommand.ResetType;
|
||||
import org.eclipse.jgit.api.TransportConfigCallback;
|
||||
import org.eclipse.jgit.api.errors.GitAPIException;
|
||||
import org.eclipse.jgit.lib.Ref;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
@@ -39,7 +48,7 @@ import org.hamcrest.Matchers;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.boot.WebApplicationType;
|
||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
@@ -49,18 +58,12 @@ import org.springframework.cloud.config.server.config.ConfigServerProperties;
|
||||
import org.springframework.cloud.config.server.config.EnvironmentRepositoryConfiguration;
|
||||
import org.springframework.cloud.config.server.test.ConfigServerTestUtils;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.util.ResourceUtils;
|
||||
import org.springframework.util.StreamUtils;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* @author Roy Clarkson
|
||||
@@ -93,8 +96,7 @@ public class JGitEnvironmentRepositoryIntegrationTests {
|
||||
String uri = ConfigServerTestUtils.prepareLocalRepo();
|
||||
this.context = new SpringApplicationBuilder(TestConfiguration.class).web(WebApplicationType.NONE)
|
||||
.properties("spring.cloud.config.server.git.uri:" + uri).run();
|
||||
EnvironmentRepository repository = this.context
|
||||
.getBean(EnvironmentRepository.class);
|
||||
EnvironmentRepository repository = this.context.getBean(EnvironmentRepository.class);
|
||||
repository.findOne("bar", "staging", "master");
|
||||
Environment environment = repository.findOne("bar", "staging", "master");
|
||||
assertEquals(2, environment.getPropertySources().size());
|
||||
@@ -109,12 +111,10 @@ public class JGitEnvironmentRepositoryIntegrationTests {
|
||||
String uri = ConfigServerTestUtils.copyLocalRepo("config-copy");
|
||||
this.context = new SpringApplicationBuilder(TestConfiguration.class).web(WebApplicationType.NONE)
|
||||
.run("--spring.cloud.config.server.git.uri=" + uri);
|
||||
EnvironmentRepository repository = this.context
|
||||
.getBean(EnvironmentRepository.class);
|
||||
EnvironmentRepository repository = this.context.getBean(EnvironmentRepository.class);
|
||||
repository.findOne("bar", "staging", "master");
|
||||
Environment environment = repository.findOne("bar", "staging", "master");
|
||||
assertEquals("bar",
|
||||
environment.getPropertySources().get(0).getSource().get("foo"));
|
||||
assertEquals("bar", environment.getPropertySources().get(0).getSource().get("foo"));
|
||||
Git git = Git.open(ResourceUtils.getFile(uri).getAbsoluteFile());
|
||||
git.checkout().setName("master").call();
|
||||
StreamUtils.copy("foo: foo", Charset.defaultCharset(),
|
||||
@@ -122,15 +122,14 @@ public class JGitEnvironmentRepositoryIntegrationTests {
|
||||
git.add().addFilepattern("bar.properties").call();
|
||||
git.commit().setMessage("Updated for pull").call();
|
||||
environment = repository.findOne("bar", "staging", "master");
|
||||
assertEquals("foo",
|
||||
environment.getPropertySources().get(0).getSource().get("foo"));
|
||||
assertEquals("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.
|
||||
* 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 {
|
||||
@@ -142,23 +141,19 @@ public class JGitEnvironmentRepositoryIntegrationTests {
|
||||
|
||||
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.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();
|
||||
String commitToRevertBeforePull = git.log().setMaxCount(1).call().iterator().next().getName();
|
||||
|
||||
this.context = new SpringApplicationBuilder(TestConfiguration.class).web(WebApplicationType.NONE)
|
||||
.run("--spring.cloud.config.server.git.uri=" + uri);
|
||||
|
||||
JGitEnvironmentRepository repository = this.context
|
||||
.getBean(JGitEnvironmentRepository.class);
|
||||
JGitEnvironmentRepository repository = this.context.getBean(JGitEnvironmentRepository.class);
|
||||
|
||||
// Fetches the repository for the first time.
|
||||
SearchPathLocator.Locations locations = repository.getLocations("bar", "test", "raw");
|
||||
@@ -168,17 +163,14 @@ public class JGitEnvironmentRepositoryIntegrationTests {
|
||||
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");
|
||||
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);
|
||||
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();
|
||||
String conflictingCommit = git.log().setMaxCount(1).call().iterator()
|
||||
.next().getName();
|
||||
String conflictingCommit = git.log().setMaxCount(1).call().iterator().next().getName();
|
||||
|
||||
// Reset to the raw branch.
|
||||
git.reset().setMode(ResetType.HARD).setRef(commitToRevertBeforePull).call();
|
||||
@@ -187,8 +179,17 @@ public class JGitEnvironmentRepositoryIntegrationTests {
|
||||
locations = repository.getLocations("bar", "test", "raw");
|
||||
assertEquals(locations.getVersion(), conflictingCommit);
|
||||
|
||||
assertTrue("Local repository is not cleaned after retrieving resources.",
|
||||
git.status().call().isClean());
|
||||
assertTrue("Local repository is not cleaned after retrieving resources.", git.status().call().isClean());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pullMissingRepo() throws Exception {
|
||||
pull();
|
||||
JGitEnvironmentRepository repository = this.context.getBean(JGitEnvironmentRepository.class);
|
||||
new File(repository.getUri().replaceAll("file:", ""), ".git/index.lock").createNewFile();
|
||||
repository.findOne("bar", "staging", "master");
|
||||
Environment environment = repository.findOne("bar", "staging", "master");
|
||||
assertEquals("foo", environment.getPropertySources().get(0).getSource().get("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -196,10 +197,8 @@ public class JGitEnvironmentRepositoryIntegrationTests {
|
||||
String uri = ConfigServerTestUtils.prepareLocalRepo("another-config-repo");
|
||||
this.context = new SpringApplicationBuilder(TestConfiguration.class).web(WebApplicationType.NONE)
|
||||
// TODO: why didn't .properties() work for me?
|
||||
.run("--spring.cloud.config.server.git.uri=" + uri,
|
||||
"--spring.cloud.config.server.git.searchPaths=sub");
|
||||
EnvironmentRepository repository = this.context
|
||||
.getBean(EnvironmentRepository.class);
|
||||
.run("--spring.cloud.config.server.git.uri=" + uri, "--spring.cloud.config.server.git.searchPaths=sub");
|
||||
EnvironmentRepository repository = this.context.getBean(EnvironmentRepository.class);
|
||||
repository.findOne("bar", "staging", "master");
|
||||
Environment environment = repository.findOne("bar", "staging", "master");
|
||||
assertEquals(2, environment.getPropertySources().size());
|
||||
@@ -212,8 +211,7 @@ public class JGitEnvironmentRepositoryIntegrationTests {
|
||||
// TODO: why didn't .properties() work for me?
|
||||
.run("--spring.cloud.config.server.git.uri=" + uri,
|
||||
"--spring.cloud.config.server.git.searchPaths={application}");
|
||||
EnvironmentRepository repository = this.context
|
||||
.getBean(EnvironmentRepository.class);
|
||||
EnvironmentRepository repository = this.context.getBean(EnvironmentRepository.class);
|
||||
repository.findOne("foo,bar", "staging", "master");
|
||||
Environment environment = repository.findOne("foo,bar", "staging", "master");
|
||||
assertEquals(3, environment.getPropertySources().size());
|
||||
@@ -226,8 +224,7 @@ public class JGitEnvironmentRepositoryIntegrationTests {
|
||||
// TODO: why didn't .properties() work for me?
|
||||
.run("--spring.cloud.config.server.git.uri=" + uri,
|
||||
"--spring.cloud.config.server.git.searchPaths={profile}");
|
||||
EnvironmentRepository repository = this.context
|
||||
.getBean(EnvironmentRepository.class);
|
||||
EnvironmentRepository repository = this.context.getBean(EnvironmentRepository.class);
|
||||
repository.findOne("foo,bar", "staging", "master");
|
||||
Environment environment = repository.findOne("staging", "foo,bar", "master");
|
||||
assertEquals(3, environment.getPropertySources().size());
|
||||
@@ -243,8 +240,7 @@ public class JGitEnvironmentRepositoryIntegrationTests {
|
||||
.getBean(JGitEnvironmentRepository.class);
|
||||
assertThat(repository.getSearchPaths(), Matchers.arrayContaining("{application}"));
|
||||
assertFalse(Arrays.equals(repository.getSearchPaths(),
|
||||
new JGitEnvironmentRepository(repository.getEnvironment())
|
||||
.getSearchPaths()));
|
||||
new JGitEnvironmentRepository(repository.getEnvironment()).getSearchPaths()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -252,8 +248,7 @@ public class JGitEnvironmentRepositoryIntegrationTests {
|
||||
String uri = ConfigServerTestUtils.prepareLocalRepo();
|
||||
this.context = new SpringApplicationBuilder(TestConfiguration.class).web(WebApplicationType.NONE)
|
||||
.properties("spring.cloud.config.server.git.uri:" + uri).run();
|
||||
JGitEnvironmentRepository repository = this.context
|
||||
.getBean(JGitEnvironmentRepository.class);
|
||||
JGitEnvironmentRepository repository = this.context.getBean(JGitEnvironmentRepository.class);
|
||||
assertEquals("master", repository.getDefaultLabel());
|
||||
}
|
||||
|
||||
@@ -262,8 +257,7 @@ public class JGitEnvironmentRepositoryIntegrationTests {
|
||||
String uri = ConfigServerTestUtils.prepareLocalRepo();
|
||||
this.context = new SpringApplicationBuilder(TestConfiguration.class).web(WebApplicationType.NONE)
|
||||
.properties("spring.cloud.config.server.git.uri:" + uri).run();
|
||||
EnvironmentRepository repository = this.context
|
||||
.getBean(EnvironmentRepository.class);
|
||||
EnvironmentRepository repository = this.context.getBean(EnvironmentRepository.class);
|
||||
repository.findOne("bar", "staging", "unknownlabel");
|
||||
}
|
||||
|
||||
@@ -295,8 +289,7 @@ public class JGitEnvironmentRepositoryIntegrationTests {
|
||||
.getBean(EnvironmentRepository.class);
|
||||
repository.findOne("bar", "staging", "master");
|
||||
Environment environment = repository.findOne("bar", "staging", "master");
|
||||
assertEquals("bar",
|
||||
environment.getPropertySources().get(0).getSource().get("foo"));
|
||||
assertEquals("bar", environment.getPropertySources().get(0).getSource().get("foo"));
|
||||
Git git = Git.open(ResourceUtils.getFile(uri).getAbsoluteFile());
|
||||
git.checkout().setName("master").call();
|
||||
StreamUtils.copy("foo: foo", Charset.defaultCharset(),
|
||||
@@ -304,8 +297,7 @@ public class JGitEnvironmentRepositoryIntegrationTests {
|
||||
git.add().addFilepattern("bar.properties").call();
|
||||
git.commit().setMessage("Updated for pull").call();
|
||||
environment = repository.findOne("bar", "staging", "master");
|
||||
assertEquals("foo",
|
||||
environment.getPropertySources().get(0).getSource().get("foo"));
|
||||
assertEquals("foo", environment.getPropertySources().get(0).getSource().get("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -313,83 +305,80 @@ public class JGitEnvironmentRepositoryIntegrationTests {
|
||||
String uri = ConfigServerTestUtils.prepareLocalRepo("another-config-repo");
|
||||
this.context = new SpringApplicationBuilder(TestConfiguration.class).web(WebApplicationType.NONE)
|
||||
// TODO: why didn't .properties() work for me?
|
||||
.run("--spring.cloud.config.server.git.uri=" + uri,
|
||||
"--spring.cloud.config.server.git.searchPaths=sub",
|
||||
.run("--spring.cloud.config.server.git.uri=" + uri, "--spring.cloud.config.server.git.searchPaths=sub",
|
||||
"--spring.cloud.config.server.git.cloneOnStart=true");
|
||||
EnvironmentRepository repository = this.context
|
||||
.getBean(EnvironmentRepository.class);
|
||||
EnvironmentRepository repository = this.context.getBean(EnvironmentRepository.class);
|
||||
repository.findOne("bar", "staging", "master");
|
||||
Environment environment = repository.findOne("bar", "staging", "master");
|
||||
assertEquals(2, environment.getPropertySources().size());
|
||||
}
|
||||
|
||||
@Test(expected = NoSuchLabelException.class)
|
||||
public void findOne_FindInvalidLabel_IllegalStateExceptionThrown()
|
||||
throws IOException {
|
||||
public void findOne_FindInvalidLabel_IllegalStateExceptionThrown() throws IOException {
|
||||
String uri = ConfigServerTestUtils.prepareLocalRepo();
|
||||
this.context = new SpringApplicationBuilder(TestConfiguration.class).web(WebApplicationType.NONE)
|
||||
.properties("spring.cloud.config.server.git.uri:" + uri,
|
||||
"--spring.cloud.config.server.git.cloneOnStart=true")
|
||||
.run();
|
||||
EnvironmentRepository repository = this.context
|
||||
.getBean(EnvironmentRepository.class);
|
||||
EnvironmentRepository repository = this.context.getBean(EnvironmentRepository.class);
|
||||
repository.findOne("bar", "staging", "unknownlabel");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVersionUpdate() throws Exception {
|
||||
JGitConfigServerTestData testData = JGitConfigServerTestData.prepareClonedGitRepository(TestConfiguration.class);
|
||||
JGitConfigServerTestData testData = JGitConfigServerTestData
|
||||
.prepareClonedGitRepository(TestConfiguration.class);
|
||||
|
||||
//get our starting versions
|
||||
// get our starting versions
|
||||
String startingLocalVersion = getCommitID(testData.getClonedGit().getGit(), "master");
|
||||
String startingRemoteVersion = getCommitID(testData.getServerGit().getGit(), "master");
|
||||
|
||||
//make sure we get the right version out of the gate
|
||||
// make sure we get the right version out of the gate
|
||||
Environment environment = testData.getRepository().findOne("bar", "staging", "master");
|
||||
|
||||
//make sure the environments version is the same as the remote repo version
|
||||
// make sure the environments version is the same as the remote repo
|
||||
// version
|
||||
assertEquals(environment.getVersion(), startingRemoteVersion);
|
||||
|
||||
//update the remote repo
|
||||
FileOutputStream out = new FileOutputStream(new File(testData.getServerGit().getGitWorkingDirectory(), "bar.properties"));
|
||||
// update the remote repo
|
||||
FileOutputStream out = new FileOutputStream(
|
||||
new File(testData.getServerGit().getGitWorkingDirectory(), "bar.properties"));
|
||||
StreamUtils.copy("foo: foo", Charset.defaultCharset(), out);
|
||||
testData.getServerGit().getGit().add().addFilepattern("bar.properties").call();
|
||||
testData.getServerGit().getGit().commit().setMessage("Updated for pull").call();
|
||||
|
||||
//pull the environment again which should update the local repo from the just updated remote repo
|
||||
// pull the environment again which should update the local repo from
|
||||
// the just updated remote repo
|
||||
environment = testData.getRepository().findOne("bar", "staging", "master");
|
||||
|
||||
//do some more check outs to get updated version numbers
|
||||
// do some more check outs to get updated version numbers
|
||||
String updatedLocalVersion = getCommitID(testData.getClonedGit().getGit(), "master");
|
||||
String updatedRemoteVersion = getCommitID(testData.getClonedGit().getGit(), "master");
|
||||
|
||||
//make sure our versions have been updated
|
||||
// make sure our versions have been updated
|
||||
assertEquals(updatedRemoteVersion, updatedLocalVersion);
|
||||
assertNotEquals(updatedRemoteVersion, startingRemoteVersion);
|
||||
assertNotEquals(updatedLocalVersion, startingLocalVersion);
|
||||
|
||||
//make sure our environment also reflects the updated version
|
||||
//this used to have a bug
|
||||
// make sure our environment also reflects the updated version
|
||||
// this used to have a bug
|
||||
assertEquals(environment.getVersion(), updatedRemoteVersion);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNewRemoteBranch() throws Exception {
|
||||
JGitConfigServerTestData testData = JGitConfigServerTestData.prepareClonedGitRepository(TestConfiguration.class);
|
||||
JGitConfigServerTestData testData = JGitConfigServerTestData
|
||||
.prepareClonedGitRepository(TestConfiguration.class);
|
||||
|
||||
Environment environment = testData.getRepository().findOne("bar", "staging", "master");
|
||||
Object fooProperty = ConfigServerTestUtils.getProperty(environment, "bar.properties", "foo");
|
||||
assertEquals(fooProperty, "bar");
|
||||
|
||||
testData.getServerGit().getGit().branchCreate()
|
||||
.setName("testNewRemoteBranch")
|
||||
.call();
|
||||
testData.getServerGit().getGit().branchCreate().setName("testNewRemoteBranch").call();
|
||||
|
||||
testData.getServerGit().getGit().checkout()
|
||||
.setName("testNewRemoteBranch")
|
||||
.call();
|
||||
testData.getServerGit().getGit().checkout().setName("testNewRemoteBranch").call();
|
||||
|
||||
//update the remote repo
|
||||
// update the remote repo
|
||||
FileOutputStream out = new FileOutputStream(
|
||||
new File(testData.getServerGit().getGitWorkingDirectory(), "/bar.properties"));
|
||||
StreamUtils.copy("foo: branchBar", Charset.defaultCharset(), out);
|
||||
@@ -403,7 +392,8 @@ public class JGitEnvironmentRepositoryIntegrationTests {
|
||||
|
||||
@Test
|
||||
public void testNewRemoteTag() throws Exception {
|
||||
JGitConfigServerTestData testData = JGitConfigServerTestData.prepareClonedGitRepository(TestConfiguration.class);
|
||||
JGitConfigServerTestData testData = JGitConfigServerTestData
|
||||
.prepareClonedGitRepository(TestConfiguration.class);
|
||||
|
||||
Git serverGit = testData.getServerGit().getGit();
|
||||
|
||||
@@ -413,10 +403,10 @@ public class JGitEnvironmentRepositoryIntegrationTests {
|
||||
|
||||
serverGit.checkout().setName("master").call();
|
||||
|
||||
//create a new tag
|
||||
// create a new tag
|
||||
serverGit.tag().setName("testTag").setMessage("Testing a tag").call();
|
||||
|
||||
//update the remote repo
|
||||
// update the remote repo
|
||||
FileOutputStream out = new FileOutputStream(
|
||||
new File(testData.getServerGit().getGitWorkingDirectory(), "/bar.properties"));
|
||||
StreamUtils.copy("foo: testAfterTag", Charset.defaultCharset(), out);
|
||||
@@ -431,50 +421,52 @@ public class JGitEnvironmentRepositoryIntegrationTests {
|
||||
fooProperty = ConfigServerTestUtils.getProperty(environment, "bar.properties", "foo");
|
||||
assertEquals(fooProperty, "bar");
|
||||
|
||||
//now move the tag and test again
|
||||
serverGit.tag().setName("testTag").setForceUpdate(true).setMessage("Testing a moved tag").call();
|
||||
// now move the tag and test again
|
||||
serverGit.tag().setName("testTag").setForceUpdate(true).setMessage("Testing a moved tag").call();
|
||||
|
||||
environment = testData.getRepository().findOne("bar", "staging", "testTag");
|
||||
fooProperty = ConfigServerTestUtils.getProperty(environment, "bar.properties", "foo");
|
||||
assertEquals(fooProperty, "testAfterTag");
|
||||
environment = testData.getRepository().findOne("bar", "staging", "testTag");
|
||||
fooProperty = ConfigServerTestUtils.getProperty(environment, "bar.properties", "foo");
|
||||
assertEquals(fooProperty, "testAfterTag");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test
|
||||
public void testNewCommitID() throws Exception {
|
||||
JGitConfigServerTestData testData = JGitConfigServerTestData.prepareClonedGitRepository(TestConfiguration.class);
|
||||
JGitConfigServerTestData testData = JGitConfigServerTestData
|
||||
.prepareClonedGitRepository(TestConfiguration.class);
|
||||
|
||||
//get our starting versions
|
||||
// get our starting versions
|
||||
String startingRemoteVersion = getCommitID(testData.getServerGit().getGit(), "master");
|
||||
|
||||
//make sure we get the right version out of the gate
|
||||
// make sure we get the right version out of the gate
|
||||
Environment environment = testData.getRepository().findOne("bar", "staging", "master");
|
||||
assertEquals(environment.getVersion(), startingRemoteVersion);
|
||||
|
||||
//update the remote repo
|
||||
FileOutputStream out = new FileOutputStream(new File(testData.getServerGit().getGitWorkingDirectory(), "bar.properties"));
|
||||
// update the remote repo
|
||||
FileOutputStream out = new FileOutputStream(
|
||||
new File(testData.getServerGit().getGitWorkingDirectory(), "bar.properties"));
|
||||
StreamUtils.copy("foo: barNewCommit", Charset.defaultCharset(), out);
|
||||
testData.getServerGit().getGit().add().addFilepattern("bar.properties").call();
|
||||
testData.getServerGit().getGit().commit().setMessage("Updated for pull").call();
|
||||
String updatedRemoteVersion = getCommitID(testData.getServerGit().getGit(), "master");
|
||||
|
||||
//do a normal request and verify we get the new version
|
||||
// do a normal request and verify we get the new version
|
||||
environment = testData.getRepository().findOne("bar", "staging", "master");
|
||||
assertEquals(environment.getVersion(), updatedRemoteVersion);
|
||||
Object fooProperty = ConfigServerTestUtils.getProperty(environment, "bar.properties", "foo");
|
||||
assertEquals(fooProperty, "barNewCommit");
|
||||
|
||||
//request the prior commit ID and make sure we get it
|
||||
// request the prior commit ID and make sure we get it
|
||||
environment = testData.getRepository().findOne("bar", "staging", startingRemoteVersion);
|
||||
assertEquals(environment.getVersion(), startingRemoteVersion);
|
||||
fooProperty = ConfigServerTestUtils.getProperty(environment, "bar.properties", "foo");
|
||||
assertEquals(fooProperty, "bar");
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = NoSuchLabelException.class)
|
||||
public void testUnknownLabelWithRemote() throws Exception {
|
||||
JGitConfigServerTestData testData = JGitConfigServerTestData.prepareClonedGitRepository(TestConfiguration.class);
|
||||
JGitConfigServerTestData testData = JGitConfigServerTestData
|
||||
.prepareClonedGitRepository(TestConfiguration.class);
|
||||
testData.getRepository().findOne("bar", "staging", "BADLabel");
|
||||
}
|
||||
|
||||
@@ -506,11 +498,31 @@ public class JGitEnvironmentRepositoryIntegrationTests {
|
||||
assertEquals(repository.isStrictHostKeyChecking(), strictHostKeyChecking);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldSetTransportConfigCallback() throws IOException {
|
||||
String uri = ConfigServerTestUtils.prepareLocalRepo();
|
||||
this.context = new SpringApplicationBuilder(TestConfigurationWithTransportConfigCallback.class).web(WebApplicationType.NONE)
|
||||
.properties("spring.cloud.config.server.git.uri:" + uri).run();
|
||||
|
||||
JGitEnvironmentRepository repository = this.context.getBean(JGitEnvironmentRepository.class);
|
||||
assertNotNull(repository.getTransportConfigCallback());
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(ConfigServerProperties.class)
|
||||
@Import({ PropertyPlaceholderAutoConfiguration.class,
|
||||
EnvironmentRepositoryConfiguration.class })
|
||||
@Import({ PropertyPlaceholderAutoConfiguration.class, EnvironmentRepositoryConfiguration.class })
|
||||
protected static class TestConfiguration {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(ConfigServerProperties.class)
|
||||
@Import({ PropertyPlaceholderAutoConfiguration.class, EnvironmentRepositoryConfiguration.class })
|
||||
protected static class TestConfigurationWithTransportConfigCallback {
|
||||
|
||||
@Bean
|
||||
public TransportConfigCallback transportConfigCallback() {
|
||||
return Mockito.mock(TransportConfigCallback.class);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,56 +16,6 @@
|
||||
|
||||
package org.springframework.cloud.config.server.environment;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.jcraft.jsch.Session;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.eclipse.jgit.api.CheckoutCommand;
|
||||
import org.eclipse.jgit.api.CloneCommand;
|
||||
import org.eclipse.jgit.api.FetchCommand;
|
||||
import org.eclipse.jgit.api.Git;
|
||||
import org.eclipse.jgit.api.ListBranchCommand;
|
||||
import org.eclipse.jgit.api.MergeCommand;
|
||||
import org.eclipse.jgit.api.ResetCommand;
|
||||
import org.eclipse.jgit.api.Status;
|
||||
import org.eclipse.jgit.api.StatusCommand;
|
||||
import org.eclipse.jgit.api.errors.GitAPIException;
|
||||
import org.eclipse.jgit.api.errors.InvalidRemoteException;
|
||||
import org.eclipse.jgit.api.errors.NotMergedException;
|
||||
import org.eclipse.jgit.api.errors.TransportException;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.eclipse.jgit.lib.Ref;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
import org.eclipse.jgit.lib.StoredConfig;
|
||||
import org.eclipse.jgit.transport.CredentialItem;
|
||||
import org.eclipse.jgit.transport.CredentialsProvider;
|
||||
import org.eclipse.jgit.transport.FetchResult;
|
||||
import org.eclipse.jgit.transport.JschConfigSessionFactory;
|
||||
import org.eclipse.jgit.transport.OpenSshConfig;
|
||||
import org.eclipse.jgit.transport.SshSessionFactory;
|
||||
import org.eclipse.jgit.transport.URIish;
|
||||
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
|
||||
import org.eclipse.jgit.util.FS;
|
||||
import org.eclipse.jgit.util.FileUtils;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
import org.springframework.cloud.config.environment.Environment;
|
||||
import org.springframework.cloud.config.server.support.AwsCodeCommitCredentialProvider;
|
||||
import org.springframework.cloud.config.server.support.GitCredentialsProviderFactory;
|
||||
import org.springframework.cloud.config.server.support.PassphraseCredentialsProvider;
|
||||
import org.springframework.cloud.config.server.test.ConfigServerTestUtils;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
|
||||
import static junit.framework.TestCase.assertTrue;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
@@ -81,6 +31,57 @@ import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.eclipse.jgit.api.CheckoutCommand;
|
||||
import org.eclipse.jgit.api.CloneCommand;
|
||||
import org.eclipse.jgit.api.FetchCommand;
|
||||
import org.eclipse.jgit.api.Git;
|
||||
import org.eclipse.jgit.api.ListBranchCommand;
|
||||
import org.eclipse.jgit.api.MergeCommand;
|
||||
import org.eclipse.jgit.api.ResetCommand;
|
||||
import org.eclipse.jgit.api.Status;
|
||||
import org.eclipse.jgit.api.StatusCommand;
|
||||
import org.eclipse.jgit.api.TransportConfigCallback;
|
||||
import org.eclipse.jgit.api.errors.GitAPIException;
|
||||
import org.eclipse.jgit.api.errors.InvalidRemoteException;
|
||||
import org.eclipse.jgit.api.errors.NotMergedException;
|
||||
import org.eclipse.jgit.api.errors.TransportException;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.eclipse.jgit.lib.Ref;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
import org.eclipse.jgit.lib.StoredConfig;
|
||||
import org.eclipse.jgit.transport.CredentialItem;
|
||||
import org.eclipse.jgit.transport.CredentialsProvider;
|
||||
import org.eclipse.jgit.transport.FetchResult;
|
||||
import org.eclipse.jgit.transport.JschConfigSessionFactory;
|
||||
import org.eclipse.jgit.transport.OpenSshConfig;
|
||||
import org.eclipse.jgit.transport.SshSessionFactory;
|
||||
import org.eclipse.jgit.transport.TrackingRefUpdate;
|
||||
import org.eclipse.jgit.transport.URIish;
|
||||
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
|
||||
import org.eclipse.jgit.util.FS;
|
||||
import org.eclipse.jgit.util.FileUtils;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.springframework.cloud.config.environment.Environment;
|
||||
import org.springframework.cloud.config.server.support.AwsCodeCommitCredentialProvider;
|
||||
import org.springframework.cloud.config.server.support.GitCredentialsProviderFactory;
|
||||
import org.springframework.cloud.config.server.support.PassphraseCredentialsProvider;
|
||||
import org.springframework.cloud.config.server.test.ConfigServerTestUtils;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
|
||||
import com.jcraft.jsch.Session;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
@@ -88,8 +89,7 @@ import static org.mockito.Mockito.when;
|
||||
public class JGitEnvironmentRepositoryTests {
|
||||
|
||||
private StandardEnvironment environment = new StandardEnvironment();
|
||||
private JGitEnvironmentRepository repository = new JGitEnvironmentRepository(
|
||||
this.environment);
|
||||
private JGitEnvironmentRepository repository = new JGitEnvironmentRepository(this.environment);
|
||||
|
||||
private File basedir = new File("target/config");
|
||||
|
||||
@@ -110,8 +110,7 @@ public class JGitEnvironmentRepositoryTests {
|
||||
this.repository.findOne("bar", "staging", "master");
|
||||
Environment environment = this.repository.findOne("bar", "staging", "master");
|
||||
assertEquals(2, environment.getPropertySources().size());
|
||||
assertEquals(this.repository.getUri() + "/bar.properties",
|
||||
environment.getPropertySources().get(0).getName());
|
||||
assertEquals(this.repository.getUri() + "/bar.properties", environment.getPropertySources().get(0).getName());
|
||||
assertVersion(environment);
|
||||
}
|
||||
|
||||
@@ -119,7 +118,7 @@ public class JGitEnvironmentRepositoryTests {
|
||||
public void nested() throws IOException {
|
||||
String uri = ConfigServerTestUtils.prepareLocalRepo("another-config-repo");
|
||||
this.repository.setUri(uri);
|
||||
this.repository.setSearchPaths(new String[] {"sub"});
|
||||
this.repository.setSearchPaths(new String[] { "sub" });
|
||||
this.repository.findOne("bar", "staging", "master");
|
||||
Environment environment = this.repository.findOne("bar", "staging", "master");
|
||||
assertEquals(2, environment.getPropertySources().size());
|
||||
@@ -132,7 +131,7 @@ public class JGitEnvironmentRepositoryTests {
|
||||
public void placeholderInSearchPath() throws IOException {
|
||||
String uri = ConfigServerTestUtils.prepareLocalRepo("another-config-repo");
|
||||
this.repository.setUri(uri);
|
||||
this.repository.setSearchPaths(new String[] {"{application}"});
|
||||
this.repository.setSearchPaths(new String[] { "{application}" });
|
||||
this.repository.findOne("sub", "staging", "master");
|
||||
Environment environment = this.repository.findOne("sub", "staging", "master");
|
||||
assertEquals(1, environment.getPropertySources().size());
|
||||
@@ -151,7 +150,7 @@ public class JGitEnvironmentRepositoryTests {
|
||||
public void nestedPattern() throws IOException {
|
||||
String uri = ConfigServerTestUtils.prepareLocalRepo("another-config-repo");
|
||||
this.repository.setUri(uri);
|
||||
this.repository.setSearchPaths(new String[] {"sub*"});
|
||||
this.repository.setSearchPaths(new String[] { "sub*" });
|
||||
this.repository.findOne("bar", "staging", "master");
|
||||
Environment environment = this.repository.findOne("bar", "staging", "master");
|
||||
assertEquals(2, environment.getPropertySources().size());
|
||||
@@ -165,8 +164,7 @@ public class JGitEnvironmentRepositoryTests {
|
||||
this.repository.setBasedir(this.basedir);
|
||||
Environment environment = this.repository.findOne("bar", "staging", "raw");
|
||||
assertEquals(2, environment.getPropertySources().size());
|
||||
assertEquals(this.repository.getUri() + "/bar.properties",
|
||||
environment.getPropertySources().get(0).getName());
|
||||
assertEquals(this.repository.getUri() + "/bar.properties", environment.getPropertySources().get(0).getName());
|
||||
assertVersion(environment);
|
||||
}
|
||||
|
||||
@@ -175,8 +173,7 @@ public class JGitEnvironmentRepositoryTests {
|
||||
this.repository.setBasedir(this.basedir);
|
||||
Environment environment = this.repository.findOne("bar", "staging", "foo");
|
||||
assertEquals(2, environment.getPropertySources().size());
|
||||
assertEquals(this.repository.getUri() + "/bar.properties", environment
|
||||
.getPropertySources().get(0).getName());
|
||||
assertEquals(this.repository.getUri() + "/bar.properties", environment.getPropertySources().get(0).getName());
|
||||
assertVersion(environment);
|
||||
}
|
||||
|
||||
@@ -186,8 +183,7 @@ public class JGitEnvironmentRepositoryTests {
|
||||
this.repository.findOne("bar", "staging", "master");
|
||||
Environment environment = this.repository.findOne("bar", "staging", "master");
|
||||
assertEquals(2, environment.getPropertySources().size());
|
||||
assertEquals(this.repository.getUri() + "/bar.properties",
|
||||
environment.getPropertySources().get(0).getName());
|
||||
assertEquals(this.repository.getUri() + "/bar.properties", environment.getPropertySources().get(0).getName());
|
||||
assertVersion(environment);
|
||||
}
|
||||
|
||||
@@ -199,8 +195,7 @@ public class JGitEnvironmentRepositoryTests {
|
||||
this.repository.findOne("bar", "staging", "master");
|
||||
Environment environment = this.repository.findOne("bar", "staging", "master");
|
||||
assertEquals(2, environment.getPropertySources().size());
|
||||
assertEquals(this.repository.getUri() + "/bar.properties",
|
||||
environment.getPropertySources().get(0).getName());
|
||||
assertEquals(this.repository.getUri() + "/bar.properties", environment.getPropertySources().get(0).getName());
|
||||
assertVersion(environment);
|
||||
}
|
||||
|
||||
@@ -217,16 +212,14 @@ public class JGitEnvironmentRepositoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void afterPropertiesSet_CloneOnStartTrue_CloneAndFetchCalled()
|
||||
throws Exception {
|
||||
public void afterPropertiesSet_CloneOnStartTrue_CloneAndFetchCalled() throws Exception {
|
||||
Git mockGit = mock(Git.class);
|
||||
CloneCommand mockCloneCommand = mock(CloneCommand.class);
|
||||
|
||||
when(mockCloneCommand.setURI(anyString())).thenReturn(mockCloneCommand);
|
||||
when(mockCloneCommand.setDirectory(any(File.class))).thenReturn(mockCloneCommand);
|
||||
|
||||
JGitEnvironmentRepository envRepository = new JGitEnvironmentRepository(
|
||||
this.environment);
|
||||
JGitEnvironmentRepository envRepository = new JGitEnvironmentRepository(this.environment);
|
||||
envRepository.setGitFactory(new MockGitFactory(mockGit, mockCloneCommand));
|
||||
envRepository.setUri("http://somegitserver/somegitrepo");
|
||||
envRepository.setCloneOnStart(true);
|
||||
@@ -235,16 +228,14 @@ public class JGitEnvironmentRepositoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void afterPropertiesSet_CloneOnStartFalse_CloneAndFetchNotCalled()
|
||||
throws Exception {
|
||||
public void afterPropertiesSet_CloneOnStartFalse_CloneAndFetchNotCalled() throws Exception {
|
||||
Git mockGit = mock(Git.class);
|
||||
CloneCommand mockCloneCommand = mock(CloneCommand.class);
|
||||
|
||||
when(mockCloneCommand.setURI(anyString())).thenReturn(mockCloneCommand);
|
||||
when(mockCloneCommand.setDirectory(any(File.class))).thenReturn(mockCloneCommand);
|
||||
|
||||
JGitEnvironmentRepository envRepository = new JGitEnvironmentRepository(
|
||||
this.environment);
|
||||
JGitEnvironmentRepository envRepository = new JGitEnvironmentRepository(this.environment);
|
||||
envRepository.setGitFactory(new MockGitFactory(mockGit, mockCloneCommand));
|
||||
envRepository.setUri("http://somegitserver/somegitrepo");
|
||||
envRepository.afterPropertiesSet();
|
||||
@@ -253,16 +244,14 @@ public class JGitEnvironmentRepositoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void afterPropertiesSet_CloneOnStartTrueWithFileURL_CloneAndFetchNotCalled()
|
||||
throws Exception {
|
||||
public void afterPropertiesSet_CloneOnStartTrueWithFileURL_CloneAndFetchNotCalled() throws Exception {
|
||||
Git mockGit = mock(Git.class);
|
||||
CloneCommand mockCloneCommand = mock(CloneCommand.class);
|
||||
|
||||
when(mockCloneCommand.setURI(anyString())).thenReturn(mockCloneCommand);
|
||||
when(mockCloneCommand.setDirectory(any(File.class))).thenReturn(mockCloneCommand);
|
||||
|
||||
JGitEnvironmentRepository envRepository = new JGitEnvironmentRepository(
|
||||
this.environment);
|
||||
JGitEnvironmentRepository envRepository = new JGitEnvironmentRepository(this.environment);
|
||||
envRepository.setGitFactory(new MockGitFactory(mockGit, mockCloneCommand));
|
||||
envRepository.setUri("file://somefilesystem/somegitrepo");
|
||||
envRepository.setCloneOnStart(true);
|
||||
@@ -286,8 +275,7 @@ public class JGitEnvironmentRepositoryTests {
|
||||
when(statusCommand.call()).thenReturn(status);
|
||||
when(status.isClean()).thenReturn(false);
|
||||
|
||||
JGitEnvironmentRepository repo = new JGitEnvironmentRepository(
|
||||
this.environment);
|
||||
JGitEnvironmentRepository repo = new JGitEnvironmentRepository(this.environment);
|
||||
repo.setForcePull(true);
|
||||
|
||||
boolean shouldPull = repo.shouldPull(git);
|
||||
@@ -310,8 +298,7 @@ public class JGitEnvironmentRepositoryTests {
|
||||
when(statusCommand.call()).thenReturn(status);
|
||||
when(status.isClean()).thenReturn(false);
|
||||
|
||||
JGitEnvironmentRepository repo = new JGitEnvironmentRepository(
|
||||
this.environment);
|
||||
JGitEnvironmentRepository repo = new JGitEnvironmentRepository(this.environment);
|
||||
|
||||
boolean shouldPull = repo.shouldPull(git);
|
||||
|
||||
@@ -333,8 +320,7 @@ public class JGitEnvironmentRepositoryTests {
|
||||
when(statusCommand.call()).thenReturn(status);
|
||||
when(status.isClean()).thenReturn(true);
|
||||
|
||||
JGitEnvironmentRepository repo = new JGitEnvironmentRepository(
|
||||
this.environment);
|
||||
JGitEnvironmentRepository repo = new JGitEnvironmentRepository(this.environment);
|
||||
|
||||
boolean shouldPull = repo.shouldPull(git);
|
||||
|
||||
@@ -347,11 +333,9 @@ public class JGitEnvironmentRepositoryTests {
|
||||
Git git = mock(Git.class);
|
||||
CloneCommand cloneCommand = mock(CloneCommand.class);
|
||||
MockGitFactory factory = new MockGitFactory(git, cloneCommand);
|
||||
JGitEnvironmentRepository repo = new JGitEnvironmentRepository(
|
||||
this.environment);
|
||||
this.repository.setGitFactory(factory);
|
||||
|
||||
//refresh()->shouldPull
|
||||
// refresh()->shouldPull
|
||||
StatusCommand statusCommand = mock(StatusCommand.class);
|
||||
Status status = mock(Status.class);
|
||||
when(git.status()).thenReturn(statusCommand);
|
||||
@@ -363,15 +347,21 @@ public class JGitEnvironmentRepositoryTests {
|
||||
when(statusCommand.call()).thenReturn(status);
|
||||
when(status.isClean()).thenReturn(true);
|
||||
|
||||
//refresh()->fetch
|
||||
// refresh()->fetch
|
||||
FetchCommand fetchCommand = mock(FetchCommand.class);
|
||||
when(git.fetch()).thenReturn(fetchCommand);
|
||||
when(fetchCommand.setRemote(anyString())).thenReturn(fetchCommand);
|
||||
when(fetchCommand.call()).thenThrow(new InvalidRemoteException("invalid mock remote")); //here is our exception we are testing
|
||||
when(fetchCommand.call()).thenThrow(new InvalidRemoteException("invalid mock remote")); // here
|
||||
// is
|
||||
// our
|
||||
// exception
|
||||
// we
|
||||
// are
|
||||
// testing
|
||||
|
||||
//refresh()->checkout
|
||||
// refresh()->checkout
|
||||
CheckoutCommand checkoutCommand = mock(CheckoutCommand.class);
|
||||
//refresh()->checkout->containsBranch
|
||||
// refresh()->checkout->containsBranch
|
||||
ListBranchCommand listBranchCommand = mock(ListBranchCommand.class);
|
||||
when(git.checkout()).thenReturn(checkoutCommand);
|
||||
when(git.branchList()).thenReturn(listBranchCommand);
|
||||
@@ -381,20 +371,27 @@ public class JGitEnvironmentRepositoryTests {
|
||||
when(ref.getName()).thenReturn("/master");
|
||||
when(listBranchCommand.call()).thenReturn(refs);
|
||||
|
||||
//refresh()->merge
|
||||
// refresh()->merge
|
||||
MergeCommand mergeCommand = mock(MergeCommand.class);
|
||||
when(git.merge()).thenReturn(mergeCommand);
|
||||
when(mergeCommand.call()).thenThrow(new NotMergedException()); //here is our exception we are testing
|
||||
when(mergeCommand.call()).thenThrow(new NotMergedException()); // here
|
||||
// is
|
||||
// our
|
||||
// exception
|
||||
// we
|
||||
// are
|
||||
// testing
|
||||
|
||||
//refresh()->return git.getRepository().getRef("HEAD").getObjectId().getName();
|
||||
// refresh()->return
|
||||
// git.getRepository().getRef("HEAD").getObjectId().getName();
|
||||
Ref headRef = mock(Ref.class);
|
||||
when(repository.getRef(anyString())).thenReturn(headRef);
|
||||
when(repository.findRef(anyString())).thenReturn(headRef);
|
||||
|
||||
ObjectId newObjectId = ObjectId.fromRaw(new int[]{1,2,3,4,5});
|
||||
ObjectId newObjectId = ObjectId.fromRaw(new int[] { 1, 2, 3, 4, 5 });
|
||||
when(headRef.getObjectId()).thenReturn(newObjectId);
|
||||
|
||||
SearchPathLocator.Locations locations = this.repository.getLocations("bar", "staging", null);
|
||||
assertEquals(locations.getVersion(),newObjectId.getName());
|
||||
assertEquals(locations.getVersion(), newObjectId.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -403,8 +400,6 @@ public class JGitEnvironmentRepositoryTests {
|
||||
Git git = mock(Git.class);
|
||||
CloneCommand cloneCommand = mock(CloneCommand.class);
|
||||
MockGitFactory factory = new MockGitFactory(git, cloneCommand);
|
||||
JGitEnvironmentRepository repo = new JGitEnvironmentRepository(
|
||||
this.environment);
|
||||
this.repository.setGitFactory(factory);
|
||||
|
||||
//refresh()->shouldPull
|
||||
@@ -425,7 +420,7 @@ public class JGitEnvironmentRepositoryTests {
|
||||
when(git.fetch()).thenReturn(fetchCommand);
|
||||
when(fetchCommand.setRemote(anyString())).thenReturn(fetchCommand);
|
||||
when(fetchCommand.call()).thenReturn(fetchResult);
|
||||
when(fetchResult.getTrackingRefUpdates()).thenReturn(Collections.EMPTY_LIST);
|
||||
when(fetchResult.getTrackingRefUpdates()).thenReturn(Collections.<TrackingRefUpdate>emptyList());
|
||||
|
||||
//refresh()->checkout
|
||||
CheckoutCommand checkoutCommand = mock(CheckoutCommand.class);
|
||||
@@ -446,7 +441,7 @@ public class JGitEnvironmentRepositoryTests {
|
||||
|
||||
//refresh()->return git.getRepository().getRef("HEAD").getObjectId().getName();
|
||||
Ref headRef = mock(Ref.class);
|
||||
when(repository.getRef(anyString())).thenReturn(headRef);
|
||||
when(repository.findRef(anyString())).thenReturn(headRef);
|
||||
|
||||
ObjectId newObjectId = ObjectId.fromRaw(new int[]{1,2,3,4,5});
|
||||
when(headRef.getObjectId()).thenReturn(newObjectId);
|
||||
@@ -461,11 +456,9 @@ public class JGitEnvironmentRepositoryTests {
|
||||
Git git = mock(Git.class);
|
||||
CloneCommand cloneCommand = mock(CloneCommand.class);
|
||||
MockGitFactory factory = new MockGitFactory(git, cloneCommand);
|
||||
JGitEnvironmentRepository repo = new JGitEnvironmentRepository(
|
||||
this.environment);
|
||||
this.repository.setGitFactory(factory);
|
||||
|
||||
//refresh()->shouldPull
|
||||
// refresh()->shouldPull
|
||||
StatusCommand statusCommand = mock(StatusCommand.class);
|
||||
Status status = mock(Status.class);
|
||||
when(git.status()).thenReturn(statusCommand);
|
||||
@@ -477,17 +470,17 @@ public class JGitEnvironmentRepositoryTests {
|
||||
when(statusCommand.call()).thenReturn(status);
|
||||
when(status.isClean()).thenReturn(true).thenReturn(false);
|
||||
|
||||
//refresh()->fetch
|
||||
// refresh()->fetch
|
||||
FetchCommand fetchCommand = mock(FetchCommand.class);
|
||||
FetchResult fetchResult = mock(FetchResult.class);
|
||||
when(git.fetch()).thenReturn(fetchCommand);
|
||||
when(fetchCommand.setRemote(anyString())).thenReturn(fetchCommand);
|
||||
when(fetchCommand.call()).thenReturn(fetchResult);
|
||||
when(fetchResult.getTrackingRefUpdates()).thenReturn(Collections.EMPTY_LIST);
|
||||
when(fetchResult.getTrackingRefUpdates()).thenReturn(Collections.<TrackingRefUpdate>emptyList());
|
||||
|
||||
//refresh()->checkout
|
||||
// refresh()->checkout
|
||||
CheckoutCommand checkoutCommand = mock(CheckoutCommand.class);
|
||||
//refresh()->checkout->containsBranch
|
||||
// refresh()->checkout->containsBranch
|
||||
ListBranchCommand listBranchCommand = mock(ListBranchCommand.class);
|
||||
when(git.checkout()).thenReturn(checkoutCommand);
|
||||
when(git.branchList()).thenReturn(listBranchCommand);
|
||||
@@ -497,29 +490,36 @@ public class JGitEnvironmentRepositoryTests {
|
||||
when(ref.getName()).thenReturn("/master");
|
||||
when(listBranchCommand.call()).thenReturn(refs);
|
||||
|
||||
//refresh()->merge
|
||||
// refresh()->merge
|
||||
MergeCommand mergeCommand = mock(MergeCommand.class);
|
||||
when(git.merge()).thenReturn(mergeCommand);
|
||||
when(mergeCommand.call()).thenThrow(new NotMergedException()); //here is our exception we are testing
|
||||
when(mergeCommand.call()).thenThrow(new NotMergedException()); // here
|
||||
// is
|
||||
// our
|
||||
// exception
|
||||
// we
|
||||
// are
|
||||
// testing
|
||||
|
||||
//refresh()->hardReset
|
||||
// refresh()->hardReset
|
||||
ResetCommand resetCommand = mock(ResetCommand.class);
|
||||
when(git.reset()).thenReturn(resetCommand);
|
||||
when(resetCommand.call()).thenReturn(ref);
|
||||
|
||||
//refresh()->return git.getRepository().getRef("HEAD").getObjectId().getName();
|
||||
// refresh()->return
|
||||
// git.getRepository().getRef("HEAD").getObjectId().getName();
|
||||
Ref headRef = mock(Ref.class);
|
||||
when(repository.getRef(anyString())).thenReturn(headRef);
|
||||
when(repository.findRef(anyString())).thenReturn(headRef);
|
||||
|
||||
ObjectId newObjectId = ObjectId.fromRaw(new int[]{1,2,3,4,5});
|
||||
ObjectId newObjectId = ObjectId.fromRaw(new int[] { 1, 2, 3, 4, 5 });
|
||||
when(headRef.getObjectId()).thenReturn(newObjectId);
|
||||
|
||||
SearchPathLocator.Locations locations = this.repository.getLocations("bar", "staging", "master");
|
||||
assertEquals(locations.getVersion(),newObjectId.getName());
|
||||
assertEquals(locations.getVersion(), newObjectId.getName());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void shouldDeleteBaseDirWhenCloneFails() throws Exception {
|
||||
public void shouldDeleteBaseDirWhenCloneFails() throws Exception {
|
||||
Git mockGit = mock(Git.class);
|
||||
CloneCommand mockCloneCommand = mock(CloneCommand.class);
|
||||
|
||||
@@ -527,19 +527,17 @@ public class JGitEnvironmentRepositoryTests {
|
||||
when(mockCloneCommand.setDirectory(any(File.class))).thenReturn(mockCloneCommand);
|
||||
when(mockCloneCommand.call()).thenThrow(new TransportException("failed to clone"));
|
||||
|
||||
JGitEnvironmentRepository envRepository = new JGitEnvironmentRepository(
|
||||
this.environment);
|
||||
JGitEnvironmentRepository envRepository = new JGitEnvironmentRepository(this.environment);
|
||||
envRepository.setGitFactory(new MockGitFactory(mockGit, mockCloneCommand));
|
||||
envRepository.setUri("http://somegitserver/somegitrepo");
|
||||
envRepository.setBasedir(this.basedir);
|
||||
|
||||
|
||||
try {
|
||||
envRepository.findOne("bar", "staging", "master");
|
||||
}
|
||||
catch (Exception ex) {
|
||||
} catch (Exception ex) {
|
||||
// expected - ignore
|
||||
}
|
||||
|
||||
|
||||
assertFalse("baseDir should be deleted when clone fails", this.basedir.exists());
|
||||
}
|
||||
|
||||
@@ -592,13 +590,14 @@ public class JGitEnvironmentRepositoryTests {
|
||||
CredentialsProvider provider = mockCloneCommand.getCredentialsProvider();
|
||||
assertFalse(provider.isInteractive());
|
||||
|
||||
CredentialItem.StringType stringCredential = new CredentialItem.StringType(PassphraseCredentialsProvider.PROMPT, true);
|
||||
CredentialItem.StringType stringCredential = new CredentialItem.StringType(PassphraseCredentialsProvider.PROMPT,
|
||||
true);
|
||||
|
||||
assertTrue(provider.supports(stringCredential));
|
||||
provider.get(new URIish(), stringCredential);
|
||||
assertEquals(stringCredential.getValue(), passphrase);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void gitCredentialsProviderFactoryCreatesPassphraseProvider() throws Exception {
|
||||
final String passphrase = "mypassphrase";
|
||||
@@ -620,7 +619,8 @@ public class JGitEnvironmentRepositoryTests {
|
||||
CredentialsProvider provider = mockCloneCommand.getCredentialsProvider();
|
||||
assertFalse(provider.isInteractive());
|
||||
|
||||
CredentialItem.StringType stringCredential = new CredentialItem.StringType(PassphraseCredentialsProvider.PROMPT, true);
|
||||
CredentialItem.StringType stringCredential = new CredentialItem.StringType(PassphraseCredentialsProvider.PROMPT,
|
||||
true);
|
||||
|
||||
assertTrue(provider.supports(stringCredential));
|
||||
provider.get(new URIish(), stringCredential);
|
||||
@@ -640,8 +640,8 @@ public class JGitEnvironmentRepositoryTests {
|
||||
envRepository.setGitFactory(new MockGitFactory(mockGit, mockCloneCommand));
|
||||
envRepository.setUri("git+ssh://git@somegitserver/somegitrepo");
|
||||
envRepository.setBasedir(new File("./mybasedir"));
|
||||
envRepository.setGitCredentialsProvider(credentialsFactory.createFor(
|
||||
envRepository.getUri(), username, password, null));
|
||||
envRepository.setGitCredentialsProvider(
|
||||
credentialsFactory.createFor(envRepository.getUri(), username, password, null));
|
||||
envRepository.setCloneOnStart(true);
|
||||
envRepository.afterPropertiesSet();
|
||||
|
||||
@@ -665,12 +665,11 @@ public class JGitEnvironmentRepositoryTests {
|
||||
Git mockGit = mock(Git.class);
|
||||
MockCloneCommand mockCloneCommand = new MockCloneCommand(mockGit);
|
||||
final String awsUri = "https://git-codecommit.us-east-1.amazonaws.com/v1/repos/test";
|
||||
|
||||
|
||||
JGitEnvironmentRepository envRepository = new JGitEnvironmentRepository(this.environment);
|
||||
envRepository.setGitFactory(new MockGitFactory(mockGit, mockCloneCommand));
|
||||
envRepository.setUri(awsUri);
|
||||
envRepository.setGitCredentialsProvider(credentialsFactory.createFor(
|
||||
envRepository.getUri(), null, null, null));
|
||||
envRepository.setGitCredentialsProvider(credentialsFactory.createFor(envRepository.getUri(), null, null, null));
|
||||
envRepository.setCloneOnStart(true);
|
||||
envRepository.afterPropertiesSet();
|
||||
|
||||
@@ -693,14 +692,17 @@ public class JGitEnvironmentRepositoryTests {
|
||||
} catch (Exception e) {
|
||||
final OpenSshConfig.Host hc = OpenSshConfig.get(FS.detect()).lookup("github.com");
|
||||
JschConfigSessionFactory factory = (JschConfigSessionFactory) SshSessionFactory.getInstance();
|
||||
// There's no public method that can be used to inspect the ssh configuration, so we'll reflect
|
||||
// the configure method to allow us to check that the config property is set as expected.
|
||||
Method configure = factory.getClass().getDeclaredMethod("configure", OpenSshConfig.Host.class, Session.class );
|
||||
// There's no public method that can be used to inspect the ssh
|
||||
// configuration, so we'll reflect
|
||||
// the configure method to allow us to check that the config
|
||||
// property is set as expected.
|
||||
Method configure = factory.getClass().getDeclaredMethod("configure", OpenSshConfig.Host.class,
|
||||
Session.class);
|
||||
configure.setAccessible(true);
|
||||
Session session = mock(Session.class);
|
||||
ArgumentCaptor<String> keyCaptor = ArgumentCaptor.forClass(String.class);
|
||||
ArgumentCaptor<String> valueCaptor = ArgumentCaptor.forClass(String.class);
|
||||
configure.invoke(factory, hc, session );
|
||||
configure.invoke(factory, hc, session);
|
||||
verify(session).setConfig(keyCaptor.capture(), valueCaptor.capture());
|
||||
configure.setAccessible(false);
|
||||
assertTrue("yes".equals(valueCaptor.getValue()));
|
||||
@@ -710,7 +712,7 @@ public class JGitEnvironmentRepositoryTests {
|
||||
@Test
|
||||
public void shouldPrintStacktraceIfDebugEnabled() throws Exception {
|
||||
final Log mockLogger = mock(Log.class);
|
||||
JGitEnvironmentRepository envRepository = new JGitEnvironmentRepository(this.environment){
|
||||
JGitEnvironmentRepository envRepository = new JGitEnvironmentRepository(this.environment) {
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
this.logger = mockLogger;
|
||||
@@ -728,6 +730,31 @@ public class JGitEnvironmentRepositoryTests {
|
||||
assertEquals("should call isDebugEnabled warn and debug", 3, numberOfInvocations);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldSetTransportConfigCallbackOnCloneAndFetch() throws Exception {
|
||||
Git mockGit = mock(Git.class);
|
||||
FetchCommand fetchCommand = mock(FetchCommand.class);
|
||||
when(mockGit.fetch()).thenReturn(fetchCommand);
|
||||
when(fetchCommand.call()).thenReturn(mock(FetchResult.class));
|
||||
|
||||
CloneCommand mockCloneCommand = mock(CloneCommand.class);
|
||||
when(mockCloneCommand.setURI(anyString())).thenReturn(mockCloneCommand);
|
||||
when(mockCloneCommand.setDirectory(any(File.class))).thenReturn(mockCloneCommand);
|
||||
|
||||
TransportConfigCallback configCallback = mock(TransportConfigCallback.class);
|
||||
JGitEnvironmentRepository envRepository = new JGitEnvironmentRepository(this.environment);
|
||||
envRepository.setGitFactory(new MockGitFactory(mockGit, mockCloneCommand));
|
||||
envRepository.setUri("http://somegitserver/somegitrepo");
|
||||
envRepository.setTransportConfigCallback(configCallback);
|
||||
envRepository.setCloneOnStart(true);
|
||||
|
||||
envRepository.afterPropertiesSet();
|
||||
verify(mockCloneCommand, times(1)).setTransportConfigCallback(configCallback);
|
||||
|
||||
envRepository.fetch(mockGit, "master");
|
||||
verify(fetchCommand, times(1)).setTransportConfigCallback(configCallback);
|
||||
}
|
||||
|
||||
class MockCloneCommand extends CloneCommand {
|
||||
private Git mockGit;
|
||||
|
||||
@@ -749,13 +776,12 @@ public class JGitEnvironmentRepositoryTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class MockGitFactory extends JGitEnvironmentRepository.JGitFactory {
|
||||
|
||||
private Git mockGit;
|
||||
private CloneCommand mockCloneCommand;
|
||||
|
||||
public MockGitFactory (Git mockGit, CloneCommand mockCloneCommand) {
|
||||
public MockGitFactory(Git mockGit, CloneCommand mockCloneCommand) {
|
||||
this.mockGit = mockGit;
|
||||
this.mockCloneCommand = mockCloneCommand;
|
||||
}
|
||||
|
||||
@@ -15,22 +15,27 @@
|
||||
*/
|
||||
package org.springframework.cloud.config.server.environment;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.cloud.config.environment.Environment;
|
||||
import org.springframework.cloud.config.server.environment.MultipleJGitEnvironmentRepository.PatternMatchingJGitEnvironmentRepository;
|
||||
import org.springframework.cloud.config.server.environment.SearchPathLocator.Locations;
|
||||
import org.springframework.cloud.config.server.test.ConfigServerTestUtils;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
@@ -46,6 +51,7 @@ public class MultipleJGitEnvironmentProfilePlaceholderRepositoryTests {
|
||||
public void init() throws Exception {
|
||||
String defaultUri = ConfigServerTestUtils.prepareLocalRepo("config-repo");
|
||||
this.repository.setUri(defaultUri);
|
||||
this.repository.setBasedir(new File("target/repos/parent_repo"));
|
||||
this.repository.setRepos(createRepositories());
|
||||
}
|
||||
|
||||
@@ -67,6 +73,7 @@ public class MultipleJGitEnvironmentProfilePlaceholderRepositoryTests {
|
||||
repo.setName(name);
|
||||
repo.setPattern(new String[] { pattern });
|
||||
repo.setUri(uri);
|
||||
repo.setBasedir(new File("target/repos/pattern_repos", name));
|
||||
return repo;
|
||||
}
|
||||
|
||||
@@ -84,11 +91,12 @@ public class MultipleJGitEnvironmentProfilePlaceholderRepositoryTests {
|
||||
Environment environment = this.repository.findOne("application",
|
||||
"test1-config-repo", "master");
|
||||
assertEquals(1, environment.getPropertySources().size());
|
||||
assertEquals(
|
||||
getUri("*").replace("{profile}", "test1-config-repo")
|
||||
+ "/application.yml",
|
||||
String uri = getUri("*").replace("{profile}", "test1-config-repo");
|
||||
assertEquals(uri + "/application.yml",
|
||||
environment.getPropertySources().get(0).getName());
|
||||
assertVersion(environment);
|
||||
assertThat(StringUtils.cleanPath(getRepository(uri).getBasedir().toString()),
|
||||
containsString("target/repos"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -141,6 +149,13 @@ public class MultipleJGitEnvironmentProfilePlaceholderRepositoryTests {
|
||||
"test2-config-repo", "missing-config-repo" });
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private JGitEnvironmentRepository getRepository(String uri) {
|
||||
Map<String, JGitEnvironmentRepository> repos = (Map<String, JGitEnvironmentRepository>) ReflectionTestUtils
|
||||
.getField(repository, "placeholders");
|
||||
return repos.get(uri);
|
||||
}
|
||||
|
||||
private void assertVersion(Environment environment) {
|
||||
String version = environment.getVersion();
|
||||
assertNotNull("version was null", version);
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package org.springframework.cloud.config.server.environment;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -24,8 +27,10 @@ import java.util.Map;
|
||||
import org.eclipse.jgit.util.FileUtils;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.junit.internal.matchers.ThrowableMessageMatcher;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.springframework.boot.WebApplicationType;
|
||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
@@ -38,8 +43,6 @@ import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* @author Andy Chan (iceycake)
|
||||
* @author Dave Syer
|
||||
@@ -51,6 +54,9 @@ public class MultipleJGitEnvironmentRepositoryIntegrationTests {
|
||||
|
||||
private File basedir = new File("target/config");
|
||||
|
||||
@Rule
|
||||
public ExpectedException expected = ExpectedException.none();
|
||||
|
||||
@Before
|
||||
public void init() throws Exception {
|
||||
if (this.basedir.exists()) {
|
||||
@@ -184,6 +190,17 @@ public class MultipleJGitEnvironmentRepositoryIntegrationTests {
|
||||
assertEquals(2, environment.getPropertySources().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonWritableBasedir() throws IOException {
|
||||
String defaultRepoUri = ConfigServerTestUtils.prepareLocalRepo("config-repo");
|
||||
expected.expectCause(ThrowableMessageMatcher
|
||||
.hasMessage(containsString("Cannot write parent")));
|
||||
this.context = new SpringApplicationBuilder(TestConfiguration.class).web(false)
|
||||
.properties("spring.cloud.config.server.git.uri:" + defaultRepoUri,
|
||||
"spring.cloud.config.server.git.basedir:/tmp")
|
||||
.run();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(ConfigServerProperties.class)
|
||||
@Import({ PropertyPlaceholderAutoConfiguration.class,
|
||||
|
||||
@@ -15,22 +15,32 @@
|
||||
*/
|
||||
package org.springframework.cloud.config.server.environment;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jgit.api.TransportConfigCallback;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.springframework.cloud.config.environment.Environment;
|
||||
import org.springframework.cloud.config.server.environment.MultipleJGitEnvironmentRepository.PatternMatchingJGitEnvironmentRepository;
|
||||
import org.springframework.cloud.config.server.test.ConfigServerTestUtils;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Andy Chan (iceycake)
|
||||
* @author Dave Syer
|
||||
@@ -39,17 +49,23 @@ import static org.junit.Assert.assertTrue;
|
||||
*/
|
||||
public class MultipleJGitEnvironmentRepositoryTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException exception = ExpectedException.none();
|
||||
|
||||
private StandardEnvironment environment = new StandardEnvironment();
|
||||
private MultipleJGitEnvironmentRepository repository = new MultipleJGitEnvironmentRepository(this.environment);
|
||||
private MultipleJGitEnvironmentRepository repository;
|
||||
|
||||
|
||||
@Before
|
||||
public void init() throws Exception {
|
||||
String defaultUri = ConfigServerTestUtils.prepareLocalRepo("config-repo");
|
||||
this.repository = new MultipleJGitEnvironmentRepository(this.environment);
|
||||
this.repository.setUri(defaultUri);
|
||||
this.repository.setRepos(createRepositories());
|
||||
}
|
||||
|
||||
private Map<String, PatternMatchingJGitEnvironmentRepository> createRepositories() throws Exception {
|
||||
private Map<String, PatternMatchingJGitEnvironmentRepository> createRepositories()
|
||||
throws Exception {
|
||||
String test1Uri = ConfigServerTestUtils.prepareLocalRepo("test1-config-repo");
|
||||
|
||||
Map<String, PatternMatchingJGitEnvironmentRepository> repos = new HashMap<>();
|
||||
@@ -57,12 +73,14 @@ public class MultipleJGitEnvironmentRepositoryTests {
|
||||
return repos;
|
||||
}
|
||||
|
||||
private PatternMatchingJGitEnvironmentRepository createRepository(String name, String pattern, String uri) {
|
||||
private PatternMatchingJGitEnvironmentRepository createRepository(String name,
|
||||
String pattern, String uri) {
|
||||
PatternMatchingJGitEnvironmentRepository repo = new PatternMatchingJGitEnvironmentRepository();
|
||||
repo.setEnvironment(this.environment);
|
||||
repo.setName(name);
|
||||
repo.setPattern(new String[] {pattern});
|
||||
repo.setPattern(new String[] { pattern });
|
||||
repo.setUri(uri);
|
||||
repo.setBasedir(new File(this.repository.getBasedir().getParentFile(), name));
|
||||
return repo;
|
||||
}
|
||||
|
||||
@@ -78,14 +96,15 @@ public class MultipleJGitEnvironmentRepositoryTests {
|
||||
private void assertVersion(Environment environment) {
|
||||
String version = environment.getVersion();
|
||||
assertNotNull("version was null", version);
|
||||
assertTrue("version length was wrong", version.length() >= 40 && version.length() <= 64);
|
||||
assertTrue("version length was wrong",
|
||||
version.length() >= 40 && version.length() <= 64);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultRepoNested() throws IOException {
|
||||
String uri = ConfigServerTestUtils.prepareLocalRepo("another-config-repo");
|
||||
this.repository.setUri(uri);
|
||||
this.repository.setSearchPaths(new String[] {"sub"});
|
||||
this.repository.setSearchPaths(new String[] { "sub" });
|
||||
this.repository.findOne("bar", "staging", "master");
|
||||
Environment environment = this.repository.findOne("bar", "staging", "master");
|
||||
assertEquals(2, environment.getPropertySources().size());
|
||||
@@ -107,13 +126,13 @@ public class MultipleJGitEnvironmentRepositoryTests {
|
||||
public void defaultRepoTag() {
|
||||
Environment environment = this.repository.findOne("bar", "staging", "foo");
|
||||
assertEquals(2, environment.getPropertySources().size());
|
||||
assertEquals(this.repository.getUri() + "/bar.properties", environment
|
||||
.getPropertySources().get(0).getName());
|
||||
assertEquals(this.repository.getUri() + "/bar.properties",
|
||||
environment.getPropertySources().get(0).getName());
|
||||
assertVersion(environment);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultRepoBasedir() {
|
||||
public void defaultRepoTwice() {
|
||||
this.repository.findOne("bar", "staging", "master");
|
||||
Environment environment = this.repository.findOne("bar", "staging", "master");
|
||||
assertEquals(2, environment.getPropertySources().size());
|
||||
@@ -122,9 +141,18 @@ public class MultipleJGitEnvironmentRepositoryTests {
|
||||
assertVersion(environment);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultRepoBasedir() {
|
||||
repository.setBasedir(new File("target/testBase"));
|
||||
assertThat(repository.getBasedir().toString(), containsString("target/testBase"));
|
||||
assertThat(repository.getRepos().get("test1").getBasedir().toString(),
|
||||
containsString("/test1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mappingRepo() {
|
||||
Environment environment = this.repository.findOne("test1-svc", "staging", "master");
|
||||
Environment environment = this.repository.findOne("test1-svc", "staging",
|
||||
"master");
|
||||
assertEquals(2, environment.getPropertySources().size());
|
||||
assertEquals(getUri("*test1*") + "/test1-svc.properties",
|
||||
environment.getPropertySources().get(0).getName());
|
||||
@@ -152,15 +180,70 @@ public class MultipleJGitEnvironmentRepositoryTests {
|
||||
assertVersion(environment);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldSetTransportConfigCallback() throws Exception {
|
||||
TransportConfigCallback mockCallback1 = mock(TransportConfigCallback.class);
|
||||
TransportConfigCallback mockCallback2 = mock(TransportConfigCallback.class);
|
||||
|
||||
PatternMatchingJGitEnvironmentRepository repo1 = createRepository("test1", "*test1*", "test1Uri");
|
||||
|
||||
PatternMatchingJGitEnvironmentRepository repo2 = createRepository("test2", "*test2*", "test2Uri");
|
||||
repo2.setTransportConfigCallback(mockCallback2);
|
||||
|
||||
Map<String, PatternMatchingJGitEnvironmentRepository> repos = new HashMap<>();
|
||||
repos.put("test1", repo1);
|
||||
repos.put("test2", repo2);
|
||||
|
||||
this.repository.setRepos(repos);
|
||||
this.repository.setTransportConfigCallback(mockCallback1);
|
||||
this.repository.afterPropertiesSet();
|
||||
|
||||
assertEquals(repo1.getTransportConfigCallback(), mockCallback1);
|
||||
assertEquals(repo2.getTransportConfigCallback(), mockCallback2);
|
||||
}
|
||||
|
||||
@Test
|
||||
// test for gh-700
|
||||
public void basedirCreatedIfNotExists() throws Exception {
|
||||
Path tempDir = Files.createTempDirectory("basedirCreatedTest");
|
||||
File parent = new File(tempDir.toFile(), "parent");
|
||||
File basedir = new File(parent, "basedir");
|
||||
this.repository.setBasedir(basedir);
|
||||
|
||||
assertThat(basedir).doesNotExist();
|
||||
|
||||
this.repository.afterPropertiesSet();
|
||||
|
||||
assertThat(basedir).exists();
|
||||
}
|
||||
|
||||
@Test
|
||||
// test for gh-700
|
||||
public void exceptionThrownIfBasedirDoesnotExistAndCannotBeCreated() throws Exception {
|
||||
File basedir = mock(File.class);
|
||||
File absoluteBasedir = mock(File.class);
|
||||
when(basedir.getAbsoluteFile()).thenReturn(absoluteBasedir);
|
||||
|
||||
when(absoluteBasedir.exists()).thenReturn(false);
|
||||
when(absoluteBasedir.mkdir()).thenReturn(false);
|
||||
|
||||
this.repository.setBasedir(basedir);
|
||||
|
||||
this.exception.expect(IllegalStateException.class);
|
||||
this.exception.expectMessage("Basedir does not exist and can not be created:");
|
||||
|
||||
this.repository.afterPropertiesSet();
|
||||
}
|
||||
|
||||
private String getUri(String pattern) {
|
||||
String uri = null;
|
||||
|
||||
Map<String, PatternMatchingJGitEnvironmentRepository> repoMappings = this.repository.getRepos();
|
||||
Map<String, PatternMatchingJGitEnvironmentRepository> repoMappings = this.repository
|
||||
.getRepos();
|
||||
|
||||
for (PatternMatchingJGitEnvironmentRepository repo : repoMappings.values()) {
|
||||
String[] mappingPattern = repo.getPattern();
|
||||
if (mappingPattern != null && mappingPattern.length!=0) {
|
||||
if (mappingPattern != null && mappingPattern.length != 0) {
|
||||
uri = repo.getUri();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
* Copyright 2013-2017 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.
|
||||
@@ -15,21 +15,21 @@
|
||||
*/
|
||||
package org.springframework.cloud.config.server.environment;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.WebApplicationType;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.cloud.config.environment.Environment;
|
||||
import org.springframework.cloud.config.server.environment.SearchPathLocator.Locations;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* @author Spencer Gibb
|
||||
*
|
||||
* @author Venil Noronha
|
||||
*/
|
||||
public class NativeEnvironmentRepositoryTests {
|
||||
|
||||
@@ -165,4 +165,28 @@ public class NativeEnvironmentRepositoryTests {
|
||||
environment.getPropertySources().get(0).getSource().get("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void locationAddLabelLocations() {
|
||||
this.repository.setSearchLocations("classpath:/test/dev/");
|
||||
Environment environment = this.repository.findOne("foo", "development", "ignore");
|
||||
assertEquals(2, environment.getPropertySources().size());
|
||||
assertNotEquals("dev_bar", environment.getPropertySources().get(0).getSource().get("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void locationDontAddLabelLocations() {
|
||||
this.repository.setSearchLocations("classpath:/test/dev/");
|
||||
this.repository.setAddLabelLocations(false);
|
||||
Environment environment = this.repository.findOne("foo", "development", "ignore");
|
||||
assertEquals(1, environment.getPropertySources().size());
|
||||
assertEquals("dev_bar", environment.getPropertySources().get(0).getSource().get("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void locationNoDuplicates() {
|
||||
this.repository.setSearchLocations("classpath:/test/{profile}", "classpath:/test/dev");
|
||||
Locations locations = this.repository.getLocations("foo", "dev", null);
|
||||
assertEquals(1, locations.getLocations().length);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,5 +3,11 @@ spring:
|
||||
config:
|
||||
server:
|
||||
git:
|
||||
uri: file:./target/repos/config-repo
|
||||
bootstrap: true
|
||||
uri: file:./target/repos/encrypt-repo
|
||||
bootstrap: true
|
||||
encrypt:
|
||||
key-store:
|
||||
location: classpath:server.jks
|
||||
password: letmein
|
||||
secret: changeme
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
info:
|
||||
foo: bar
|
||||
|
||||
---
|
||||
spring:
|
||||
profiles: encrypt
|
||||
config:
|
||||
foo: '{cipher}{key:mytestkey}AQCohs2V6P8/UiG6a4TF/CZTCBdt5Q7wvNvcyf6vs2ByK2ZYSM77Nu0sOAduxUpMbVwJ/syecmkIXR+hU3EfT2uqPieA7/v5n33ppqIQ9JAt5JggdYIGe+wX25zU3DTXOOJdAAMzNX+zjOVyCh0QtmJf/kFslg6NqQq0E+kSg3zBi3AnkKj5BLnLIxkjxzKA4mnDXpSm7ekLZZP2iQSYSW/82AC7UOLLzTqwInMI3tJLW1e9Ne+LDsjmSxA+nkK9zhidtXPwb/SPaNF74cJCEf9mgzzKYwJlwqChLzJt8UQ1jHwRc8B6FufmizUHSp27nxdtVB4HMqh3nNsMCy137Ces58T09ZS/y/cYNRxcFbp78MHFHUqAgbC0B/p5t6h4XbQ='
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
foo: bar
|
||||
@@ -0,0 +1 @@
|
||||
Add encrypted property
|
||||
@@ -0,0 +1,2 @@
|
||||
7df4a26d5437d9d4090cd5809967f870444cde8f not-for-merge branch 'raw' of dsyer@localhost:/home/dsyer/dev/platform/config/spring-platform-config-server/target/test-classes/config-repo
|
||||
7df4a26d5437d9d4090cd5809967f870444cde8f not-for-merge tag 'foo' of dsyer@localhost:/home/dsyer/dev/platform/config/spring-platform-config-server/target/test-classes/config-repo
|
||||
@@ -0,0 +1 @@
|
||||
ref: refs/heads/master
|
||||
@@ -0,0 +1,5 @@
|
||||
[core]
|
||||
repositoryformatversion = 0
|
||||
filemode = true
|
||||
logallrefupdates = true
|
||||
[branch "raw"]
|
||||
@@ -0,0 +1,3 @@
|
||||
1 1
|
||||
7df4a26d5437d9d4090cd5809967f870444cde8f 9f01fb972bc9617e4ea59f5c8ee3ceb5ff515cd0 9f01fb972bc9617e4ea59f5c8ee3ceb5ff515cd0
|
||||
1
|
||||
Binary file not shown.
@@ -0,0 +1,7 @@
|
||||
0000000000000000000000000000000000000000 7df4a26d5437d9d4090cd5809967f870444cde8f Dave Syer <dsyer@gopivotal.com> 1406860717 -0700
|
||||
7df4a26d5437d9d4090cd5809967f870444cde8f 9f01fb972bc9617e4ea59f5c8ee3ceb5ff515cd0 Ryan Baxter <rbaxter@pivotal.io> 1481905383 -0500 checkout: moving from raw to master
|
||||
9f01fb972bc9617e4ea59f5c8ee3ceb5ff515cd0 7df4a26d5437d9d4090cd5809967f870444cde8f Ryan Baxter <rbaxter@pivotal.io> 1481905407 -0500 checkout: moving from master to raw
|
||||
7df4a26d5437d9d4090cd5809967f870444cde8f 7df4a26d5437d9d4090cd5809967f870444cde8f Ryan Baxter <rbaxter@pivotal.io> 1481905544 -0500 checkout: moving from raw to composite
|
||||
7df4a26d5437d9d4090cd5809967f870444cde8f 7df4a26d5437d9d4090cd5809967f870444cde8f Ryan Baxter <rbaxter@pivotal.io> 1481905552 -0500 checkout: moving from composite to raw
|
||||
7df4a26d5437d9d4090cd5809967f870444cde8f 9f01fb972bc9617e4ea59f5c8ee3ceb5ff515cd0 Dave Syer <dsyer@pivotal.io> 1498491043 +0100 checkout: moving from raw to master
|
||||
9f01fb972bc9617e4ea59f5c8ee3ceb5ff515cd0 ad5e0cb7036ed11ddd4b7be6ed86ad3565c8a3fc Dave Syer <dsyer@pivotal.io> 1498491468 +0100 commit: Add encrypted property
|
||||
@@ -0,0 +1 @@
|
||||
0000000000000000000000000000000000000000 7df4a26d5437d9d4090cd5809967f870444cde8f Ryan Baxter <rbaxter@pivotal.io> 1481905474 -0500 branch: Created from raw
|
||||
@@ -0,0 +1,2 @@
|
||||
0000000000000000000000000000000000000000 9f01fb972bc9617e4ea59f5c8ee3ceb5ff515cd0 Dave Syer <dsyer@gopivotal.com> 1406860776 -0700 branch: Created from 9f01fb972bc9617e4ea59f5c8ee3ceb5ff515cd0
|
||||
9f01fb972bc9617e4ea59f5c8ee3ceb5ff515cd0 ad5e0cb7036ed11ddd4b7be6ed86ad3565c8a3fc Dave Syer <dsyer@pivotal.io> 1498491468 +0100 commit: Add encrypted property
|
||||
@@ -0,0 +1 @@
|
||||
0000000000000000000000000000000000000000 7df4a26d5437d9d4090cd5809967f870444cde8f Dave Syer <dsyer@gopivotal.com> 1406860717 -0700
|
||||
Binary file not shown.
@@ -0,0 +1,4 @@
|
||||
x<01><>M
|
||||
<EFBFBD>0<10>]<5D><14>$<24><><EFBFBD>o<> <09><><0B> 1z{<7B>7p<37><16>{<1F><><EFBFBD><EFBFBD>
|
||||
<EFBFBD><EFBFBD>Ze<06><>P<05>+G<><47>D<EFBFBD>v<08>GJ<47>8i#<23><><EFBFBD>6pIb
|
||||
<EFBFBD><EFBFBD><EFBFBD>ZV<5A><56>K<EFBFBD>&摸[<5B>FMQ
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
|
||||
7df4a26d5437d9d4090cd5809967f870444cde8f
|
||||
@@ -0,0 +1 @@
|
||||
ad5e0cb7036ed11ddd4b7be6ed86ad3565c8a3fc
|
||||
@@ -0,0 +1 @@
|
||||
7df4a26d5437d9d4090cd5809967f870444cde8f
|
||||
@@ -0,0 +1 @@
|
||||
7df4a26d5437d9d4090cd5809967f870444cde8f
|
||||
@@ -0,0 +1 @@
|
||||
foo: app
|
||||
Reference in New Issue
Block a user