Merge remote-tracking branch 'origin/main' into simlify-encryption-config-for-aot

This commit is contained in:
Olga Maciaszek-Sharma
2022-09-28 12:57:15 +02:00
57 changed files with 176 additions and 134 deletions

View File

@@ -1432,10 +1432,12 @@ NOTE: The `--key` argument is mandatory (despite having a `--` prefix).
=== Key Management
The Config Server can use a symmetric (shared) key or an asymmetric one (RSA key pair).
The asymmetric choice is superior in terms of security, but it is often more convenient to use a symmetric key since it is a single property value to configure in the `bootstrap.properties`.
The asymmetric choice is superior in terms of security, but it is often more convenient to use a symmetric key since it is a single property value to configure in the `application.properties`.
To configure a symmetric key, you need to set `encrypt.key` to a secret String (or use the `ENCRYPT_KEY` environment variable to keep it out of plain-text configuration files).
NOTE: If you include `spring-cloud-starter-bootstrap` on the classpath or set `spring.cloud.bootstrap.enabled=true` as a system property, you will need to set `encrypt.key` in `bootstrap.properties`.
NOTE: You cannot configure an asymmetric key using `encrypt.key`.
To configure an asymmetric key use a keystore (e.g. as

20
pom.xml
View File

@@ -30,10 +30,8 @@
<spring-cloud-commons.version>4.0.0-SNAPSHOT</spring-cloud-commons.version>
<aws-java-sdk.version>2.17.195</aws-java-sdk.version>
<google-api-services-iam.version>v1-rev20201112-1.30.10</google-api-services-iam.version>
<testcontainers.version>1.16.2</testcontainers.version>
<testcontainers.version>1.17.3</testcontainers.version>
<wiremock.version>2.31.0</wiremock.version>
<micrometer.version>1.10.0-M3</micrometer.version>
<micrometer-tracing.version>1.0.0-M6</micrometer-tracing.version>
<maven-checkstyle-plugin.failsOnError>true</maven-checkstyle-plugin.failsOnError>
<maven-checkstyle-plugin.failsOnViolation>true
</maven-checkstyle-plugin.failsOnViolation>
@@ -106,23 +104,9 @@
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-bom</artifactId>
<version>${micrometer.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bom</artifactId>
<version>${micrometer-tracing.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock-jre8</artifactId>
<artifactId>wiremock-jre8-standalone</artifactId>
<version>${wiremock.version}</version>
</dependency>
</dependencies>

View File

@@ -1,6 +1,3 @@
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.config.client.ConfigClientAutoConfiguration
# Bootstrap components
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
org.springframework.cloud.config.client.ConfigServiceBootstrapConfiguration,\

View File

@@ -0,0 +1 @@
org.springframework.cloud.config.client.ConfigClientAutoConfiguration

View File

@@ -108,22 +108,16 @@ public class PropertyPathEndpoint implements ApplicationEventPublisherAware {
String stem = StringUtils.stripFilenameExtension(StringUtils.getFilename(StringUtils.cleanPath(path)));
// TODO: correlate with service registry
int index = stem.indexOf("-");
while (index >= 0) {
String name = stem.substring(0, index);
String profile = stem.substring(index + 1);
if ("application".equals(name)) {
services.add("*:" + profile);
}
else if (!name.startsWith("application")) {
services.add(name + ":" + profile);
}
index = stem.indexOf("-", index + 1);
}
String name = stem;
if (index > 0) {
name = stem.substring(0, index);
}
// foo.properties is targeted at the foo application,
// while application.properties is targeted at all applications
if ("application".equals(name)) {
services.add("*");
}
else if (!name.startsWith("application")) {
else {
services.add(name);
}
}

View File

@@ -1,3 +0,0 @@
# Autoconfiguration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.config.monitor.EnvironmentMonitorAutoConfiguration

View File

@@ -0,0 +1 @@
org.springframework.cloud.config.monitor.EnvironmentMonitorAutoConfiguration

View File

@@ -72,7 +72,7 @@ public class PropertyPathEndpointTests {
public void testNotifyAllWithProfile() {
assertThat(this.endpoint
.notifyByPath(new HttpHeaders(), Collections.singletonMap("path", "application-local.yml")).toString())
.isEqualTo("[*:local]");
.isEqualTo("[*]");
}
@Test
@@ -92,13 +92,13 @@ public class PropertyPathEndpointTests {
@Test
public void testNotifyOneWithProfile() {
assertThat(this.endpoint.notifyByPath(new HttpHeaders(), Collections.singletonMap("path", "foo-local.yml"))
.toString()).isEqualTo("[foo:local, foo-local]");
.toString()).isEqualTo("[foo]");
}
@Test
public void testNotifyMultiDash() {
assertThat(this.endpoint.notifyByPath(new HttpHeaders(), Collections.singletonMap("path", "foo-local-dev.yml"))
.toString()).isEqualTo("[foo:local-dev, foo-local:dev, foo-local-dev]");
.toString()).isEqualTo("[foo]");
}
}

View File

@@ -53,7 +53,8 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
// config
// server on the classpath we need to set it explicitly
properties = { "spring.cloud.config.enabled:true", "", "spring.config.use-legacy-processing=true",
"management.security.enabled=false", "management.endpoints.web.exposure.include=*" },
"management.security.enabled=false", "management.endpoints.web.exposure.include=*",
"management.endpoint.env.show-values=ALWAYS" },
webEnvironment = RANDOM_PORT)
public class ApplicationBootstrapTests {

View File

@@ -44,7 +44,7 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
properties = { "spring.cloud.config.enabled:true",
// FIXME: configdata why is this needed here?
"spring.config.use-legacy-processing=true", "management.security.enabled=false",
"management.endpoints.web.exposure.include=*" },
"management.endpoints.web.exposure.include=*", "management.endpoint.env.show-values=ALWAYS" },
webEnvironment = RANDOM_PORT)
public class ApplicationTests {

View File

@@ -42,7 +42,8 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
// Normally spring.cloud.config.enabled:true is the default but since we have the
// config server on the classpath we need to set it explicitly
properties = { "spring.cloud.config.enabled=true", "spring.config.import=configserver:",
"management.security.enabled=false", "management.endpoints.web.exposure.include=*" },
"management.security.enabled=false", "management.endpoints.web.exposure.include=*",
"management.endpoint.env.show-values=ALWAYS" },
webEnvironment = RANDOM_PORT)
public class ConfigDataIntegrationTests {

View File

@@ -45,7 +45,7 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
// hence no spring.config.import here and config name change
properties = { "spring.application.name=profilesample", "spring.cloud.config.enabled=true",
"spring.config.name=orderingtest", "management.security.enabled=false", "spring.profiles.active=dev",
"management.endpoints.web.exposure.include=*" },
"management.endpoints.web.exposure.include=*", "management.endpoint.env.show-values=ALWAYS" },
webEnvironment = RANDOM_PORT)
public class ConfigDataOrderingIntegrationTests {

View File

@@ -53,7 +53,7 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
properties = { "spring.application.name=retryapp", "spring.cloud.config.fail-fast=true",
"spring.cloud.config.enabled=true", "spring.config.import=configserver:",
"management.security.enabled=false", "management.endpoints.web.exposure.include=*",
"logging.level.org.springframework.retry=TRACE" },
"logging.level.org.springframework.retry=TRACE", "management.endpoint.env.show-values=ALWAYS" },
webEnvironment = RANDOM_PORT)
public class ConfigDataRetryIntegrationTests {

View File

@@ -179,7 +179,7 @@
</dependency>
<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock-jre8</artifactId>
<artifactId>wiremock-jre8-standalone</artifactId>
<scope>test</scope>
</dependency>
<dependency>

View File

@@ -39,7 +39,7 @@ import org.springframework.util.StringUtils;
* Default text encryption auto-configuration.
*
* @author Olga Maciaszek-Sharma
* @since 3.1.2
* @since 4.0.0
*/
@Configuration(proxyBeanMethods = false)
@AutoConfigureAfter(RsaEncryptionAutoConfiguration.class)

View File

@@ -30,7 +30,7 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.encrypt.TextEncryptor;
/**
* Auto-configuration for text encryptors and environment encryptors (non-web stuff).
* Autoconfiguration for text encryptors and environment encryptors (non-web stuff).
* Users can provide beans of the same type as any or all of the beans defined here in
* application code to override the default behaviour.
*

View File

@@ -31,10 +31,10 @@ import org.springframework.security.rsa.crypto.RsaAlgorithm;
import org.springframework.security.rsa.crypto.RsaSecretEncryptor;
/**
* Auto-configuration for RSA encryption.
* Autoconfiguration for RSA encryption.
*
* @author Olga Maciaszek-Sharma
* @since 3.1.2
* @since 4.0.0
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(prefix = "encrypt.key-store", value = "location")

View File

@@ -130,29 +130,37 @@ public class AwsS3EnvironmentRepository implements EnvironmentRepository, Ordere
private S3ConfigFile getS3ConfigFile(String keyPrefix) {
try {
final ResponseInputStream<GetObjectResponse> responseInputStream = s3Client
.getObject(GetObjectRequest.builder().bucket(bucketName).key(keyPrefix + ".properties").build());
final ResponseInputStream<GetObjectResponse> responseInputStream = getObject(keyPrefix + ".properties");
return new PropertyS3ConfigFile(responseInputStream.response().versionId(), responseInputStream);
}
catch (Exception eProperties) {
try {
final ResponseInputStream<GetObjectResponse> responseInputStream = s3Client
.getObject(GetObjectRequest.builder().bucket(bucketName).key(keyPrefix + ".yml").build());
final ResponseInputStream<GetObjectResponse> responseInputStream = getObject(keyPrefix + ".yml");
return new YamlS3ConfigFile(responseInputStream.response().versionId(), responseInputStream);
}
catch (Exception eYaml) {
catch (Exception eYml) {
try {
final ResponseInputStream<GetObjectResponse> responseInputStream = s3Client
.getObject(GetObjectRequest.builder().bucket(bucketName).key(keyPrefix + ".json").build());
return new JsonS3ConfigFile(responseInputStream.response().versionId(), responseInputStream);
final ResponseInputStream<GetObjectResponse> responseInputStream = getObject(keyPrefix + ".yaml");
return new YamlS3ConfigFile(responseInputStream.response().versionId(), responseInputStream);
}
catch (Exception eJson) {
return null;
catch (Exception eYaml) {
try {
final ResponseInputStream<GetObjectResponse> responseInputStream = getObject(
keyPrefix + ".json");
return new JsonS3ConfigFile(responseInputStream.response().versionId(), responseInputStream);
}
catch (Exception eJson) {
return null;
}
}
}
}
}
private ResponseInputStream<GetObjectResponse> getObject(String key) throws Exception {
return s3Client.getObject(GetObjectRequest.builder().bucket(bucketName).key(key).build());
}
@Override
public Locations getLocations(String application, String profiles, String label) {
String baseLocation = AWS_S3_RESOURCE_SCHEME + bucketName + PATH_SEPARATOR + application;

View File

@@ -18,6 +18,7 @@ package org.springframework.cloud.config.server.environment;
import io.micrometer.common.docs.KeyName;
import io.micrometer.observation.Observation;
import io.micrometer.observation.ObservationConvention;
import io.micrometer.observation.docs.DocumentedObservation;
enum DocumentedConfigObservation implements DocumentedObservation {
@@ -27,7 +28,7 @@ enum DocumentedConfigObservation implements DocumentedObservation {
*/
ENVIRONMENT_REPOSITORY {
@Override
public Class<? extends Observation.ObservationConvention<? extends Observation.Context>> getDefaultConvention() {
public Class<? extends ObservationConvention<? extends Observation.Context>> getDefaultConvention() {
return ObservationEnvironmentRepositoryObservationConvention.class;
}
@@ -54,7 +55,7 @@ enum DocumentedConfigObservation implements DocumentedObservation {
*/
ENVIRONMENT_CLASS {
@Override
public String getKeyName() {
public String asString() {
return "spring.cloud.config.environment.class";
}
},
@@ -64,7 +65,7 @@ enum DocumentedConfigObservation implements DocumentedObservation {
*/
PROFILE {
@Override
public String getKeyName() {
public String asString() {
return "spring.cloud.config.environment.profile";
}
},
@@ -74,7 +75,7 @@ enum DocumentedConfigObservation implements DocumentedObservation {
*/
LABEL {
@Override
public String getKeyName() {
public String asString() {
return "spring.cloud.config.environment.label";
}
},
@@ -84,7 +85,7 @@ enum DocumentedConfigObservation implements DocumentedObservation {
*/
APPLICATION {
@Override
public String getKeyName() {
public String asString() {
return "spring.cloud.config.environment.application";
}
}

View File

@@ -103,14 +103,12 @@ public class EnvironmentController {
this.acceptEmpty = acceptEmpty;
}
@GetMapping(path = "/{name}/{profiles:(?!.*\\b\\.(?:ya?ml|properties|json)\\b).*}",
produces = MediaType.APPLICATION_JSON_VALUE)
@GetMapping(path = "/{name}/{profiles:[^\\.]*}", produces = MediaType.APPLICATION_JSON_VALUE)
public Environment defaultLabel(@PathVariable String name, @PathVariable String profiles) {
return getEnvironment(name, profiles, null, false);
}
@GetMapping(path = "/{name}/{profiles:(?!.*\\b\\.(?:ya?ml|properties|json)\\b).*}",
produces = EnvironmentMediaType.V2_JSON)
@GetMapping(path = "/{name}/{profiles:[^\\.]*}", produces = EnvironmentMediaType.V2_JSON)
public Environment defaultLabelIncludeOrigin(@PathVariable String name, @PathVariable String profiles) {
return getEnvironment(name, profiles, null, true);
}
@@ -464,14 +462,14 @@ public class EnvironmentController {
}
else {
switch (this.propertyKey.charAt(this.currentPos)) {
case '.':
this.valueType = NodeType.MAP;
break;
case '[':
this.valueType = NodeType.ARRAY;
break;
default:
throw new IllegalArgumentException("Invalid key: " + this.propertyKey);
case '.':
this.valueType = NodeType.MAP;
break;
case '[':
this.valueType = NodeType.ARRAY;
break;
default:
throw new IllegalArgumentException("Invalid key: " + this.propertyKey);
}
}
return index;

View File

@@ -32,7 +32,6 @@ import java.util.stream.Collectors;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.eclipse.jgit.transport.http.HttpConnection;
import org.eclipse.jgit.transport.http.apache.HttpClientConnection;
@@ -70,7 +69,16 @@ public class HttpClientConfigurableHttpConnectionFactory implements Configurable
@Override
public HttpConnection create(URL url, Proxy proxy) throws IOException {
return new HttpClientConnection(url.toString(), null, lookupHttpClientBuilder(url).build());
HttpClientBuilder builder = lookupHttpClientBuilder(url);
if (builder != null) {
return new HttpClientConnection(url.toString(), null, builder.build());
}
else {
/*
* No matching builder found: let jGit handle the creation of the HttpClient
*/
return new HttpClientConnection(url.toString());
}
}
private void addHttpClient(JGitEnvironmentProperties properties) throws GeneralSecurityException {
@@ -99,7 +107,7 @@ public class HttpClientConfigurableHttpConnectionFactory implements Configurable
if (builderMap.isEmpty()) {
this.log.warn(String.format("No custom http config found for URL: %s", url));
return HttpClients.custom();
return null;
}
if (builderMap.size() > 1) {
/*
@@ -118,7 +126,7 @@ public class HttpClientConfigurableHttpConnectionFactory implements Configurable
"More than one git repo URL template matched URL:"
+ " %s, proxy and skipSslValidation config won't be applied. Matched templates: %s",
url, builderMap.keySet().stream().collect(Collectors.joining(", "))));
return HttpClients.custom();
return null;
}
return new ArrayList<>(builderMap.values()).get(0);
}

View File

@@ -726,7 +726,7 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
}
List<Ref> branches = command.call();
for (Ref ref : branches) {
if (ref.getName().endsWith("/" + label)) {
if (ref.getName().equals("refs/heads/" + label) || ref.getName().equals("refs/remotes/origin/" + label)) {
return true;
}
}

View File

@@ -270,6 +270,9 @@ public class NativeEnvironmentRepository implements EnvironmentRepository, Searc
locations = new String[] { matcher.group(2) };
}
}
name = name.replace("\\", "/"); // change windows path '\' into '/'
name = name.replaceAll("\\[(?=\\w:)", "[/"); // change [D:/path] into
// [/D:/path]
name = name.replace("applicationConfig: [", "");
name = name.replace("file [", "file:");
name = name.replace("class path resource [", "classpath:/");

View File

@@ -19,6 +19,7 @@ package org.springframework.cloud.config.server.environment;
import io.micrometer.common.KeyValues;
import io.micrometer.common.docs.KeyName;
import io.micrometer.observation.Observation;
import io.micrometer.observation.ObservationConvention;
import org.springframework.util.StringUtils;
@@ -29,7 +30,7 @@ import org.springframework.util.StringUtils;
* @since 4.0.0
*/
class ObservationEnvironmentRepositoryObservationConvention
implements Observation.ObservationConvention<ObservationEnvironmentRepositoryContext> {
implements ObservationConvention<ObservationEnvironmentRepositoryContext> {
@Override
public KeyValues getLowCardinalityKeyValues(ObservationEnvironmentRepositoryContext context) {
@@ -46,7 +47,7 @@ class ObservationEnvironmentRepositoryObservationConvention
private KeyValues appendIfPresent(KeyValues keyValues, KeyName profile, String value) {
if (StringUtils.hasText(value)) {
keyValues = keyValues.and(profile.of(value));
keyValues = keyValues.and(profile.withValue(value));
}
return keyValues;
}

View File

@@ -46,12 +46,12 @@ public final class VaultKvAccessStrategyFactory {
public static VaultKvAccessStrategy forVersion(RestOperations rest, String baseUrl, int version, String pathToKey) {
switch (version) {
case 1:
return new V1VaultKvAccessStrategy(baseUrl, rest);
case 2:
return new V2VaultKvAccessStrategy(baseUrl, pathToKey, rest);
default:
throw new IllegalArgumentException("No support for given Vault k/v backend version " + version);
case 1:
return new V1VaultKvAccessStrategy(baseUrl, rest);
case 2:
return new V2VaultKvAccessStrategy(baseUrl, pathToKey, rest);
default:
throw new IllegalArgumentException("No support for given Vault k/v backend version " + version);
}
}

View File

@@ -32,16 +32,17 @@ public final class GoogleSecretManagerAccessStrategyFactory {
GoogleSecretManagerEnvironmentProperties properties) {
switch (properties.getVersion()) {
case 1:
try {
return new GoogleSecretManagerV1AccessStrategy(rest, configProvider, properties.getServiceAccount());
}
catch (Exception e) {
throw new RepositoryException("Cannot create service client", e);
}
default:
throw new IllegalArgumentException(
"No support for given Google Secret manager backend version " + properties.getVersion());
case 1:
try {
return new GoogleSecretManagerV1AccessStrategy(rest, configProvider,
properties.getServiceAccount());
}
catch (Exception e) {
throw new RepositoryException("Cannot create service client", e);
}
default:
throw new IllegalArgumentException(
"No support for given Google Secret manager backend version " + properties.getVersion());
}
}
@@ -50,11 +51,11 @@ public final class GoogleSecretManagerAccessStrategyFactory {
GoogleSecretManagerEnvironmentProperties properties, SecretManagerServiceClient client) {
switch (properties.getVersion()) {
case 1:
return new GoogleSecretManagerV1AccessStrategy(rest, configProvider, client);
default:
throw new IllegalArgumentException(
"No support for given Google Secret manager backend version " + properties.getVersion());
case 1:
return new GoogleSecretManagerV1AccessStrategy(rest, configProvider, client);
default:
throw new IllegalArgumentException(
"No support for given Google Secret manager backend version " + properties.getVersion());
}
}

View File

@@ -61,12 +61,12 @@ public class SpringVaultEnvironmentRepositoryFactory
int version = vaultProperties.getKvVersion();
switch (version) {
case 1:
return vaultTemplate.opsForKeyValue(backend, VaultKeyValueOperationsSupport.KeyValueBackend.KV_1);
case 2:
return vaultTemplate.opsForKeyValue(backend, VaultKeyValueOperationsSupport.KeyValueBackend.KV_2);
default:
throw new IllegalArgumentException("No support for given Vault k/v backend version " + version);
case 1:
return vaultTemplate.opsForKeyValue(backend, VaultKeyValueOperationsSupport.KeyValueBackend.KV_1);
case 2:
return vaultTemplate.opsForKeyValue(backend, VaultKeyValueOperationsSupport.KeyValueBackend.KV_2);
default:
throw new IllegalArgumentException("No support for given Vault k/v backend version " + version);
}
}

View File

@@ -65,6 +65,13 @@ public final class HttpClientSupport {
httpClientBuilder.setDefaultCredentialsProvider(new SystemDefaultCredentialsProvider());
}
/*
* According to https://git.eclipse.org/c/jgit/jgit.git/commit/?id=
* e17bfc96f293744cc5c0cef306e100f53d63bb3d jGit does its own redirect handling
* and disables HttpClient's redirect handing.
*/
httpClientBuilder.disableRedirectHandling();
int timeout = environmentProperties.getTimeout() * 1000;
return httpClientBuilder.setSSLContext(sslContextBuilder.build()).setDefaultRequestConfig(
RequestConfig.custom().setSocketTimeout(timeout).setConnectTimeout(timeout).build());

View File

@@ -1,20 +1,11 @@
# Bootstrap components
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
org.springframework.cloud.config.server.bootstrap.ConfigServerBootstrapConfiguration,\
org.springframework.cloud.config.server.config.DefaultTextEncryptionAutoConfiguration,\
org.springframework.cloud.config.server.config.RsaEncryptionAutoConfiguration,\
org.springframework.cloud.config.server.config.EncryptionAutoConfiguration
# Environment PostProcessor
org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.cloud.config.server.bootstrap.ConfigServerBootstrapApplicationListener
# Autoconfiguration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.config.server.config.ConfigServerAutoConfiguration,\
org.springframework.cloud.config.server.config.EncryptionAutoConfiguration,\
org.springframework.cloud.config.server.config.DefaultTextEncryptionAutoConfiguration,\
org.springframework.cloud.config.server.config.RsaEncryptionAutoConfiguration,\
org.springframework.cloud.config.server.config.VaultEncryptionAutoConfiguration
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.cloud.config.server.diagnostics.GitUriFailureAnalyzer

View File

@@ -0,0 +1,5 @@
org.springframework.cloud.config.server.config.ConfigServerAutoConfiguration
org.springframework.cloud.config.server.config.EncryptionAutoConfiguration
org.springframework.cloud.config.server.config.DefaultTextEncryptionAutoConfiguration
org.springframework.cloud.config.server.config.RsaEncryptionAutoConfiguration
org.springframework.cloud.config.server.config.VaultEncryptionAutoConfiguration

View File

@@ -115,6 +115,15 @@ public class AwsS3EnvironmentRepositoryTests {
@Test
public void findYamlObject() throws UnsupportedEncodingException {
setupS3("foo-bar.yaml", yamlContent);
final Environment env = envRepo.findOne("foo", "bar", null);
assertExpectedEnvironment(env, "foo", null, null, 1, "bar");
}
@Test
public void findYmlObject() throws UnsupportedEncodingException {
setupS3("foo-bar.yml", yamlContent);
final Environment env = envRepo.findOne("foo", "bar", null);

View File

@@ -643,11 +643,11 @@ class EnvironmentControllerTests {
@Test
public void handleEnvironmentException() throws Exception {
when(EnvironmentControllerTests.this.repository.findOne(eq("exception"), eq("bad_syntax.ext"), any(),
when(EnvironmentControllerTests.this.repository.findOne(eq("exception"), eq("bad_syntax"), any(),
eq(false)))
.thenThrow(new FailedToConstructEnvironmentException("Cannot construct",
new RuntimeException("underlier")));
MvcResult result = this.mvc.perform(MockMvcRequestBuilders.get("/exception/bad_syntax.ext"))
MvcResult result = this.mvc.perform(MockMvcRequestBuilders.get("/exception/bad_syntax"))
.andExpect(MockMvcResultMatchers.status().is(500)).andReturn();
assertThat(result.getResponse().getErrorMessage()).isEqualTo("Cannot construct");
}

View File

@@ -198,10 +198,8 @@ public class HttpClientConfigurableHttpConnectionFactoryTest {
HttpConnection actualConnection = this.connectionFactory.create(
new URL(properties2.getUri().replace("{placeholder1}", "value1").replace("{placeholder2}", "value2")));
HttpClientBuilder expectedHttpClientBuilder = this.connectionFactory.httpClientBuildersByUri
.get(properties2.getUri());
HttpClientBuilder actualHttpClientBuilder = getActualHttpClientBuilder(actualConnection);
assertThat(actualHttpClientBuilder).isNotSameAs(expectedHttpClientBuilder);
HttpClient actualHttpClient = getActualHttpClient(actualConnection);
assertThat(actualHttpClient).isNull();
}
@Test

View File

@@ -230,6 +230,20 @@ public class JGitEnvironmentRepositoryTests {
assertThat(this.repository.getUri()).isEqualTo("git://localhost/foo");
}
@Test
public void testBranchEndsWithTag() throws IOException {
String uri = ConfigServerTestUtils.prepareLocalRepo("branch-with-slash-repo");
this.repository.setUri(uri);
// exists branch "feature/foo"
Environment environment = this.repository.findOne("bar", "staging", "feature/foo");
assertVersion(environment);
// try tag "foo"
environment = this.repository.findOne("bar", "staging", "foo");
assertThat(environment.getPropertySources().get(0).getSource().get("key")).isEqualTo("value from tag");
}
@Test
public void afterPropertiesSet_CloneOnStartTrue_CloneAndFetchCalled() throws Exception {
Git mockGit = mock(Git.class);
@@ -744,7 +758,7 @@ public class JGitEnvironmentRepositoryTests {
when(checkoutCommand.call()).thenReturn(ref);
when(listBranchCommand.call()).thenReturn(Arrays.asList(branch1Ref));
when(fetchCommand.call()).thenReturn(fetchResult);
when(branch1Ref.getName()).thenReturn("origin/master");
when(branch1Ref.getName()).thenReturn("refs/remotes/origin/master");
when(status.isClean()).thenReturn(true);
JGitEnvironmentRepository repo = new JGitEnvironmentRepository(this.environment,
@@ -1207,12 +1221,12 @@ public class JGitEnvironmentRepositoryTests {
// Mock master branch
Ref mockMasterRef = mock(Ref.class);
repositoryRefsList.add(mockMasterRef);
when(mockMasterRef.getName()).thenReturn("/master");
when(mockMasterRef.getName()).thenReturn("refs/remotes/origin/master");
// Mock release branch.
Ref mockReleaseRef = mock(Ref.class);
repositoryRefsList.add(mockReleaseRef);
when(mockReleaseRef.getName()).thenReturn("/release");
when(mockReleaseRef.getName()).thenReturn("refs/remotes/origin/release");
// Mock calls on list and checkout commands
when(mockListBranchCommand.call()).thenReturn(repositoryRefsList);
@@ -1261,7 +1275,7 @@ public class JGitEnvironmentRepositoryTests {
// Mock master branch
Ref mockMasterRef = mock(Ref.class);
repositoryRefsList.add(mockMasterRef);
when(mockMasterRef.getName()).thenReturn("/master");
when(mockMasterRef.getName()).thenReturn("refs/remotes/origin/master");
// Mock calls on list and checkout commands
when(mockListBranchCommand.call()).thenReturn(repositoryRefsList);

View File

@@ -49,8 +49,8 @@ public class RedisEnvironmentRepositoryIntegrationTests {
@DynamicPropertySource
static void containerProperties(DynamicPropertyRegistry registry) {
registry.add("spring.redis.host", redisContainer::getContainerIpAddress);
registry.add("spring.redis.port", redisContainer::getFirstMappedPort);
registry.add("spring.data.redis.host", redisContainer::getHost);
registry.add("spring.data.redis.port", redisContainer::getFirstMappedPort);
}
@Test

View File

@@ -45,7 +45,6 @@ import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
import static com.github.tomakehurst.wiremock.client.WireMock.get;
import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor;
import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
import static com.github.tomakehurst.wiremock.client.WireMock.verify;
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
@@ -77,7 +76,7 @@ public class HttpClientSupportTest {
wireMockProxyServer.start();
wireMockServer.start();
WireMock.configureFor("https", "localhost", wireMockServer.httpsPort());
stubFor(get("/test/proxy").willReturn(aResponse().withStatus(200)));
wireMockServer.stubFor(get("/test/proxy").willReturn(aResponse().withStatus(200)));
JGitEnvironmentProperties properties = new JGitEnvironmentProperties();
Map<ProxyHostProperties.ProxyForScheme, ProxyHostProperties> proxy = new HashMap<>();

View File

@@ -0,0 +1 @@
key: value from master

View File

@@ -0,0 +1 @@
ref: refs/heads/master

View File

@@ -0,0 +1,5 @@
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true

View File

@@ -0,0 +1 @@
Unnamed repository; edit this file 'description' to name the repository.

View File

@@ -0,0 +1,3 @@
0000000000000000000000000000000000000000 7a9804f8901709bdcf794c553805d5bc5188f821 woshikid <name.kid@gmail.com> 1663579538 +0800 commit (initial): tag
7a9804f8901709bdcf794c553805d5bc5188f821 915bd24aaf815120f2755ef4fc66404f5d37b383 woshikid <name.kid@gmail.com> 1663579645 +0800 commit: branch
915bd24aaf815120f2755ef4fc66404f5d37b383 08eb9e67a7225c302e3906a63cb9544e619fc804 woshikid <name.kid@gmail.com> 1663579718 +0800 commit: master

View File

@@ -0,0 +1 @@
0000000000000000000000000000000000000000 915bd24aaf815120f2755ef4fc66404f5d37b383 woshikid <name.kid@gmail.com> 1663579678 +0800 branch: Created from master

View File

@@ -0,0 +1,3 @@
0000000000000000000000000000000000000000 7a9804f8901709bdcf794c553805d5bc5188f821 woshikid <name.kid@gmail.com> 1663579538 +0800 commit (initial): tag
7a9804f8901709bdcf794c553805d5bc5188f821 915bd24aaf815120f2755ef4fc66404f5d37b383 woshikid <name.kid@gmail.com> 1663579645 +0800 commit: branch
915bd24aaf815120f2755ef4fc66404f5d37b383 08eb9e67a7225c302e3906a63cb9544e619fc804 woshikid <name.kid@gmail.com> 1663579718 +0800 commit: master

View File

@@ -0,0 +1,2 @@
x<01><>A
<EFBFBD>0E]<5D><14>J<><4A>LR(<28>U&ql<71><6C>@<40>x}sw<><07><><EFBFBD>j-fv<66>~<7E><>]2SB<53><1C>G<EFBFBD>.EVL.<2E>l<13>L<16>$<18><><EFBFBD><1D>m<EFBFBD><6D><<3C>

View File

@@ -0,0 +1 @@
915bd24aaf815120f2755ef4fc66404f5d37b383

View File

@@ -0,0 +1 @@
08eb9e67a7225c302e3906a63cb9544e619fc804

View File

@@ -0,0 +1 @@
7a9804f8901709bdcf794c553805d5bc5188f821