From 85053fc06a35011601db185f6e5b6542df2d2ecf Mon Sep 17 00:00:00 2001
From: Ryan Baxter <524254+ryanjbaxter@users.noreply.github.com>
Date: Mon, 14 Aug 2023 09:36:54 -0400
Subject: [PATCH 01/11] Upgrade jgit to 5.13.2.202306221912-r
---
spring-cloud-config-dependencies/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/spring-cloud-config-dependencies/pom.xml b/spring-cloud-config-dependencies/pom.xml
index 2d2a4221..280178c1 100644
--- a/spring-cloud-config-dependencies/pom.xml
+++ b/spring-cloud-config-dependencies/pom.xml
@@ -15,7 +15,7 @@
spring-cloud-config-dependencies
Spring Cloud Config Dependencies
- 5.13.1.202206130422-r
+ 5.13.2.202306221912-r
2.3.2
2.1.1.RELEASE
2.4.4
From 558545dbfbe20b03dc5394aeda4b2b9cb8e8e1ce Mon Sep 17 00:00:00 2001
From: Ryan Baxter <524254+ryanjbaxter@users.noreply.github.com>
Date: Thu, 2 Nov 2023 15:15:59 -0400
Subject: [PATCH 02/11] Fixing doc includes
---
README.adoc | 2 +-
docs/src/main/asciidoc/README.adoc | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/README.adoc b/README.adoc
index 2991a3d1..83062c93 100644
--- a/README.adoc
+++ b/README.adoc
@@ -264,7 +264,7 @@ The refresh endpoint reports that the "sample" property changed.
== Building
-:jdkversion: 17
+:jdkversion: 1.8
=== Basic Compile and Test
diff --git a/docs/src/main/asciidoc/README.adoc b/docs/src/main/asciidoc/README.adoc
index 0ee4204e..bcd2f7bc 100644
--- a/docs/src/main/asciidoc/README.adoc
+++ b/docs/src/main/asciidoc/README.adoc
@@ -60,7 +60,7 @@ The refresh endpoint reports that the "sample" property changed.
== Building
-include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/docs/src/main/asciidoc/building.adoc[]
+include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/3.1.x/docs/src/main/asciidoc/building.adoc[]
=== JCE
@@ -77,4 +77,4 @@ Extract the JCE files into the `JDK/jre/lib/security` folder for whichever versi
== Contributing
-include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/docs/src/main/asciidoc/contributing.adoc[]
+include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/3.1.x/docs/src/main/asciidoc/contributing.adoc[]
From 25a3655b194d6bdb4d114824beee7e0117ac3ecc Mon Sep 17 00:00:00 2001
From: Ryan Baxter
Date: Tue, 14 Nov 2023 14:39:36 -0500
Subject: [PATCH 03/11] Use config server uri from boostrap context if
discovery is enabled. Fixes #2338 (#2343)
Co-authored-by: Ryan Baxter <524254+ryanjbaxter@users.noreply.github.com>
---
.../client/ConfigServerConfigDataLoader.java | 36 +++++++++++++++----
.../ConfigServerConfigDataLoaderTests.java | 22 ++++++++++++
2 files changed, 52 insertions(+), 6 deletions(-)
diff --git a/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigServerConfigDataLoader.java b/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigServerConfigDataLoader.java
index ced0f6ef..7a4eda8a 100644
--- a/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigServerConfigDataLoader.java
+++ b/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigServerConfigDataLoader.java
@@ -265,8 +265,23 @@ public class ConfigServerConfigDataLoader implements ConfigDataLoader 1) {
+ String[] uris;
+ boolean discoveryEnabled = properties.getDiscovery().isEnabled();
+ ConfigClientProperties bootstrapConfigClientProperties = context.getBootstrapContext()
+ .get(ConfigClientProperties.class);
+ // In the case where discovery is enabled we need to extract the config server
+ // uris, username, and password
+ // from the properties from the context. These are set in
+ // ConfigServerInstanceMonitor.refresh which will only
+ // be called the first time we fetch configuration.
+ if (discoveryEnabled) {
+ uris = bootstrapConfigClientProperties.getUri();
+ }
+ else {
+ uris = properties.getUri();
+ }
+ int noOfUrls = uris.length;
+ if (uris.length > 1) {
logger.info("Multiple Config Server Urls found listed.");
}
@@ -284,10 +299,19 @@ public class ConfigServerConfigDataLoader implements ConfigDataLoader logger);
+ ClientHttpRequestFactory requestFactory = mock(ClientHttpRequestFactory.class);
+ RestTemplate restTemplate = new RestTemplate(requestFactory);
+ when(bootstrapContext.get(RestTemplate.class)).thenReturn(restTemplate);
+ ConfigClientProperties bootstrapConfigClientProperties = new ConfigClientProperties();
+ bootstrapConfigClientProperties.setDiscovery(discovery);
+ bootstrapConfigClientProperties.setUri(new String[] { "http://configservice:8888" });
+ when(bootstrapContext.get(ConfigClientProperties.class)).thenReturn(bootstrapConfigClientProperties);
+
+ mockRequestResponse(requestFactory, "http://configservice:8888", HttpStatus.OK);
+
+ assertThat(this.loader.load(context, resource)).isNotNull();
+ }
+
@Disabled
@Test
// TODO Enable once we have
From 613be430826b705a3cb352c03ec0d46bdb9a41b7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ondrej=20=C5=A0=C4=8Decina?=
Date: Wed, 15 Nov 2023 00:55:31 +0100
Subject: [PATCH 04/11] Do not fail retrieving secrets from Secrets Manager
when any secret is marked for deletion. (#2350)
Co-authored-by: Ondrej Scecina
---
...wsSecretsManagerEnvironmentRepository.java | 3 +-
...retsManagerEnvironmentRepositoryTests.java | 45 +++++++++++++++++++
2 files changed, 47 insertions(+), 1 deletion(-)
diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsSecretsManagerEnvironmentRepository.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsSecretsManagerEnvironmentRepository.java
index 0443b5e4..262c22fb 100644
--- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsSecretsManagerEnvironmentRepository.java
+++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsSecretsManagerEnvironmentRepository.java
@@ -28,6 +28,7 @@ import org.apache.commons.logging.LogFactory;
import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient;
import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest;
import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueResponse;
+import software.amazon.awssdk.services.secretsmanager.model.InvalidRequestException;
import software.amazon.awssdk.services.secretsmanager.model.ResourceNotFoundException;
import org.springframework.cloud.config.environment.Environment;
@@ -155,7 +156,7 @@ public class AwsSecretsManagerEnvironmentRepository implements EnvironmentReposi
}
}
}
- catch (ResourceNotFoundException | IOException e) {
+ catch (InvalidRequestException | ResourceNotFoundException | IOException e) {
log.debug(String.format(
"Skip adding propertySource. Unable to load secrets from AWS Secrets Manager for secretId=%s",
path), e);
diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/AwsSecretsManagerEnvironmentRepositoryTests.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/AwsSecretsManagerEnvironmentRepositoryTests.java
index 600aa08a..32691d99 100644
--- a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/AwsSecretsManagerEnvironmentRepositoryTests.java
+++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/AwsSecretsManagerEnvironmentRepositoryTests.java
@@ -42,6 +42,7 @@ import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient;
import software.amazon.awssdk.services.secretsmanager.model.CreateSecretRequest;
import software.amazon.awssdk.services.secretsmanager.model.CreateSecretResponse;
import software.amazon.awssdk.services.secretsmanager.model.DeleteSecretRequest;
+import software.amazon.awssdk.services.secretsmanager.model.RestoreSecretRequest;
import software.amazon.awssdk.services.secretsmanager.model.UpdateSecretVersionStageRequest;
import org.springframework.cloud.config.environment.Environment;
@@ -91,6 +92,8 @@ public class AwsSecretsManagerEnvironmentRepositoryTests {
private final List toBeRemoved = new ArrayList<>();
+ private final List markedForDeletion = new ArrayList<>();
+
private static Map getFooProperties() {
return new HashMap() {
{
@@ -237,6 +240,10 @@ public class AwsSecretsManagerEnvironmentRepositoryTests {
@AfterEach
public void cleanUp() {
+ markedForDeletion
+ .forEach(value -> smClient.restoreSecret(RestoreSecretRequest.builder().secretId(value).build()));
+ markedForDeletion.clear();
+
toBeRemoved.forEach(value -> smClient
.deleteSecret(DeleteSecretRequest.builder().secretId(value).forceDeleteWithoutRecovery(true).build()));
toBeRemoved.clear();
@@ -2502,6 +2509,36 @@ public class AwsSecretsManagerEnvironmentRepositoryTests {
assertThat(resultEnv).usingRecursiveComparison().withStrictTypeChecking().isEqualTo(environment);
}
+ @Test
+ public void testFindOneWithExistingApplicationAndNonExistingProfileAndNoDefaultProfileForFooMarkedForDeletion() {
+ String application = "foo";
+ String profile = randomAlphabetic(RandomUtils.nextInt(2, 25));
+ String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
+
+ String fooPropertiesName = "aws:secrets:/secret/foo/";
+ PropertySource fooProperties = new PropertySource(fooPropertiesName, getFooProperties());
+
+ String applicationDefaultPropertiesName = "aws:secrets:/secret/application-default/";
+ PropertySource applicationDefaultProperties = new PropertySource(applicationDefaultPropertiesName,
+ getApplicationDefaultProperties());
+
+ String applicationPropertiesName = "aws:secrets:/secret/application/";
+ PropertySource applicationProperties = new PropertySource(applicationPropertiesName,
+ getApplicationProperties());
+
+ Environment environment = new Environment(application, profiles, null, null, null);
+ environment.addAll(Arrays.asList(applicationDefaultProperties, fooProperties, applicationProperties));
+
+ putSecrets(environment);
+ deleteSecrets(environment);
+
+ Environment emptyEnvironment = new Environment(application, profiles, null, null, null);
+
+ Environment resultEnv = repository.findOne(application, profile, null);
+
+ assertThat(resultEnv).usingRecursiveComparison().withStrictTypeChecking().isEqualTo(emptyEnvironment);
+ }
+
@Test
public void factoryCustomizableWithRegion() {
AwsSecretsManagerEnvironmentRepositoryFactory factory = new AwsSecretsManagerEnvironmentRepositoryFactory(
@@ -2539,6 +2576,14 @@ public class AwsSecretsManagerEnvironmentRepositoryTests {
}
}
+ private void deleteSecrets(Environment environment) {
+ for (PropertySource ps : environment.getPropertySources()) {
+ String path = StringUtils.delete(ps.getName(), environmentProperties.getOrigin());
+ smClient.deleteSecret(DeleteSecretRequest.builder().secretId(path).recoveryWindowInDays(30L).build());
+ markedForDeletion.add(path);
+ }
+ }
+
private String getSecrets(PropertySource ps) {
Map map = (Map) ps.getSource();
try {
From 0b92d82a2b600558c8075398965fb55c2770bb2b Mon Sep 17 00:00:00 2001
From: Ryan Baxter
Date: Tue, 21 Nov 2023 15:23:27 -0500
Subject: [PATCH 05/11] Add support for random exponential backoff policy.
Fixes #2351 (#2353)
Co-authored-by: Ryan Baxter <524254+ryanjbaxter@users.noreply.github.com>
---
docs/src/main/asciidoc/spring-cloud-config.adoc | 1 +
.../cloud/config/client/RetryProperties.java | 13 +++++++++++++
.../cloud/config/client/RetryTemplateFactory.java | 6 +++---
...ConfigServerConfigDataLocationResolverTests.java | 2 ++
4 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/docs/src/main/asciidoc/spring-cloud-config.adoc b/docs/src/main/asciidoc/spring-cloud-config.adoc
index af52458e..ff78863b 100644
--- a/docs/src/main/asciidoc/spring-cloud-config.adoc
+++ b/docs/src/main/asciidoc/spring-cloud-config.adoc
@@ -1906,6 +1906,7 @@ First, you need to set `spring.cloud.config.fail-fast=true`.
Then you need to add `spring-retry` and `spring-boot-starter-aop` to your classpath.
The default behavior is to retry six times with an initial backoff interval of 1000ms and an exponential multiplier of 1.1 for subsequent backoffs.
You can configure these properties (and others) by setting the `spring.cloud.config.retry.*` configuration properties.
+To use a random exponential backoff policy set `spring.cloud.config.retry.useRandomPolicy` to `true`.
TIP: To take full control of the retry behavior and are using legacy bootstrap, add a `@Bean` of type `RetryOperationsInterceptor` with an ID of `configServerRetryInterceptor`.
Spring Retry has a `RetryInterceptorBuilder` that supports creating one.
diff --git a/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/RetryProperties.java b/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/RetryProperties.java
index 903f0c8b..7eb88e77 100644
--- a/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/RetryProperties.java
+++ b/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/RetryProperties.java
@@ -50,6 +50,11 @@ public class RetryProperties {
*/
int maxAttempts = 6;
+ /**
+ * Use a random exponential backoff policy.
+ */
+ boolean useRandomPolicy = false;
+
public long getInitialInterval() {
return this.initialInterval;
}
@@ -82,4 +87,12 @@ public class RetryProperties {
this.maxAttempts = maxAttempts;
}
+ public boolean isUseRandomPolicy() {
+ return this.useRandomPolicy;
+ }
+
+ public void setUseRandomPolicy(boolean useRandomPolicy) {
+ this.useRandomPolicy = useRandomPolicy;
+ }
+
}
diff --git a/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/RetryTemplateFactory.java b/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/RetryTemplateFactory.java
index 5aa2abbc..068ea985 100644
--- a/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/RetryTemplateFactory.java
+++ b/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/RetryTemplateFactory.java
@@ -39,9 +39,9 @@ public final class RetryTemplateFactory {
}
public static RetryTemplate create(RetryProperties properties, Log log) {
- RetryTemplate retryTemplate = RetryTemplate.builder().maxAttempts(properties.getMaxAttempts())
- .exponentialBackoff(properties.getInitialInterval(), properties.getMultiplier(),
- properties.getMaxInterval())
+ RetryTemplate retryTemplate = RetryTemplate
+ .builder().maxAttempts(properties.getMaxAttempts()).exponentialBackoff(properties.getInitialInterval(),
+ properties.getMultiplier(), properties.getMaxInterval(), properties.isUseRandomPolicy())
.build();
try {
field.set(retryTemplate, log);
diff --git a/spring-cloud-config-client/src/test/java/org/springframework/cloud/config/client/ConfigServerConfigDataLocationResolverTests.java b/spring-cloud-config-client/src/test/java/org/springframework/cloud/config/client/ConfigServerConfigDataLocationResolverTests.java
index 504050a8..f2f3c822 100644
--- a/spring-cloud-config-client/src/test/java/org/springframework/cloud/config/client/ConfigServerConfigDataLocationResolverTests.java
+++ b/spring-cloud-config-client/src/test/java/org/springframework/cloud/config/client/ConfigServerConfigDataLocationResolverTests.java
@@ -138,6 +138,7 @@ public class ConfigServerConfigDataLocationResolverTests {
assertThat(resource.getRetryProperties().getMaxInterval()).isEqualTo(defaultRetry.getMaxInterval());
assertThat(resource.getRetryProperties().getInitialInterval()).isEqualTo(defaultRetry.getInitialInterval());
assertThat(resource.getRetryProperties().getMultiplier()).isEqualTo(defaultRetry.getMultiplier());
+ assertThat(resource.getRetryProperties().isUseRandomPolicy()).isEqualTo(defaultRetry.isUseRandomPolicy());
}
@Test
@@ -158,6 +159,7 @@ public class ConfigServerConfigDataLocationResolverTests {
assertThat(resource.getRetryProperties().getMaxInterval()).isEqualTo(1500);
assertThat(resource.getRetryProperties().getInitialInterval()).isEqualTo(1100);
assertThat(resource.getRetryProperties().getMultiplier()).isEqualTo(1.2);
+ assertThat(resource.getRetryProperties().isUseRandomPolicy()).isEqualTo(false);
}
@Test
From ba4c2c56251883f98279acdefa93b08419209246 Mon Sep 17 00:00:00 2001
From: Ryan Baxter <524254+ryanjbaxter@users.noreply.github.com>
Date: Tue, 21 Nov 2023 15:26:05 -0500
Subject: [PATCH 06/11] Adding documentation from merge
---
docs/modules/ROOT/pages/client.adoc | 1 +
1 file changed, 1 insertion(+)
diff --git a/docs/modules/ROOT/pages/client.adoc b/docs/modules/ROOT/pages/client.adoc
index 543a7708..f639805a 100644
--- a/docs/modules/ROOT/pages/client.adoc
+++ b/docs/modules/ROOT/pages/client.adoc
@@ -93,6 +93,7 @@ First, you need to set `spring.cloud.config.fail-fast=true`.
Then you need to add `spring-retry` and `spring-boot-starter-aop` to your classpath.
The default behavior is to retry six times with an initial backoff interval of 1000ms and an exponential multiplier of 1.1 for subsequent backoffs.
You can configure these properties (and others) by setting the `spring.cloud.config.retry.*` configuration properties.
+To use a random exponential backoff policy set `spring.cloud.config.retry.useRandomPolicy` to `true`.
TIP: To take full control of the retry behavior and are using legacy bootstrap, add a `@Bean` of type `RetryOperationsInterceptor` with an ID of `configServerRetryInterceptor`.
Spring Retry has a `RetryInterceptorBuilder` that supports creating one.
From 861ed6785e4a7eceacb123076062721e56ab0b40 Mon Sep 17 00:00:00 2001
From: Ryan Baxter
Date: Tue, 21 Nov 2023 15:27:17 -0500
Subject: [PATCH 07/11] Do not combine profiles when
spring.cloud.config.pofiles is set. (#2354)
Fixes #2349
---
.../ConfigServicePropertySourceLocator.java | 12 ++++--------
...ConfigServicePropertySourceLocatorTests.java | 17 +++++++++++++++++
2 files changed, 21 insertions(+), 8 deletions(-)
diff --git a/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigServicePropertySourceLocator.java b/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigServicePropertySourceLocator.java
index 5509a259..73ab8066 100644
--- a/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigServicePropertySourceLocator.java
+++ b/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigServicePropertySourceLocator.java
@@ -50,7 +50,6 @@ import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.retry.annotation.Retryable;
import org.springframework.util.Assert;
-import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException;
@@ -80,8 +79,7 @@ public class ConfigServicePropertySourceLocator implements PropertySourceLocator
}
/**
- * Combine properties from the config client properties and the active profiles from
- * the environment.
+ * Combine the active and default profiles from the environment.
* @param properties config client properties,
* @param environment application environment.
* @return A list of combined profiles.
@@ -89,10 +87,6 @@ public class ConfigServicePropertySourceLocator implements PropertySourceLocator
private List combineProfiles(ConfigClientProperties properties,
org.springframework.core.env.Environment environment) {
List combinedProfiles = new ArrayList<>();
- if (!ObjectUtils.isEmpty(properties.getProfile())) {
- combinedProfiles = Stream.of(properties.getProfile().split(",")).map(String::trim).filter(s -> !s.isEmpty())
- .collect(Collectors.toList());
- }
if (environment.getActiveProfiles().length > 0) {
List finalCombinedProfiles = combinedProfiles;
List filteredActiveProfiles = Stream.of(environment.getActiveProfiles())
@@ -109,7 +103,9 @@ public class ConfigServicePropertySourceLocator implements PropertySourceLocator
@Retryable(interceptor = "configServerRetryInterceptor")
public org.springframework.core.env.PropertySource> locate(org.springframework.core.env.Environment environment) {
ConfigClientProperties properties = this.defaultProperties.override(environment);
- properties.setProfile(String.join(",", combineProfiles(properties, environment)));
+ if (!StringUtils.hasText(properties.getProfile())) {
+ properties.setProfile(String.join(",", combineProfiles(properties, environment)));
+ }
if (StringUtils.startsWithIgnoreCase(properties.getName(), "application-")) {
InvalidApplicationNameException exception = new InvalidApplicationNameException(properties.getName());
diff --git a/spring-cloud-config-client/src/test/java/org/springframework/cloud/config/client/ConfigServicePropertySourceLocatorTests.java b/spring-cloud-config-client/src/test/java/org/springframework/cloud/config/client/ConfigServicePropertySourceLocatorTests.java
index 39d61edb..83bd5ff3 100644
--- a/spring-cloud-config-client/src/test/java/org/springframework/cloud/config/client/ConfigServicePropertySourceLocatorTests.java
+++ b/spring-cloud-config-client/src/test/java/org/springframework/cloud/config/client/ConfigServicePropertySourceLocatorTests.java
@@ -118,6 +118,17 @@ public class ConfigServicePropertySourceLocatorTests {
assertThat(this.locator.locateCollection(this.environment)).isNotNull();
}
+ @Test
+ public void overrideProfile() {
+ Environment body = new Environment("app", "override-profile");
+ body.add(new PropertySource("p1", new HashMap<>()));
+ mockRequestResponseWithProfile(new ResponseEntity<>(body, HttpStatus.OK), "override-profile");
+ this.locator.setRestTemplate(this.restTemplate);
+ TestPropertyValues.of("spring.cloud.config.profile:override-profile", "spring.profiles.active: foo")
+ .applyTo(this.environment);
+ assertThat(this.locator.locateCollection(this.environment).size()).isEqualTo(2);
+ }
+
@Test
public void sunnyDayWithLabelThatContainsASlash() {
Environment body = new Environment("app", "master");
@@ -358,6 +369,12 @@ public class ConfigServicePropertySourceLocatorTests {
ArgumentMatchers.eq(label))).thenReturn(response);
}
+ private void mockRequestResponseWithProfile(ResponseEntity> response, String profiles) {
+ Mockito.when(this.restTemplate.exchange(Mockito.any(String.class), Mockito.any(HttpMethod.class),
+ Mockito.any(HttpEntity.class), Mockito.any(Class.class), anyString(), ArgumentMatchers.eq(profiles)))
+ .thenReturn(response);
+ }
+
@SuppressWarnings("unchecked")
private void mockRequestResponseWithoutLabel(ResponseEntity> response) {
Mockito.when(this.restTemplate.exchange(Mockito.any(String.class), Mockito.any(HttpMethod.class),
From dc9d207d8065ddd9668cd2b97eaeff4d707bb61d Mon Sep 17 00:00:00 2001
From: buildmaster
Date: Wed, 22 Nov 2023 10:36:17 +0000
Subject: [PATCH 08/11] Bumping versions
---
README.adoc | 2 +-
docs/modules/ROOT/partials/_configprops.adoc | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/README.adoc b/README.adoc
index 3577a351..fcf46c26 100644
--- a/README.adoc
+++ b/README.adoc
@@ -71,7 +71,7 @@ The refresh endpoint reports that the "sample" property changed.
[[building]]
= Building
-:jdkversion: 1.8
+:jdkversion: 17
[[basic-compile-and-test]]
== Basic Compile and Test
diff --git a/docs/modules/ROOT/partials/_configprops.adoc b/docs/modules/ROOT/partials/_configprops.adoc
index e3090ac5..fd9f93cd 100644
--- a/docs/modules/ROOT/partials/_configprops.adoc
+++ b/docs/modules/ROOT/partials/_configprops.adoc
@@ -22,6 +22,7 @@
|spring.cloud.config.retry.max-attempts | `+++6+++` | Maximum number of attempts.
|spring.cloud.config.retry.max-interval | `+++2000+++` | Maximum interval for backoff.
|spring.cloud.config.retry.multiplier | `+++1.1+++` | Multiplier for next interval.
+|spring.cloud.config.retry.use-random-policy | `+++false+++` | Use a random exponential backoff policy.
|spring.cloud.config.send-state | `+++true+++` | Flag to indicate whether to send state. Default true.
|spring.cloud.config.tls | | TLS properties.
|spring.cloud.config.token | | Security Token passed thru to underlying environment repository.
From e8fe9d4fbaedabfa39ef1cb84022e7aacc46a739 Mon Sep 17 00:00:00 2001
From: buildmaster
Date: Wed, 22 Nov 2023 13:48:18 +0000
Subject: [PATCH 09/11] Bumping versions
---
README.adoc | 2 +-
docs/src/main/asciidoc/_configprops.adoc | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/README.adoc b/README.adoc
index cbac101d..076c8022 100644
--- a/README.adoc
+++ b/README.adoc
@@ -264,7 +264,7 @@ The refresh endpoint reports that the "sample" property changed.
== Building
-:jdkversion: 1.8
+:jdkversion: 17
=== Basic Compile and Test
diff --git a/docs/src/main/asciidoc/_configprops.adoc b/docs/src/main/asciidoc/_configprops.adoc
index e3090ac5..fd9f93cd 100644
--- a/docs/src/main/asciidoc/_configprops.adoc
+++ b/docs/src/main/asciidoc/_configprops.adoc
@@ -22,6 +22,7 @@
|spring.cloud.config.retry.max-attempts | `+++6+++` | Maximum number of attempts.
|spring.cloud.config.retry.max-interval | `+++2000+++` | Maximum interval for backoff.
|spring.cloud.config.retry.multiplier | `+++1.1+++` | Multiplier for next interval.
+|spring.cloud.config.retry.use-random-policy | `+++false+++` | Use a random exponential backoff policy.
|spring.cloud.config.send-state | `+++true+++` | Flag to indicate whether to send state. Default true.
|spring.cloud.config.tls | | TLS properties.
|spring.cloud.config.token | | Security Token passed thru to underlying environment repository.
From 8a409cd7d0dc05083a02474b7c95628c93f0cdf9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ondrej=20=C5=A0=C4=8Decina?=
Date: Wed, 29 Nov 2023 20:03:55 +0100
Subject: [PATCH 10/11] Do not set staging label when fetching the secret
values. (#2359)
* Do not set staging label when fetching the secret values.
* Add `ignoreLabel` documentation.
* Amend `ignoreLabel` documentation.
---------
Co-authored-by: Ondrej Scecina
---
.../main/asciidoc/spring-cloud-config.adoc | 16 +++++++
...wsSecretsManagerEnvironmentProperties.java | 13 +++++
...wsSecretsManagerEnvironmentRepository.java | 6 ++-
...retsManagerEnvironmentRepositoryTests.java | 48 +++++++++++++++++++
4 files changed, 82 insertions(+), 1 deletion(-)
diff --git a/docs/src/main/asciidoc/spring-cloud-config.adoc b/docs/src/main/asciidoc/spring-cloud-config.adoc
index ff78863b..6be14a2f 100644
--- a/docs/src/main/asciidoc/spring-cloud-config.adoc
+++ b/docs/src/main/asciidoc/spring-cloud-config.adoc
@@ -915,6 +915,21 @@ Note that if the default label is not set and a request does not define a label,
Note that if the staging label contains a slash (`/`), then the label in the HTTP URL should instead be specified with the special string `({special-string})` (to avoid ambiguity with other URL paths) the same way <<_git_backend,Git backend's section>> describes it.
+Use `spring.cloud.config.server.aws-secretsmanager.ignore-label` property to ignore the `{label}` parameter of the HTTP resource as well as `spring.cloud.config.server.aws-secretsmanager.default-label` property. The repository will use secrets as if labelled version support is disabled.
+
+[source,yaml]
+----
+spring:
+ profiles:
+ active: aws-secretsmanager
+ cloud:
+ config:
+ server:
+ aws-secretsmanager:
+ region: us-east-1
+ ignore-label: true
+----
+
==== AWS Parameter Store
When using AWS Parameter Store as a backend, you can share configuration with all applications by placing properties within the `/application` hierarchy.
@@ -1158,6 +1173,7 @@ AWS Secrets Manager API credentials are determined using link:https://docs.aws.a
[NOTE]
====
- When no application is specified `application` is the default, and when no profile is specified `default` is used.
+- Both `label` and `defaultLabel` properties are ignored, when `ignoreLabel` is set to `true`.
====
==== CredHub Backend
diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsSecretsManagerEnvironmentProperties.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsSecretsManagerEnvironmentProperties.java
index 2895a1da..f9decfa9 100644
--- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsSecretsManagerEnvironmentProperties.java
+++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsSecretsManagerEnvironmentProperties.java
@@ -54,6 +54,11 @@ public class AwsSecretsManagerEnvironmentProperties implements EnvironmentReposi
*/
private String defaultLabel;
+ /**
+ * Do not set staging label when fetching the secret values.
+ */
+ private boolean ignoreLabel;
+
/**
* The order of the environment repository.
*/
@@ -105,6 +110,14 @@ public class AwsSecretsManagerEnvironmentProperties implements EnvironmentReposi
this.defaultLabel = defaultLabel;
}
+ public boolean isIgnoreLabel() {
+ return this.ignoreLabel;
+ }
+
+ public void setIgnoreLabel(boolean ignoreLabel) {
+ this.ignoreLabel = ignoreLabel;
+ }
+
public int getOrder() {
return order;
}
diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsSecretsManagerEnvironmentRepository.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsSecretsManagerEnvironmentRepository.java
index 262c22fb..bdb4a89b 100644
--- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsSecretsManagerEnvironmentRepository.java
+++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsSecretsManagerEnvironmentRepository.java
@@ -73,6 +73,7 @@ public class AwsSecretsManagerEnvironmentRepository implements EnvironmentReposi
final String defaultApplication = configServerProperties.getDefaultApplicationName();
final String defaultProfile = configServerProperties.getDefaultProfile();
final String defaultLabel = environmentProperties.getDefaultLabel();
+ final boolean ignoreLabel = environmentProperties.isIgnoreLabel();
if (ObjectUtils.isEmpty(application)) {
application = defaultApplication;
@@ -82,7 +83,10 @@ public class AwsSecretsManagerEnvironmentRepository implements EnvironmentReposi
profileList = defaultProfile;
}
- if (StringUtils.isEmpty(label)) {
+ if (ignoreLabel) {
+ label = null;
+ }
+ else if (StringUtils.isEmpty(label)) {
label = defaultLabel;
}
diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/AwsSecretsManagerEnvironmentRepositoryTests.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/AwsSecretsManagerEnvironmentRepositoryTests.java
index 32691d99..3b8bfe65 100644
--- a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/AwsSecretsManagerEnvironmentRepositoryTests.java
+++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/AwsSecretsManagerEnvironmentRepositoryTests.java
@@ -88,6 +88,13 @@ public class AwsSecretsManagerEnvironmentRepositoryTests {
private final AwsSecretsManagerEnvironmentRepository labeledRepository = new AwsSecretsManagerEnvironmentRepository(
smClient, configServerProperties, labeledEnvironmentProperties);
+ private final AwsSecretsManagerEnvironmentProperties ignoreLabelEnvironmentProperties = new AwsSecretsManagerEnvironmentProperties() {{
+ setIgnoreLabel(true);
+ }};
+
+ private final AwsSecretsManagerEnvironmentRepository ignoreLabelRepository = new AwsSecretsManagerEnvironmentRepository(
+ smClient, configServerProperties, ignoreLabelEnvironmentProperties);
+
private final ObjectMapper objectMapper = new ObjectMapper().configure(SerializationFeature.INDENT_OUTPUT, true);
private final List toBeRemoved = new ArrayList<>();
@@ -1827,6 +1834,47 @@ public class AwsSecretsManagerEnvironmentRepositoryTests {
assertThat(resultEnv).usingRecursiveComparison().withStrictTypeChecking().isEqualTo(expectedEnv);
}
+ @Test
+ public void testFindOneWithExistingApplicationAndExistingProfileAndExistingLabelWhenIgnoreLabelIsSet() {
+ String application = "foo";
+ String profile = "prod";
+ String label = "release";
+ String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
+
+ String fooProdPropertiesName = "aws:secrets:/secret/foo-prod/";
+ PropertySource fooProdProperties = new PropertySource(fooProdPropertiesName, getFooProdReleaseProperties());
+
+ String fooPropertiesName = "aws:secrets:/secret/foo/";
+ PropertySource fooProperties = new PropertySource(fooPropertiesName, getFooReleaseProperties());
+
+ String fooDefaultPropertiesName = "aws:secrets:/secret/foo-default/";
+ PropertySource fooDefaultProperties = new PropertySource(fooDefaultPropertiesName,
+ getFooDefaultReleaseProperties());
+
+ String applicationProdPropertiesName = "aws:secrets:/secret/application-prod/";
+ PropertySource applicationProdProperties = new PropertySource(applicationProdPropertiesName,
+ getApplicationProdReleaseProperties());
+
+ String applicationDefaultPropertiesName = "aws:secrets:/secret/application-default/";
+ PropertySource applicationDefaultProperties = new PropertySource(applicationDefaultPropertiesName,
+ getApplicationDefaultReleaseProperties());
+
+ String applicationPropertiesName = "aws:secrets:/secret/application/";
+ PropertySource applicationProperties = new PropertySource(applicationPropertiesName,
+ getApplicationReleaseProperties());
+
+ Environment expectedEnv = new Environment(application, profiles, null, null, null);
+ expectedEnv.addAll(Arrays.asList(
+ fooProdProperties, applicationProdProperties, fooDefaultProperties,
+ applicationDefaultProperties, fooProperties, applicationProperties));
+
+ putSecrets(expectedEnv);
+
+ Environment resultEnv = ignoreLabelRepository.findOne(application, profile, label);
+
+ assertThat(resultEnv).usingRecursiveComparison().withStrictTypeChecking().isEqualTo(expectedEnv);
+ }
+
@Test
public void testFindOneWithNullApplicationAndNullProfile() {
String application = null;
From 25c5d087eff5902395e84662ff1d31a040427868 Mon Sep 17 00:00:00 2001
From: Ryan Baxter <524254+ryanjbaxter@users.noreply.github.com>
Date: Wed, 29 Nov 2023 14:08:43 -0500
Subject: [PATCH 11/11] Porting documentation changes to antora
---
.../aws-secrets-manager-backend.adoc | 1 +
.../aws-secrets-manager.adoc | 14 ++++++++++++++
2 files changed, 15 insertions(+)
diff --git a/docs/modules/ROOT/pages/server/environment-repository/aws-secrets-manager-backend.adoc b/docs/modules/ROOT/pages/server/environment-repository/aws-secrets-manager-backend.adoc
index a0ea21e6..5155a8d1 100644
--- a/docs/modules/ROOT/pages/server/environment-repository/aws-secrets-manager-backend.adoc
+++ b/docs/modules/ROOT/pages/server/environment-repository/aws-secrets-manager-backend.adoc
@@ -37,5 +37,6 @@ AWS Secrets Manager API credentials are determined using link:https://docs.aws.a
[NOTE]
====
- When no application is specified `application` is the default, and when no profile is specified `default` is used.
+- Both `label` and `defaultLabel` properties are ignored, when `ignoreLabel` is set to `true`.
====
diff --git a/docs/modules/ROOT/pages/server/environment-repository/aws-secrets-manager.adoc b/docs/modules/ROOT/pages/server/environment-repository/aws-secrets-manager.adoc
index c414f478..1b0c995f 100644
--- a/docs/modules/ROOT/pages/server/environment-repository/aws-secrets-manager.adoc
+++ b/docs/modules/ROOT/pages/server/environment-repository/aws-secrets-manager.adoc
@@ -78,3 +78,17 @@ Note that if the default label is not set and a request does not define a label,
Note that if the staging label contains a slash (`/`), then the label in the HTTP URL should instead be specified with the special string `(\{special-string})` (to avoid ambiguity with other URL paths) the same way <<_git_backend,Git backend's section>> describes it.
+Use `spring.cloud.config.server.aws-secretsmanager.ignore-label` property to ignore the `{label}` parameter of the HTTP resource as well as `spring.cloud.config.server.aws-secretsmanager.default-label` property. The repository will use secrets as if labelled version support is disabled.
+
+[source,yaml]
+----
+spring:
+ profiles:
+ active: aws-secretsmanager
+ cloud:
+ config:
+ server:
+ aws-secretsmanager:
+ region: us-east-1
+ ignore-label: true
+----