From e0cdf318713e6d1e8cf1037887d0a1e81687085f Mon Sep 17 00:00:00 2001 From: Mike Eltsufin Date: Tue, 8 Jun 2021 11:46:47 -0400 Subject: [PATCH 1/2] Allow placeholders in Cloud SQL config Secret Manager placehoders are still skipped as before. Fixes: #491. --- .../sql/CloudSqlEnvironmentPostProcessor.java | 18 ++++++++++++++++-- .../CloudSqlEnvironmentPostProcessorTests.java | 18 +++++++++++++++++- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/sql/CloudSqlEnvironmentPostProcessor.java b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/sql/CloudSqlEnvironmentPostProcessor.java index cedad81065..c2e8376e27 100644 --- a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/sql/CloudSqlEnvironmentPostProcessor.java +++ b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/sql/CloudSqlEnvironmentPostProcessor.java @@ -31,6 +31,8 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.bind.Binder; +import org.springframework.boot.context.properties.bind.PlaceholdersResolver; +import org.springframework.boot.context.properties.bind.PropertySourcesPlaceholdersResolver; import org.springframework.boot.context.properties.source.ConfigurationPropertySources; import org.springframework.boot.env.EnvironmentPostProcessor; import org.springframework.core.env.ConfigurableEnvironment; @@ -67,8 +69,20 @@ public void postProcessEnvironment(ConfigurableEnvironment environment, SpringAp LOGGER.info("post-processing Cloud SQL properties for + " + databaseType.name()); } - // Bind properties without resolving placeholders - Binder binder = new Binder(ConfigurationPropertySources.get(environment), null, null, null, null); + // Bind properties without resolving Secret Manager placeholders + Binder binder = new Binder(ConfigurationPropertySources.get(environment), new PlaceholdersResolver() { + PlaceholdersResolver resolver = new PropertySourcesPlaceholdersResolver(environment); + + @Override + public Object resolvePlaceholders(Object value) { + if (value.toString().contains("sm://")) { + return value; + } + else { + return resolver.resolvePlaceholders(value); + } + } + }, null, null, null); String cloudSqlPropertiesPrefix = GcpCloudSqlProperties.class.getAnnotation(ConfigurationProperties.class).value(); GcpCloudSqlProperties sqlProperties = binder diff --git a/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/sql/CloudSqlEnvironmentPostProcessorTests.java b/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/sql/CloudSqlEnvironmentPostProcessorTests.java index 978ebdf883..706e47eb44 100644 --- a/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/sql/CloudSqlEnvironmentPostProcessorTests.java +++ b/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/sql/CloudSqlEnvironmentPostProcessorTests.java @@ -264,7 +264,7 @@ public void testIamAuth() { } @Test - public void testPlaceholdersNotResolved() { + public void testSecretManagerPlaceholdersNotResolved() { this.contextRunner.withPropertyValues( "spring.cloud.gcp.sql.instance-connection-name=world:asia:japan", "spring.cloud.gcp.sql.database-name=${sm://my-db}") @@ -278,6 +278,22 @@ public void testPlaceholdersNotResolved() { }); } + @Test + public void testEnvPlaceholdersResolved() { + this.contextRunner.withPropertyValues( + "DB_NAME=mydb", + "spring.cloud.gcp.sql.instance-connection-name=world:asia:japan", + "spring.cloud.gcp.sql.database-name=${DB_NAME:not_available}") + .run(context -> { + assertThat(context.getEnvironment().getPropertySources() + .get("CLOUD_SQL_DATA_SOURCE_URL") + .getProperty("spring.datasource.url")) + .isEqualTo("jdbc:mysql://google/mydb?" + + "socketFactory=com.google.cloud.sql.mysql.SocketFactory" + + "&cloudSqlInstance=world:asia:japan"); + }); + } + @Test public void testSkipOnBootstrap() { new ApplicationContextRunner() From 2f9864cb950a8c8adfad0491cc7790c614084aa3 Mon Sep 17 00:00:00 2001 From: Mike Eltsufin Date: Tue, 8 Jun 2021 14:54:54 -0400 Subject: [PATCH 2/2] refactor into nested class --- .../sql/CloudSqlEnvironmentPostProcessor.java | 34 ++++++++++++------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/sql/CloudSqlEnvironmentPostProcessor.java b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/sql/CloudSqlEnvironmentPostProcessor.java index c2e8376e27..5cfa571273 100644 --- a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/sql/CloudSqlEnvironmentPostProcessor.java +++ b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/sql/CloudSqlEnvironmentPostProcessor.java @@ -36,6 +36,7 @@ import org.springframework.boot.context.properties.source.ConfigurationPropertySources; import org.springframework.boot.env.EnvironmentPostProcessor; import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.Environment; import org.springframework.core.env.MapPropertySource; import org.springframework.core.io.Resource; import org.springframework.util.ClassUtils; @@ -70,19 +71,9 @@ public void postProcessEnvironment(ConfigurableEnvironment environment, SpringAp } // Bind properties without resolving Secret Manager placeholders - Binder binder = new Binder(ConfigurationPropertySources.get(environment), new PlaceholdersResolver() { - PlaceholdersResolver resolver = new PropertySourcesPlaceholdersResolver(environment); - - @Override - public Object resolvePlaceholders(Object value) { - if (value.toString().contains("sm://")) { - return value; - } - else { - return resolver.resolvePlaceholders(value); - } - } - }, null, null, null); + Binder binder = new Binder(ConfigurationPropertySources.get(environment), + new NonSecretsManagerPropertiesPlaceholdersResolver(environment), + null, null, null); String cloudSqlPropertiesPrefix = GcpCloudSqlProperties.class.getAnnotation(ConfigurationProperties.class).value(); GcpCloudSqlProperties sqlProperties = binder @@ -203,4 +194,21 @@ private void setCredentialsFileProperty(Resource credentialsLocation) { } } + private static class NonSecretsManagerPropertiesPlaceholdersResolver implements PlaceholdersResolver { + private PlaceholdersResolver resolver; + + NonSecretsManagerPropertiesPlaceholdersResolver(Environment environment) { + this.resolver = new PropertySourcesPlaceholdersResolver(environment); + } + + @Override + public Object resolvePlaceholders(Object value) { + if (value.toString().contains("sm://")) { + return value; + } + else { + return resolver.resolvePlaceholders(value); + } + } + } }