From 453ee0ce4aae0089d22366b754003a33af8ce5f4 Mon Sep 17 00:00:00 2001 From: Maciej Walkowiak Date: Tue, 24 Nov 2020 21:54:43 +0100 Subject: [PATCH 01/14] Enable custom client configuration for SQS integration. --- .../messaging/SqsAutoConfiguration.java | 12 ++- .../messaging/SqsAutoConfigurationTest.java | 82 +++++++++++++++++++ .../core/SpringCloudClientConfiguration.java | 9 +- .../AmazonWebserviceClientFactoryBean.java | 16 +++- 4 files changed, 115 insertions(+), 4 deletions(-) diff --git a/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/messaging/SqsAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/messaging/SqsAutoConfiguration.java index 19438e594..8544cc957 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/messaging/SqsAutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/messaging/SqsAutoConfiguration.java @@ -19,6 +19,7 @@ import java.util.Arrays; import java.util.Optional; +import com.amazonaws.ClientConfiguration; import com.amazonaws.auth.AWSCredentialsProvider; import com.amazonaws.services.sqs.AmazonSQS; import com.amazonaws.services.sqs.AmazonSQSAsync; @@ -28,6 +29,7 @@ import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.ObjectProvider; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @@ -70,19 +72,25 @@ static class SqsClientConfiguration { private final SqsProperties properties; + private final ClientConfiguration clientConfiguration; + SqsClientConfiguration(ObjectProvider awsCredentialsProvider, - ObjectProvider regionProvider, SqsProperties properties) { + ObjectProvider regionProvider, SqsProperties properties, + @Qualifier("globalClientConfiguration") ObjectProvider globalClientConfiguration, + @Qualifier("sqsClientConfiguration") ObjectProvider sqsClientConfiguration) { this.awsCredentialsProvider = awsCredentialsProvider.getIfAvailable(); this.regionProvider = properties.getRegion() == null ? regionProvider.getIfAvailable() : new StaticRegionProvider(properties.getRegion()); this.properties = properties; + this.clientConfiguration = sqsClientConfiguration.getIfAvailable(globalClientConfiguration::getIfAvailable); } @Lazy @Bean(destroyMethod = "shutdown") public AmazonSQSBufferedAsyncClient amazonSQS() throws Exception { AmazonWebserviceClientFactoryBean clientFactoryBean = new AmazonWebserviceClientFactoryBean<>( - AmazonSQSAsyncClient.class, this.awsCredentialsProvider, this.regionProvider); + AmazonSQSAsyncClient.class, this.awsCredentialsProvider, this.regionProvider, + this.clientConfiguration); Optional.ofNullable(properties.getEndpoint()).ifPresent(clientFactoryBean::setCustomEndpoint); clientFactoryBean.afterPropertiesSet(); return new AmazonSQSBufferedAsyncClient(clientFactoryBean.getObject()); diff --git a/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/messaging/SqsAutoConfigurationTest.java b/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/messaging/SqsAutoConfigurationTest.java index 71a9f1bce..f0a324727 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/messaging/SqsAutoConfigurationTest.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/messaging/SqsAutoConfigurationTest.java @@ -20,6 +20,7 @@ import java.util.Collections; import java.util.List; +import com.amazonaws.ClientConfiguration; import com.amazonaws.auth.AWSCredentialsProvider; import com.amazonaws.auth.DefaultAWSCredentialsProviderChain; import com.amazonaws.regions.Region; @@ -276,6 +277,52 @@ void configuration_withRegionProvider_shouldUseItForClient() throws Exception { }); } + @Test + void configuration_withGlobalClientConfiguration_shouldUseItForClient() throws Exception { + // Arrange & Act + this.contextRunner.withUserConfiguration(ConfigurationWithGlobalClientConfiguration.class).run((context) -> { + AmazonSQSAsync bufferedAmazonSqsClient = context.getBean(AmazonSQSAsync.class); + AmazonSQSAsyncClient amazonSqs = (AmazonSQSAsyncClient) ReflectionTestUtils + .getField(bufferedAmazonSqsClient, "realSQS"); + + // Assert + ClientConfiguration clientConfiguration = (ClientConfiguration) ReflectionTestUtils.getField(amazonSqs, + "clientConfiguration"); + assertThat(clientConfiguration.getProxyHost()).isEqualTo("global"); + }); + } + + @Test + void configuration_withSqsClientConfiguration_shouldUseItForClient() throws Exception { + // Arrange & Act + this.contextRunner.withUserConfiguration(ConfigurationWithSqsClientConfiguration.class).run((context) -> { + AmazonSQSAsync bufferedAmazonSqsClient = context.getBean(AmazonSQSAsync.class); + AmazonSQSAsyncClient amazonSqs = (AmazonSQSAsyncClient) ReflectionTestUtils + .getField(bufferedAmazonSqsClient, "realSQS"); + + // Assert + ClientConfiguration clientConfiguration = (ClientConfiguration) ReflectionTestUtils.getField(amazonSqs, + "clientConfiguration"); + assertThat(clientConfiguration.getProxyHost()).isEqualTo("sqs"); + }); + } + + @Test + void configuration_withGlobalAndSqsClientConfigurations_shouldUseSqsConfigurationForClient() throws Exception { + // Arrange & Act + this.contextRunner.withUserConfiguration(ConfigurationWithGlobalAndSqsClientConfiguration.class) + .run((context) -> { + AmazonSQSAsync bufferedAmazonSqsClient = context.getBean(AmazonSQSAsync.class); + AmazonSQSAsyncClient amazonSqs = (AmazonSQSAsyncClient) ReflectionTestUtils + .getField(bufferedAmazonSqsClient, "realSQS"); + + // Assert + ClientConfiguration clientConfiguration = (ClientConfiguration) ReflectionTestUtils + .getField(amazonSqs, "clientConfiguration"); + assertThat(clientConfiguration.getProxyHost()).isEqualTo("sqs"); + }); + } + @Test void disableSqs() { this.contextRunner.withPropertyValues("cloud.aws.sqs.enabled:false").run(context -> { @@ -461,6 +508,41 @@ RegionProvider regionProvider() { } + @Configuration(proxyBeanMethods = false) + static class ConfigurationWithGlobalClientConfiguration { + + @Bean + ClientConfiguration globalClientConfiguration() { + return new ClientConfiguration().withProxyHost("global"); + } + + } + + @Configuration(proxyBeanMethods = false) + static class ConfigurationWithSqsClientConfiguration { + + @Bean + ClientConfiguration sqsClientConfiguration() { + return new ClientConfiguration().withProxyHost("sqs"); + } + + } + + @Configuration(proxyBeanMethods = false) + static class ConfigurationWithGlobalAndSqsClientConfiguration { + + @Bean + ClientConfiguration sqsClientConfiguration() { + return new ClientConfiguration().withProxyHost("sqs"); + } + + @Bean + ClientConfiguration globalClientConfiguration() { + return new ClientConfiguration().withProxyHost("global"); + } + + } + @Configuration(proxyBeanMethods = false) static class ConfigurationWithObjectMapper { diff --git a/spring-cloud-aws-core/src/main/java/org/springframework/cloud/aws/core/SpringCloudClientConfiguration.java b/spring-cloud-aws-core/src/main/java/org/springframework/cloud/aws/core/SpringCloudClientConfiguration.java index 621c39959..31e69a65e 100644 --- a/spring-cloud-aws-core/src/main/java/org/springframework/cloud/aws/core/SpringCloudClientConfiguration.java +++ b/spring-cloud-aws-core/src/main/java/org/springframework/cloud/aws/core/SpringCloudClientConfiguration.java @@ -17,6 +17,7 @@ package org.springframework.cloud.aws.core; import com.amazonaws.ClientConfiguration; +import com.amazonaws.ClientConfigurationFactory; import com.amazonaws.PredefinedClientConfigurations; /** @@ -37,7 +38,13 @@ private static String getUserAgent() { } public static ClientConfiguration getClientConfiguration() { - return PredefinedClientConfigurations.defaultConfig().withUserAgentSuffix(getUserAgent()); + return getClientConfiguration(PredefinedClientConfigurations.defaultConfig()); + } + + public static ClientConfiguration getClientConfiguration(ClientConfiguration clientConfiguration) { + ClientConfiguration config = clientConfiguration != null ? clientConfiguration + : PredefinedClientConfigurations.defaultConfig(); + return config.withUserAgentSuffix(getUserAgent()); } } diff --git a/spring-cloud-aws-core/src/main/java/org/springframework/cloud/aws/core/config/AmazonWebserviceClientFactoryBean.java b/spring-cloud-aws-core/src/main/java/org/springframework/cloud/aws/core/config/AmazonWebserviceClientFactoryBean.java index a7e4edd42..2cdd94101 100644 --- a/spring-cloud-aws-core/src/main/java/org/springframework/cloud/aws/core/config/AmazonWebserviceClientFactoryBean.java +++ b/spring-cloud-aws-core/src/main/java/org/springframework/cloud/aws/core/config/AmazonWebserviceClientFactoryBean.java @@ -21,6 +21,7 @@ import java.util.concurrent.ExecutorService; import com.amazonaws.AmazonWebServiceClient; +import com.amazonaws.ClientConfiguration; import com.amazonaws.auth.AWSCredentialsProvider; import com.amazonaws.client.builder.AwsAsyncClientBuilder; import com.amazonaws.client.builder.AwsClientBuilder; @@ -61,6 +62,8 @@ public class AmazonWebserviceClientFactoryBean private URI customEndpoint; + private ClientConfiguration clientConfiguration; + public AmazonWebserviceClientFactoryBean(Class clientClass, AWSCredentialsProvider credentialsProvider) { this.clientClass = clientClass; this.credentialsProvider = credentialsProvider; @@ -72,6 +75,13 @@ public AmazonWebserviceClientFactoryBean(Class clientClass, AWSCredentialsPro setRegionProvider(regionProvider); } + public AmazonWebserviceClientFactoryBean(Class clientClass, AWSCredentialsProvider credentialsProvider, + RegionProvider regionProvider, ClientConfiguration clientConfiguration) { + this(clientClass, credentialsProvider); + setRegionProvider(regionProvider); + setClientConfiguration(clientConfiguration); + } + @Override public Class getObjectType() { return this.clientClass; @@ -94,7 +104,7 @@ protected T createInstance() throws Exception { asyncBuilder.withExecutorFactory((ExecutorFactory) () -> this.executor); } - builder.withClientConfiguration(SpringCloudClientConfiguration.getClientConfiguration()); + builder.withClientConfiguration(SpringCloudClientConfiguration.getClientConfiguration(clientConfiguration)); if (this.credentialsProvider != null) { builder.withCredentials(this.credentialsProvider); @@ -134,6 +144,10 @@ public void setExecutor(ExecutorService executor) { this.executor = executor; } + public void setClientConfiguration(ClientConfiguration clientConfiguration) { + this.clientConfiguration = clientConfiguration; + } + @Override protected void destroyInstance(T instance) throws Exception { instance.shutdown(); From cf60fcef0c7c1bfdd966f62ceac43b845832eefb Mon Sep 17 00:00:00 2001 From: Maciej Walkowiak Date: Tue, 24 Nov 2020 22:00:36 +0100 Subject: [PATCH 02/14] Enable custom client configuration for CloudWatch integration. --- .../CloudWatchExportAutoConfiguration.java | 13 ++- ...CloudWatchExportAutoConfigurationTest.java | 80 +++++++++++++++++++ 2 files changed, 91 insertions(+), 2 deletions(-) diff --git a/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/metrics/CloudWatchExportAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/metrics/CloudWatchExportAutoConfiguration.java index dfcde3a51..2cfaa9e54 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/metrics/CloudWatchExportAutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/metrics/CloudWatchExportAutoConfiguration.java @@ -18,6 +18,7 @@ import java.util.Optional; +import com.amazonaws.ClientConfiguration; import com.amazonaws.auth.AWSCredentialsProvider; import com.amazonaws.services.cloudwatch.AmazonCloudWatchAsync; import com.amazonaws.services.cloudwatch.AmazonCloudWatchAsyncClient; @@ -26,6 +27,7 @@ import io.micrometer.core.instrument.Clock; import org.springframework.beans.factory.ObjectProvider; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration; @@ -66,11 +68,17 @@ public class CloudWatchExportAutoConfiguration { private final RegionProvider regionProvider; + private final ClientConfiguration clientConfiguration; + public CloudWatchExportAutoConfiguration(AWSCredentialsProvider credentialsProvider, - ObjectProvider regionProvider, CloudWatchProperties properties) { + ObjectProvider regionProvider, CloudWatchProperties properties, + @Qualifier("globalClientConfiguration") ObjectProvider globalClientConfiguration, + @Qualifier("cloudWatchClientConfiguration") ObjectProvider cloudWatchClientConfiguration) { this.credentialsProvider = credentialsProvider; this.regionProvider = properties.getRegion() == null ? regionProvider.getIfAvailable() : new StaticRegionProvider(properties.getRegion()); + this.clientConfiguration = cloudWatchClientConfiguration + .getIfAvailable(globalClientConfiguration::getIfAvailable); } @Bean @@ -85,7 +93,8 @@ public CloudWatchMeterRegistry cloudWatchMeterRegistry(CloudWatchConfig config, public AmazonWebserviceClientFactoryBean amazonCloudWatchAsync( CloudWatchProperties properties) { AmazonWebserviceClientFactoryBean clientFactoryBean = new AmazonWebserviceClientFactoryBean<>( - AmazonCloudWatchAsyncClient.class, this.credentialsProvider, this.regionProvider); + AmazonCloudWatchAsyncClient.class, this.credentialsProvider, this.regionProvider, + this.clientConfiguration); Optional.ofNullable(properties.getEndpoint()).ifPresent(clientFactoryBean::setCustomEndpoint); return clientFactoryBean; } diff --git a/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/metrics/CloudWatchExportAutoConfigurationTest.java b/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/metrics/CloudWatchExportAutoConfigurationTest.java index cf40bf7b7..fd27153a6 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/metrics/CloudWatchExportAutoConfigurationTest.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/metrics/CloudWatchExportAutoConfigurationTest.java @@ -18,6 +18,7 @@ import java.net.URI; +import com.amazonaws.ClientConfiguration; import com.amazonaws.regions.Regions; import com.amazonaws.services.cloudwatch.AmazonCloudWatchAsyncClient; import io.micrometer.cloudwatch.CloudWatchConfig; @@ -27,6 +28,8 @@ import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.springframework.test.util.ReflectionTestUtils; import static org.assertj.core.api.Assertions.assertThat; @@ -113,4 +116,81 @@ void enableAutoConfigurationWithCustomEndpoint() { }); } + @Test + void configuration_withGlobalClientConfiguration_shouldUseItForClient() throws Exception { + // Arrange & Act + this.contextRunner.withPropertyValues("management.metrics.export.cloudwatch.namespace:test") + .withUserConfiguration(ConfigurationWithGlobalClientConfiguration.class).run((context) -> { + AmazonCloudWatchAsyncClient client = context.getBean(AmazonCloudWatchAsyncClient.class); + + // Assert + ClientConfiguration clientConfiguration = (ClientConfiguration) ReflectionTestUtils.getField(client, + "clientConfiguration"); + assertThat(clientConfiguration.getProxyHost()).isEqualTo("global"); + }); + } + + @Test + void configuration_withCloudWatchClientConfiguration_shouldUseItForClient() throws Exception { + // Arrange & Act + this.contextRunner.withPropertyValues("management.metrics.export.cloudwatch.namespace:test") + .withUserConfiguration(ConfigurationWithCloudWatchClientConfiguration.class).run((context) -> { + AmazonCloudWatchAsyncClient client = context.getBean(AmazonCloudWatchAsyncClient.class); + + // Assert + ClientConfiguration clientConfiguration = (ClientConfiguration) ReflectionTestUtils.getField(client, + "clientConfiguration"); + assertThat(clientConfiguration.getProxyHost()).isEqualTo("cloudWatch"); + }); + } + + @Test + void configuration_withGlobalAndCloudWatchClientConfigurations_shouldUseCloudWatchConfigurationForClient() throws Exception { + // Arrange & Act + this.contextRunner.withPropertyValues("management.metrics.export.cloudwatch.namespace:test") + .withUserConfiguration(ConfigurationWithGlobalAndCloudWatchClientConfiguration.class).run((context) -> { + AmazonCloudWatchAsyncClient client = context.getBean(AmazonCloudWatchAsyncClient.class); + + // Assert + ClientConfiguration clientConfiguration = (ClientConfiguration) ReflectionTestUtils.getField(client, + "clientConfiguration"); + assertThat(clientConfiguration.getProxyHost()).isEqualTo("cloudWatch"); + }); + } + + @Configuration(proxyBeanMethods = false) + static class ConfigurationWithGlobalClientConfiguration { + + @Bean + ClientConfiguration globalClientConfiguration() { + return new ClientConfiguration().withProxyHost("global"); + } + + } + + @Configuration(proxyBeanMethods = false) + static class ConfigurationWithCloudWatchClientConfiguration { + + @Bean + ClientConfiguration cloudWatchClientConfiguration() { + return new ClientConfiguration().withProxyHost("cloudWatch"); + } + + } + + @Configuration(proxyBeanMethods = false) + static class ConfigurationWithGlobalAndCloudWatchClientConfiguration { + + @Bean + ClientConfiguration cloudWatchClientConfiguration() { + return new ClientConfiguration().withProxyHost("cloudWatch"); + } + + @Bean + ClientConfiguration globalClientConfiguration() { + return new ClientConfiguration().withProxyHost("global"); + } + + } + } From edf8dea1be024b3288a70a983527ea0eea7f66d4 Mon Sep 17 00:00:00 2001 From: Maciej Walkowiak Date: Tue, 24 Nov 2020 22:05:49 +0100 Subject: [PATCH 03/14] Enable custom client configuration for SNS integration. --- .../messaging/SnsAutoConfiguration.java | 11 ++- .../messaging/SnsAutoConfigurationTest.java | 81 ++++++++++++++++++- 2 files changed, 89 insertions(+), 3 deletions(-) diff --git a/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/messaging/SnsAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/messaging/SnsAutoConfiguration.java index a6a761240..86863be62 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/messaging/SnsAutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/messaging/SnsAutoConfiguration.java @@ -19,11 +19,13 @@ import java.util.List; import java.util.Optional; +import com.amazonaws.ClientConfiguration; import com.amazonaws.auth.AWSCredentialsProvider; import com.amazonaws.services.sns.AmazonSNS; import com.amazonaws.services.sns.AmazonSNSClient; import org.springframework.beans.factory.ObjectProvider; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -57,18 +59,23 @@ public class SnsAutoConfiguration { private final RegionProvider regionProvider; + private final ClientConfiguration clientConfiguration; + SnsAutoConfiguration(ObjectProvider awsCredentialsProvider, - ObjectProvider regionProvider, SnsProperties properties) { + ObjectProvider regionProvider, SnsProperties properties, + @Qualifier("globalClientConfiguration") ObjectProvider globalClientConfiguration, + @Qualifier("snsClientConfiguration") ObjectProvider snsClientConfiguration) { this.awsCredentialsProvider = awsCredentialsProvider.getIfAvailable(); this.regionProvider = properties.getRegion() == null ? regionProvider.getIfAvailable() : new StaticRegionProvider(properties.getRegion()); + this.clientConfiguration = snsClientConfiguration.getIfAvailable(globalClientConfiguration::getIfAvailable); } @ConditionalOnMissingAmazonClient(AmazonSNS.class) @Bean public AmazonWebserviceClientFactoryBean amazonSNS(SnsProperties properties) { AmazonWebserviceClientFactoryBean clientFactoryBean = new AmazonWebserviceClientFactoryBean<>( - AmazonSNSClient.class, this.awsCredentialsProvider, this.regionProvider); + AmazonSNSClient.class, this.awsCredentialsProvider, this.regionProvider, this.clientConfiguration); Optional.ofNullable(properties.getEndpoint()).ifPresent(clientFactoryBean::setCustomEndpoint); return clientFactoryBean; } diff --git a/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/messaging/SnsAutoConfigurationTest.java b/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/messaging/SnsAutoConfigurationTest.java index 6dd77aefa..9faf64ef1 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/messaging/SnsAutoConfigurationTest.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/messaging/SnsAutoConfigurationTest.java @@ -19,11 +19,14 @@ import java.net.URI; import java.util.List; +import com.amazonaws.ClientConfiguration; import com.amazonaws.auth.AWSCredentialsProvider; import com.amazonaws.regions.Region; import com.amazonaws.regions.Regions; import com.amazonaws.services.sns.AmazonSNS; import com.amazonaws.services.sns.AmazonSNSClient; +import com.amazonaws.services.sqs.AmazonSQSAsync; +import com.amazonaws.services.sqs.AmazonSQSAsyncClient; import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; @@ -32,6 +35,7 @@ import org.springframework.cloud.aws.core.region.StaticRegionProvider; import org.springframework.cloud.aws.messaging.endpoint.NotificationStatusHandlerMethodArgumentResolver; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.springframework.test.util.ReflectionTestUtils; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.method.support.HandlerMethodArgumentResolverComposite; @@ -136,7 +140,7 @@ void enableSnsWithSpecificRegion() { } @Test - void enableSqsWithCustomEndpoint() { + void enableSnsWithCustomEndpoint() { this.contextRunner.withPropertyValues("cloud.aws.sns.endpoint:http://localhost:8090").run(context -> { AmazonSNSClient client = context.getBean(AmazonSNSClient.class); @@ -148,6 +152,46 @@ void enableSqsWithCustomEndpoint() { }); } + @Test + void configuration_withGlobalClientConfiguration_shouldUseItForClient() { + // Arrange & Act + this.contextRunner.withUserConfiguration(ConfigurationWithGlobalClientConfiguration.class).run((context) -> { + AmazonSNS amazonSns = context.getBean(AmazonSNS.class); + + // Assert + ClientConfiguration clientConfiguration = (ClientConfiguration) ReflectionTestUtils.getField(amazonSns, + "clientConfiguration"); + assertThat(clientConfiguration.getProxyHost()).isEqualTo("global"); + }); + } + + @Test + void configuration_withSnsClientConfiguration_shouldUseItForClient() { + // Arrange & Act + this.contextRunner.withUserConfiguration(ConfigurationWithSnsClientConfiguration.class).run((context) -> { + AmazonSNS amazonSns = context.getBean(AmazonSNS.class); + + // Assert + ClientConfiguration clientConfiguration = (ClientConfiguration) ReflectionTestUtils.getField(amazonSns, + "clientConfiguration"); + assertThat(clientConfiguration.getProxyHost()).isEqualTo("sns"); + }); + } + + @Test + void configuration_withGlobalAndSnsClientConfigurations_shouldUseSnsConfigurationForClient() { + // Arrange & Act + this.contextRunner.withUserConfiguration(ConfigurationWithGlobalAndSnsClientConfiguration.class) + .run((context) -> { + AmazonSNS amazonSns = context.getBean(AmazonSNS.class); + + // Assert + ClientConfiguration clientConfiguration = (ClientConfiguration) ReflectionTestUtils + .getField(amazonSns, "clientConfiguration"); + assertThat(clientConfiguration.getProxyHost()).isEqualTo("sns"); + }); + } + private NotificationStatusHandlerMethodArgumentResolver getNotificationStatusHandlerMethodArgumentResolver( List resolvers) { for (HandlerMethodArgumentResolver resolver : resolvers) { @@ -199,4 +243,39 @@ RegionProvider regionProvider() { } + @Configuration(proxyBeanMethods = false) + static class ConfigurationWithGlobalClientConfiguration { + + @Bean + ClientConfiguration globalClientConfiguration() { + return new ClientConfiguration().withProxyHost("global"); + } + + } + + @Configuration(proxyBeanMethods = false) + static class ConfigurationWithSnsClientConfiguration { + + @Bean + ClientConfiguration snsClientConfiguration() { + return new ClientConfiguration().withProxyHost("sns"); + } + + } + + @Configuration(proxyBeanMethods = false) + static class ConfigurationWithGlobalAndSnsClientConfiguration { + + @Bean + ClientConfiguration snsClientConfiguration() { + return new ClientConfiguration().withProxyHost("sns"); + } + + @Bean + ClientConfiguration globalClientConfiguration() { + return new ClientConfiguration().withProxyHost("global"); + } + + } + } From 2b2f07be087ddce9445079e5dbb7fd42596e5abc Mon Sep 17 00:00:00 2001 From: Maciej Walkowiak Date: Tue, 24 Nov 2020 22:06:09 +0100 Subject: [PATCH 04/14] Polish. --- .../metrics/CloudWatchExportAutoConfigurationTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/metrics/CloudWatchExportAutoConfigurationTest.java b/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/metrics/CloudWatchExportAutoConfigurationTest.java index fd27153a6..cc7f01a1f 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/metrics/CloudWatchExportAutoConfigurationTest.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/metrics/CloudWatchExportAutoConfigurationTest.java @@ -145,7 +145,7 @@ void configuration_withCloudWatchClientConfiguration_shouldUseItForClient() thro } @Test - void configuration_withGlobalAndCloudWatchClientConfigurations_shouldUseCloudWatchConfigurationForClient() throws Exception { + void configuration_withGlobalAndCloudWatchClientConfigurations_shouldUseCloudWatchConfigurationForClient() { // Arrange & Act this.contextRunner.withPropertyValues("management.metrics.export.cloudwatch.namespace:test") .withUserConfiguration(ConfigurationWithGlobalAndCloudWatchClientConfiguration.class).run((context) -> { From a8e5df314c972b1ae7cbf06997e0ebab1dc892b5 Mon Sep 17 00:00:00 2001 From: Maciej Walkowiak Date: Tue, 24 Nov 2020 22:23:39 +0100 Subject: [PATCH 05/14] Enable custom client configuration for RDS integration. --- .../AmazonRdsDatabaseAutoConfiguration.java | 2 +- ...mazonRdsDatabaseAutoConfigurationTest.java | 77 +++++++++++++++++++ ...zonWebserviceClientConfigurationUtils.java | 20 ++++- .../xml/XmlWebserviceConfigurationUtils.java | 2 +- 4 files changed, 97 insertions(+), 4 deletions(-) diff --git a/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/jdbc/AmazonRdsDatabaseAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/jdbc/AmazonRdsDatabaseAutoConfiguration.java index 1a555f3df..9560d1289 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/jdbc/AmazonRdsDatabaseAutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/jdbc/AmazonRdsDatabaseAutoConfiguration.java @@ -81,7 +81,7 @@ public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, String endpoint = properties.getEndpoint() != null ? properties.getEndpoint().toString() : null; String amazonRdsClientBeanName = AmazonWebserviceClientConfigurationUtils .registerAmazonWebserviceClient(this, registry, "com.amazonaws.services.rds.AmazonRDSClient", null, - properties.getRegion(), endpoint) + properties.getRegion(), endpoint, "rdsClientConfiguration") .getBeanName(); properties.getInstances().stream().filter(RdsInstance::hasRequiredPropertiesSet) .forEach(instance -> registerDatasource(registry, amazonRdsClientBeanName, instance)); diff --git a/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/jdbc/AmazonRdsDatabaseAutoConfigurationTest.java b/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/jdbc/AmazonRdsDatabaseAutoConfigurationTest.java index 681db55fe..c37ef8868 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/jdbc/AmazonRdsDatabaseAutoConfigurationTest.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/jdbc/AmazonRdsDatabaseAutoConfigurationTest.java @@ -20,6 +20,7 @@ import javax.sql.DataSource; +import com.amazonaws.ClientConfiguration; import com.amazonaws.regions.Regions; import com.amazonaws.services.rds.AmazonRDS; import com.amazonaws.services.rds.AmazonRDSClient; @@ -37,6 +38,7 @@ import org.springframework.cloud.aws.jdbc.rds.AmazonRdsDataSourceFactoryBean; import org.springframework.cloud.aws.jdbc.rds.AmazonRdsReadReplicaAwareDataSourceFactoryBean; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.springframework.test.util.ReflectionTestUtils; import static org.assertj.core.api.Assertions.assertThat; @@ -167,6 +169,46 @@ void enableRdsWithCustomEndpoint() { }); } + @Test + void configuration_withGlobalClientConfiguration_shouldUseItForClient() { + // Arrange & Act + this.contextRunner.withUserConfiguration(ConfigurationWithGlobalClientConfiguration.class).run((context) -> { + AmazonRDSClient client = context.getBean(AmazonRDSClient.class); + + // Assert + ClientConfiguration clientConfiguration = (ClientConfiguration) ReflectionTestUtils.getField(client, + "clientConfiguration"); + assertThat(clientConfiguration.getProxyHost()).isEqualTo("global"); + }); + } + + @Test + void configuration_withSqsClientConfiguration_shouldUseItForClient() { + // Arrange & Act + this.contextRunner.withUserConfiguration(ConfigurationWithRdsClientConfiguration.class).run((context) -> { + AmazonRDSClient client = context.getBean(AmazonRDSClient.class); + + // Assert + ClientConfiguration clientConfiguration = (ClientConfiguration) ReflectionTestUtils.getField(client, + "clientConfiguration"); + assertThat(clientConfiguration.getProxyHost()).isEqualTo("rds"); + }); + } + + @Test + void configuration_withGlobalAndSqsClientConfigurations_shouldUseSqsConfigurationForClient() { + // Arrange & Act + this.contextRunner.withUserConfiguration(ConfigurationWithGlobalAndRdsClientConfiguration.class) + .run((context) -> { + AmazonRDSClient client = context.getBean(AmazonRDSClient.class); + + // Assert + ClientConfiguration clientConfiguration = (ClientConfiguration) ReflectionTestUtils.getField(client, + "clientConfiguration"); + assertThat(clientConfiguration.getProxyHost()).isEqualTo("rds"); + }); + } + static class ApplicationConfigurationWithoutReadReplica { @Bean @@ -238,4 +280,39 @@ public RdsInstanceConfigurer instanceConfigurer() { } + @Configuration(proxyBeanMethods = false) + static class ConfigurationWithGlobalClientConfiguration { + + @Bean + ClientConfiguration globalClientConfiguration() { + return new ClientConfiguration().withProxyHost("global"); + } + + } + + @Configuration(proxyBeanMethods = false) + static class ConfigurationWithRdsClientConfiguration { + + @Bean + ClientConfiguration rdsClientConfiguration() { + return new ClientConfiguration().withProxyHost("rds"); + } + + } + + @Configuration(proxyBeanMethods = false) + static class ConfigurationWithGlobalAndRdsClientConfiguration { + + @Bean + ClientConfiguration rdsClientConfiguration() { + return new ClientConfiguration().withProxyHost("rds"); + } + + @Bean + ClientConfiguration globalClientConfiguration() { + return new ClientConfiguration().withProxyHost("global"); + } + + } + } diff --git a/spring-cloud-aws-core/src/main/java/org/springframework/cloud/aws/core/config/AmazonWebserviceClientConfigurationUtils.java b/spring-cloud-aws-core/src/main/java/org/springframework/cloud/aws/core/config/AmazonWebserviceClientConfigurationUtils.java index 7f92ffa18..a02332ca4 100644 --- a/spring-cloud-aws-core/src/main/java/org/springframework/cloud/aws/core/config/AmazonWebserviceClientConfigurationUtils.java +++ b/spring-cloud-aws-core/src/main/java/org/springframework/cloud/aws/core/config/AmazonWebserviceClientConfigurationUtils.java @@ -67,6 +67,13 @@ public static BeanDefinitionHolder registerAmazonWebserviceClient(Object source, public static BeanDefinitionHolder registerAmazonWebserviceClient(Object source, BeanDefinitionRegistry registry, String serviceNameClassName, String customRegionProvider, String customRegion, String customEndpoint) { + return registerAmazonWebserviceClient(source, registry, serviceNameClassName, customRegionProvider, + customRegion, customEndpoint, null); + } + + public static BeanDefinitionHolder registerAmazonWebserviceClient(Object source, BeanDefinitionRegistry registry, + String serviceNameClassName, String customRegionProvider, String customRegion, String customEndpoint, + String clientConfigurationBeanName) { String beanName = getBeanName(serviceNameClassName); @@ -75,7 +82,7 @@ public static BeanDefinitionHolder registerAmazonWebserviceClient(Object source, } BeanDefinition definition = getAmazonWebserviceClientBeanDefinition(source, serviceNameClassName, - customRegionProvider, customRegion, customEndpoint, registry); + customRegionProvider, customRegion, customEndpoint, registry, clientConfigurationBeanName); BeanDefinitionHolder holder = new BeanDefinitionHolder(definition, beanName); BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry); @@ -84,7 +91,7 @@ public static BeanDefinitionHolder registerAmazonWebserviceClient(Object source, public static AbstractBeanDefinition getAmazonWebserviceClientBeanDefinition(Object source, String serviceNameClassName, String customRegionProvider, String customRegion, String customEndpoint, - BeanDefinitionRegistry beanDefinitionRegistry) { + BeanDefinitionRegistry beanDefinitionRegistry, String clientConfigurationBeanName) { if (StringUtils.hasText(customRegionProvider) && StringUtils.hasText(customRegion)) { throw new IllegalArgumentException("Only region or regionProvider can be configured, but not both"); @@ -117,6 +124,15 @@ else if (StringUtils.hasText(customRegion)) { builder.addPropertyReference("regionProvider", REGION_PROVIDER_BEAN_NAME); } + // configure client configuration + if (clientConfigurationBeanName != null + && beanDefinitionRegistry.containsBeanDefinition(clientConfigurationBeanName)) { + builder.addPropertyReference("clientConfiguration", clientConfigurationBeanName); + } + else if (beanDefinitionRegistry.containsBeanDefinition("globalClientConfiguration")) { + builder.addPropertyReference("clientConfiguration", "globalClientConfiguration"); + } + return builder.getBeanDefinition(); } diff --git a/spring-cloud-aws-core/src/main/java/org/springframework/cloud/aws/core/config/xml/XmlWebserviceConfigurationUtils.java b/spring-cloud-aws-core/src/main/java/org/springframework/cloud/aws/core/config/xml/XmlWebserviceConfigurationUtils.java index b3a8ebced..a793b2ce0 100644 --- a/spring-cloud-aws-core/src/main/java/org/springframework/cloud/aws/core/config/xml/XmlWebserviceConfigurationUtils.java +++ b/spring-cloud-aws-core/src/main/java/org/springframework/cloud/aws/core/config/xml/XmlWebserviceConfigurationUtils.java @@ -57,7 +57,7 @@ public static AbstractBeanDefinition parseCustomClientElement(Element element, P try { return getAmazonWebserviceClientBeanDefinition(source, serviceClassName, element.getAttribute(REGION_PROVIDER_ATTRIBUTE_NAME), element.getAttribute(REGION_ATTRIBUTE_NAME), - null, parserContext.getRegistry()); + null, parserContext.getRegistry(), null); } catch (Exception e) { parserContext.getReaderContext().error(e.getMessage(), source, e); From e7de146933da7ec09a163d2a4c54193bd2b181e3 Mon Sep 17 00:00:00 2001 From: Maciej Walkowiak Date: Tue, 24 Nov 2020 22:27:56 +0100 Subject: [PATCH 06/14] Enable custom client configuration for S3 integration. --- ...xtResourceLoaderAutoConfigurationTest.java | 78 +++++++++++++++++++ .../ContextResourceLoaderConfiguration.java | 2 +- 2 files changed, 79 insertions(+), 1 deletion(-) diff --git a/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/context/ContextResourceLoaderAutoConfigurationTest.java b/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/context/ContextResourceLoaderAutoConfigurationTest.java index 90ebd4f28..837794973 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/context/ContextResourceLoaderAutoConfigurationTest.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/context/ContextResourceLoaderAutoConfigurationTest.java @@ -18,6 +18,7 @@ import java.net.URI; +import com.amazonaws.ClientConfiguration; import com.amazonaws.regions.Regions; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.AmazonS3Client; @@ -28,6 +29,8 @@ import org.springframework.cloud.aws.autoconfigure.context.properties.AwsS3ResourceLoaderProperties; import org.springframework.cloud.aws.context.support.io.SimpleStorageProtocolResolverConfigurer; import org.springframework.cloud.aws.core.io.s3.SimpleStorageProtocolResolver; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.springframework.core.task.SyncTaskExecutor; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.test.util.ReflectionTestUtils; @@ -106,4 +109,79 @@ void enableS3withSpecificRegion() { }); } + @Test + void configuration_withGlobalClientConfiguration_shouldUseItForClient() { + // Arrange & Act + this.contextRunner.withUserConfiguration(ConfigurationWithGlobalClientConfiguration.class).run((context) -> { + AmazonS3 client = context.getBean(AmazonS3.class); + + // Assert + ClientConfiguration clientConfiguration = (ClientConfiguration) ReflectionTestUtils.getField(client, + "clientConfiguration"); + assertThat(clientConfiguration.getProxyHost()).isEqualTo("global"); + }); + } + + @Test + void configuration_withS3ClientConfiguration_shouldUseItForClient() { + // Arrange & Act + this.contextRunner.withUserConfiguration(ConfigurationWithS3ClientConfiguration.class).run((context) -> { + AmazonS3 client = context.getBean(AmazonS3.class); + + // Assert + ClientConfiguration clientConfiguration = (ClientConfiguration) ReflectionTestUtils.getField(client, + "clientConfiguration"); + assertThat(clientConfiguration.getProxyHost()).isEqualTo("s3"); + }); + } + + @Test + void configuration_withGlobalAndS3ClientConfigurations_shouldUseSqsConfigurationForClient() { + // Arrange & Act + this.contextRunner.withUserConfiguration(ConfigurationWithGlobalAndS3ClientConfiguration.class) + .run((context) -> { + AmazonS3 client = context.getBean(AmazonS3.class); + + // Assert + ClientConfiguration clientConfiguration = (ClientConfiguration) ReflectionTestUtils.getField(client, + "clientConfiguration"); + assertThat(clientConfiguration.getProxyHost()).isEqualTo("s3"); + }); + } + + @Configuration(proxyBeanMethods = false) + static class ConfigurationWithGlobalClientConfiguration { + + @Bean + ClientConfiguration globalClientConfiguration() { + return new ClientConfiguration().withProxyHost("global"); + } + + } + + @Configuration(proxyBeanMethods = false) + static class ConfigurationWithS3ClientConfiguration { + + @Bean + ClientConfiguration s3ClientConfiguration() { + return new ClientConfiguration().withProxyHost("s3"); + } + + } + + @Configuration(proxyBeanMethods = false) + static class ConfigurationWithGlobalAndS3ClientConfiguration { + + @Bean + ClientConfiguration s3ClientConfiguration() { + return new ClientConfiguration().withProxyHost("s3"); + } + + @Bean + ClientConfiguration globalClientConfiguration() { + return new ClientConfiguration().withProxyHost("global"); + } + + } + } diff --git a/spring-cloud-aws-context/src/main/java/org/springframework/cloud/aws/context/config/annotation/ContextResourceLoaderConfiguration.java b/spring-cloud-aws-context/src/main/java/org/springframework/cloud/aws/context/config/annotation/ContextResourceLoaderConfiguration.java index b07325b5b..d97756ba7 100644 --- a/spring-cloud-aws-context/src/main/java/org/springframework/cloud/aws/context/config/annotation/ContextResourceLoaderConfiguration.java +++ b/spring-cloud-aws-context/src/main/java/org/springframework/cloud/aws/context/config/annotation/ContextResourceLoaderConfiguration.java @@ -57,7 +57,7 @@ public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { BeanDefinitionHolder client = AmazonWebserviceClientConfigurationUtils.registerAmazonWebserviceClient(this, registry, AmazonS3Client.class.getName(), null, this.environment.getProperty("cloud.aws.s3.region"), - this.environment.getProperty("cloud.aws.s3.endpoint")); + this.environment.getProperty("cloud.aws.s3.endpoint"), "s3ClientConfiguration"); BeanDefinitionBuilder configurer = BeanDefinitionBuilder .genericBeanDefinition(SimpleStorageProtocolResolverConfigurer.class); From 88c448890771a4f87066ffc99d9ea22c3489365a Mon Sep 17 00:00:00 2001 From: Maciej Walkowiak Date: Tue, 24 Nov 2020 22:29:41 +0100 Subject: [PATCH 07/14] Polish. --- .../config/AmazonWebserviceClientConfigurationUtils.java | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/spring-cloud-aws-core/src/main/java/org/springframework/cloud/aws/core/config/AmazonWebserviceClientConfigurationUtils.java b/spring-cloud-aws-core/src/main/java/org/springframework/cloud/aws/core/config/AmazonWebserviceClientConfigurationUtils.java index a02332ca4..024fe8aad 100644 --- a/spring-cloud-aws-core/src/main/java/org/springframework/cloud/aws/core/config/AmazonWebserviceClientConfigurationUtils.java +++ b/spring-cloud-aws-core/src/main/java/org/springframework/cloud/aws/core/config/AmazonWebserviceClientConfigurationUtils.java @@ -62,13 +62,7 @@ private AmazonWebserviceClientConfigurationUtils() { public static BeanDefinitionHolder registerAmazonWebserviceClient(Object source, BeanDefinitionRegistry registry, String serviceNameClassName, String customRegionProvider, String customRegion) { return registerAmazonWebserviceClient(source, registry, serviceNameClassName, customRegionProvider, - customRegion, null); - } - - public static BeanDefinitionHolder registerAmazonWebserviceClient(Object source, BeanDefinitionRegistry registry, - String serviceNameClassName, String customRegionProvider, String customRegion, String customEndpoint) { - return registerAmazonWebserviceClient(source, registry, serviceNameClassName, customRegionProvider, - customRegion, customEndpoint, null); + customRegion, null, null); } public static BeanDefinitionHolder registerAmazonWebserviceClient(Object source, BeanDefinitionRegistry registry, From 70b81afb0b6a83000b23080c25f0db3bcec6b94d Mon Sep 17 00:00:00 2001 From: Maciej Walkowiak Date: Tue, 24 Nov 2020 22:30:00 +0100 Subject: [PATCH 08/14] Polish. --- .../core/config/AmazonWebserviceClientConfigurationUtils.java | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-cloud-aws-core/src/main/java/org/springframework/cloud/aws/core/config/AmazonWebserviceClientConfigurationUtils.java b/spring-cloud-aws-core/src/main/java/org/springframework/cloud/aws/core/config/AmazonWebserviceClientConfigurationUtils.java index 024fe8aad..e3dd0763b 100644 --- a/spring-cloud-aws-core/src/main/java/org/springframework/cloud/aws/core/config/AmazonWebserviceClientConfigurationUtils.java +++ b/spring-cloud-aws-core/src/main/java/org/springframework/cloud/aws/core/config/AmazonWebserviceClientConfigurationUtils.java @@ -35,6 +35,7 @@ /** * @author Agim Emruli * @author Alain Sahli + * @author Maciej Walkowiak */ public final class AmazonWebserviceClientConfigurationUtils { From bbc753e33b75021e3ce70fc81a11a2f8fcdfa5e6 Mon Sep 17 00:00:00 2001 From: Maciej Walkowiak Date: Tue, 24 Nov 2020 22:36:28 +0100 Subject: [PATCH 09/14] Enable custom client configuration for ElastiCache integration. --- .../cache/ElastiCacheAutoConfiguration.java | 12 ++- .../ElastiCacheAutoConfigurationTest.java | 78 +++++++++++++++++++ 2 files changed, 88 insertions(+), 2 deletions(-) diff --git a/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/cache/ElastiCacheAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/cache/ElastiCacheAutoConfiguration.java index d792bbc92..86a81c90c 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/cache/ElastiCacheAutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/cache/ElastiCacheAutoConfiguration.java @@ -19,12 +19,14 @@ import java.util.ArrayList; import java.util.List; +import com.amazonaws.ClientConfiguration; import com.amazonaws.auth.AWSCredentialsProvider; import com.amazonaws.services.elasticache.AmazonElastiCache; import com.amazonaws.services.elasticache.AmazonElastiCacheClient; import net.spy.memcached.MemcachedClient; import org.springframework.beans.factory.ObjectProvider; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -62,10 +64,16 @@ public class ElastiCacheAutoConfiguration { private final ListableStackResourceFactory stackResourceFactory; + private final ClientConfiguration clientConfiguration; + public ElastiCacheAutoConfiguration(ElastiCacheProperties properties, - ObjectProvider stackResourceFactory) { + ObjectProvider stackResourceFactory, + @Qualifier("globalClientConfiguration") ObjectProvider globalClientConfiguration, + @Qualifier("elastiCacheClientConfiguration") ObjectProvider elastiCacheClientConfiguration) { this.properties = properties; this.stackResourceFactory = stackResourceFactory.getIfAvailable(); + this.clientConfiguration = elastiCacheClientConfiguration + .getIfAvailable(globalClientConfiguration::getIfAvailable); } @Bean @@ -73,7 +81,7 @@ public ElastiCacheAutoConfiguration(ElastiCacheProperties properties, public AmazonWebserviceClientFactoryBean amazonElastiCache( ObjectProvider regionProvider, ObjectProvider credentialsProvider) { return new AmazonWebserviceClientFactoryBean<>(AmazonElastiCacheClient.class, - credentialsProvider.getIfAvailable(), regionProvider.getIfAvailable()); + credentialsProvider.getIfAvailable(), regionProvider.getIfAvailable(), clientConfiguration); } @Bean diff --git a/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/cache/ElastiCacheAutoConfigurationTest.java b/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/cache/ElastiCacheAutoConfigurationTest.java index 2530af346..8d7382ee6 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/cache/ElastiCacheAutoConfigurationTest.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/cache/ElastiCacheAutoConfigurationTest.java @@ -19,6 +19,7 @@ import java.lang.reflect.Field; import java.util.Arrays; +import com.amazonaws.ClientConfiguration; import com.amazonaws.services.elasticache.AmazonElastiCache; import com.amazonaws.services.elasticache.model.CacheCluster; import com.amazonaws.services.elasticache.model.DescribeCacheClustersRequest; @@ -37,6 +38,7 @@ import org.springframework.cloud.aws.core.env.stack.StackResource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.test.util.ReflectionTestUtils; import org.springframework.util.ReflectionUtils; import static org.assertj.core.api.Assertions.assertThat; @@ -229,6 +231,47 @@ ListableStackResourceFactory stackResourceFactory() { } + @Test + void configuration_withGlobalClientConfiguration_shouldUseItForClient() { + // Arrange & Act + this.contextRunner.withUserConfiguration(ConfigurationWithGlobalClientConfiguration.class).run((context) -> { + AmazonElastiCache client = context.getBean(AmazonElastiCache.class); + + // Assert + ClientConfiguration clientConfiguration = (ClientConfiguration) ReflectionTestUtils.getField(client, + "clientConfiguration"); + assertThat(clientConfiguration.getProxyHost()).isEqualTo("global"); + }); + } + + @Test + void configuration_withElastiCacheClientConfiguration_shouldUseItForClient() { + // Arrange & Act + this.contextRunner.withUserConfiguration(ConfigurationWithElastiCacheClientConfiguration.class) + .run((context) -> { + AmazonElastiCache client = context.getBean(AmazonElastiCache.class); + + // Assert + ClientConfiguration clientConfiguration = (ClientConfiguration) ReflectionTestUtils.getField(client, + "clientConfiguration"); + assertThat(clientConfiguration.getProxyHost()).isEqualTo("elastiCache"); + }); + } + + @Test + void configuration_withGlobalAndElastiCacheClientConfigurations_shouldUseSqsConfigurationForClient() { + // Arrange & Act + this.contextRunner.withUserConfiguration(ConfigurationWithGlobalAndElastiCacheClientConfiguration.class) + .run((context) -> { + AmazonElastiCache client = context.getBean(AmazonElastiCache.class); + + // Assert + ClientConfiguration clientConfiguration = (ClientConfiguration) ReflectionTestUtils.getField(client, + "clientConfiguration"); + assertThat(clientConfiguration.getProxyHost()).isEqualTo("elastiCache"); + }); + } + @Configuration static class CustomCacheConfigurerConfiguration { @@ -249,4 +292,39 @@ AmazonElastiCache customAmazonElastiCache() { } + @Configuration(proxyBeanMethods = false) + static class ConfigurationWithGlobalClientConfiguration { + + @Bean + ClientConfiguration globalClientConfiguration() { + return new ClientConfiguration().withProxyHost("global"); + } + + } + + @Configuration(proxyBeanMethods = false) + static class ConfigurationWithElastiCacheClientConfiguration { + + @Bean + ClientConfiguration elastiCacheClientConfiguration() { + return new ClientConfiguration().withProxyHost("elastiCache"); + } + + } + + @Configuration(proxyBeanMethods = false) + static class ConfigurationWithGlobalAndElastiCacheClientConfiguration { + + @Bean + ClientConfiguration elastiCacheClientConfiguration() { + return new ClientConfiguration().withProxyHost("elastiCache"); + } + + @Bean + ClientConfiguration globalClientConfiguration() { + return new ClientConfiguration().withProxyHost("global"); + } + + } + } From c7d9287ad42f6b38746a0f847c1455802b78f787 Mon Sep 17 00:00:00 2001 From: Maciej Walkowiak Date: Tue, 24 Nov 2020 23:02:20 +0100 Subject: [PATCH 10/14] Polish. --- .../cache/ElastiCacheAutoConfiguration.java | 4 +- .../messaging/SnsAutoConfiguration.java | 3 +- .../messaging/SqsAutoConfiguration.java | 4 +- .../CloudWatchExportAutoConfiguration.java | 4 +- .../ElastiCacheAutoConfigurationTest.java | 76 +++++++++---------- .../messaging/SnsAutoConfigurationTest.java | 2 - .../core/SpringCloudClientConfiguration.java | 1 - ...zonWebserviceClientConfigurationUtils.java | 6 +- 8 files changed, 53 insertions(+), 47 deletions(-) diff --git a/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/cache/ElastiCacheAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/cache/ElastiCacheAutoConfiguration.java index 86a81c90c..36e5255de 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/cache/ElastiCacheAutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/cache/ElastiCacheAutoConfiguration.java @@ -48,6 +48,8 @@ import org.springframework.context.annotation.Import; import org.springframework.data.redis.connection.RedisConnectionFactory; +import static org.springframework.cloud.aws.core.config.AmazonWebserviceClientConfigurationUtils.GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME; + /** * @author Agim Emruli * @author Eddú Meléndez @@ -68,7 +70,7 @@ public class ElastiCacheAutoConfiguration { public ElastiCacheAutoConfiguration(ElastiCacheProperties properties, ObjectProvider stackResourceFactory, - @Qualifier("globalClientConfiguration") ObjectProvider globalClientConfiguration, + @Qualifier(GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME) ObjectProvider globalClientConfiguration, @Qualifier("elastiCacheClientConfiguration") ObjectProvider elastiCacheClientConfiguration) { this.properties = properties; this.stackResourceFactory = stackResourceFactory.getIfAvailable(); diff --git a/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/messaging/SnsAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/messaging/SnsAutoConfiguration.java index 86863be62..4d9eccc7d 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/messaging/SnsAutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/messaging/SnsAutoConfiguration.java @@ -39,6 +39,7 @@ import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import static org.springframework.cloud.aws.core.config.AmazonWebserviceClientConfigurationUtils.GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME; import static org.springframework.cloud.aws.messaging.endpoint.config.NotificationHandlerMethodArgumentResolverConfigurationUtils.getNotificationHandlerMethodArgumentResolver; /** @@ -63,7 +64,7 @@ public class SnsAutoConfiguration { SnsAutoConfiguration(ObjectProvider awsCredentialsProvider, ObjectProvider regionProvider, SnsProperties properties, - @Qualifier("globalClientConfiguration") ObjectProvider globalClientConfiguration, + @Qualifier(GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME) ObjectProvider globalClientConfiguration, @Qualifier("snsClientConfiguration") ObjectProvider snsClientConfiguration) { this.awsCredentialsProvider = awsCredentialsProvider.getIfAvailable(); this.regionProvider = properties.getRegion() == null ? regionProvider.getIfAvailable() diff --git a/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/messaging/SqsAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/messaging/SqsAutoConfiguration.java index 8544cc957..8ddc0f3e1 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/messaging/SqsAutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/messaging/SqsAutoConfiguration.java @@ -50,6 +50,8 @@ import org.springframework.messaging.converter.MappingJackson2MessageConverter; import org.springframework.util.CollectionUtils; +import static org.springframework.cloud.aws.core.config.AmazonWebserviceClientConfigurationUtils.GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME; + /** * {@link EnableAutoConfiguration Auto-configuration} for SQS integration. * @@ -76,7 +78,7 @@ static class SqsClientConfiguration { SqsClientConfiguration(ObjectProvider awsCredentialsProvider, ObjectProvider regionProvider, SqsProperties properties, - @Qualifier("globalClientConfiguration") ObjectProvider globalClientConfiguration, + @Qualifier(GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME) ObjectProvider globalClientConfiguration, @Qualifier("sqsClientConfiguration") ObjectProvider sqsClientConfiguration) { this.awsCredentialsProvider = awsCredentialsProvider.getIfAvailable(); this.regionProvider = properties.getRegion() == null ? regionProvider.getIfAvailable() diff --git a/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/metrics/CloudWatchExportAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/metrics/CloudWatchExportAutoConfiguration.java index 2cfaa9e54..a7f314381 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/metrics/CloudWatchExportAutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/metrics/CloudWatchExportAutoConfiguration.java @@ -46,6 +46,8 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import static org.springframework.cloud.aws.core.config.AmazonWebserviceClientConfigurationUtils.GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME; + /** * Configuration for exporting metrics to CloudWatch. * @@ -72,7 +74,7 @@ public class CloudWatchExportAutoConfiguration { public CloudWatchExportAutoConfiguration(AWSCredentialsProvider credentialsProvider, ObjectProvider regionProvider, CloudWatchProperties properties, - @Qualifier("globalClientConfiguration") ObjectProvider globalClientConfiguration, + @Qualifier(GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME) ObjectProvider globalClientConfiguration, @Qualifier("cloudWatchClientConfiguration") ObjectProvider cloudWatchClientConfiguration) { this.credentialsProvider = credentialsProvider; this.regionProvider = properties.getRegion() == null ? regionProvider.getIfAvailable() diff --git a/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/cache/ElastiCacheAutoConfigurationTest.java b/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/cache/ElastiCacheAutoConfigurationTest.java index 8d7382ee6..90df927de 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/cache/ElastiCacheAutoConfigurationTest.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/cache/ElastiCacheAutoConfigurationTest.java @@ -193,44 +193,6 @@ void customElastiCacheClientProvided_doesNotCreateDefaultOne() { }); } - @Configuration(proxyBeanMethods = false) - static class MockCacheConfigurationWithStackCaches { - - @Bean - AmazonElastiCache amazonElastiCache() { - AmazonElastiCache amazonElastiCache = mock(AmazonElastiCache.class); - int port = TestMemcacheServer.startServer(); - DescribeCacheClustersRequest sampleCacheOneLogical = new DescribeCacheClustersRequest() - .withCacheClusterId("sampleCacheOneLogical"); - sampleCacheOneLogical.setShowCacheNodeInfo(true); - - Mockito.when(amazonElastiCache.describeCacheClusters(sampleCacheOneLogical)) - .thenReturn(new DescribeCacheClustersResult().withCacheClusters(new CacheCluster() - .withConfigurationEndpoint(new Endpoint().withAddress("localhost").withPort(port)) - .withEngine("memcached"))); - - DescribeCacheClustersRequest sampleCacheTwoLogical = new DescribeCacheClustersRequest() - .withCacheClusterId("sampleCacheTwoLogical"); - sampleCacheTwoLogical.setShowCacheNodeInfo(true); - - Mockito.when(amazonElastiCache.describeCacheClusters(sampleCacheTwoLogical)) - .thenReturn(new DescribeCacheClustersResult().withCacheClusters(new CacheCluster() - .withConfigurationEndpoint(new Endpoint().withAddress("localhost").withPort(port)) - .withEngine("memcached"))); - return amazonElastiCache; - } - - @Bean - ListableStackResourceFactory stackResourceFactory() { - ListableStackResourceFactory resourceFactory = mock(ListableStackResourceFactory.class); - Mockito.when(resourceFactory.resourcesByType("AWS::ElastiCache::CacheCluster")).thenReturn(Arrays.asList( - new StackResource("sampleCacheOneLogical", "sampleCacheOne", "AWS::ElastiCache::CacheCluster"), - new StackResource("sampleCacheTwoLogical", "sampleCacheTwo", "AWS::ElastiCache::CacheCluster"))); - return resourceFactory; - } - - } - @Test void configuration_withGlobalClientConfiguration_shouldUseItForClient() { // Arrange & Act @@ -272,6 +234,44 @@ void configuration_withGlobalAndElastiCacheClientConfigurations_shouldUseSqsConf }); } + @Configuration(proxyBeanMethods = false) + static class MockCacheConfigurationWithStackCaches { + + @Bean + AmazonElastiCache amazonElastiCache() { + AmazonElastiCache amazonElastiCache = mock(AmazonElastiCache.class); + int port = TestMemcacheServer.startServer(); + DescribeCacheClustersRequest sampleCacheOneLogical = new DescribeCacheClustersRequest() + .withCacheClusterId("sampleCacheOneLogical"); + sampleCacheOneLogical.setShowCacheNodeInfo(true); + + Mockito.when(amazonElastiCache.describeCacheClusters(sampleCacheOneLogical)) + .thenReturn(new DescribeCacheClustersResult().withCacheClusters(new CacheCluster() + .withConfigurationEndpoint(new Endpoint().withAddress("localhost").withPort(port)) + .withEngine("memcached"))); + + DescribeCacheClustersRequest sampleCacheTwoLogical = new DescribeCacheClustersRequest() + .withCacheClusterId("sampleCacheTwoLogical"); + sampleCacheTwoLogical.setShowCacheNodeInfo(true); + + Mockito.when(amazonElastiCache.describeCacheClusters(sampleCacheTwoLogical)) + .thenReturn(new DescribeCacheClustersResult().withCacheClusters(new CacheCluster() + .withConfigurationEndpoint(new Endpoint().withAddress("localhost").withPort(port)) + .withEngine("memcached"))); + return amazonElastiCache; + } + + @Bean + ListableStackResourceFactory stackResourceFactory() { + ListableStackResourceFactory resourceFactory = mock(ListableStackResourceFactory.class); + Mockito.when(resourceFactory.resourcesByType("AWS::ElastiCache::CacheCluster")).thenReturn(Arrays.asList( + new StackResource("sampleCacheOneLogical", "sampleCacheOne", "AWS::ElastiCache::CacheCluster"), + new StackResource("sampleCacheTwoLogical", "sampleCacheTwo", "AWS::ElastiCache::CacheCluster"))); + return resourceFactory; + } + + } + @Configuration static class CustomCacheConfigurerConfiguration { diff --git a/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/messaging/SnsAutoConfigurationTest.java b/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/messaging/SnsAutoConfigurationTest.java index 9faf64ef1..c1f173191 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/messaging/SnsAutoConfigurationTest.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/messaging/SnsAutoConfigurationTest.java @@ -25,8 +25,6 @@ import com.amazonaws.regions.Regions; import com.amazonaws.services.sns.AmazonSNS; import com.amazonaws.services.sns.AmazonSNSClient; -import com.amazonaws.services.sqs.AmazonSQSAsync; -import com.amazonaws.services.sqs.AmazonSQSAsyncClient; import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; diff --git a/spring-cloud-aws-core/src/main/java/org/springframework/cloud/aws/core/SpringCloudClientConfiguration.java b/spring-cloud-aws-core/src/main/java/org/springframework/cloud/aws/core/SpringCloudClientConfiguration.java index 31e69a65e..a7dd12f43 100644 --- a/spring-cloud-aws-core/src/main/java/org/springframework/cloud/aws/core/SpringCloudClientConfiguration.java +++ b/spring-cloud-aws-core/src/main/java/org/springframework/cloud/aws/core/SpringCloudClientConfiguration.java @@ -17,7 +17,6 @@ package org.springframework.cloud.aws.core; import com.amazonaws.ClientConfiguration; -import com.amazonaws.ClientConfigurationFactory; import com.amazonaws.PredefinedClientConfigurations; /** diff --git a/spring-cloud-aws-core/src/main/java/org/springframework/cloud/aws/core/config/AmazonWebserviceClientConfigurationUtils.java b/spring-cloud-aws-core/src/main/java/org/springframework/cloud/aws/core/config/AmazonWebserviceClientConfigurationUtils.java index e3dd0763b..090ae312b 100644 --- a/spring-cloud-aws-core/src/main/java/org/springframework/cloud/aws/core/config/AmazonWebserviceClientConfigurationUtils.java +++ b/spring-cloud-aws-core/src/main/java/org/springframework/cloud/aws/core/config/AmazonWebserviceClientConfigurationUtils.java @@ -45,6 +45,8 @@ public final class AmazonWebserviceClientConfigurationUtils { // @checkstyle:off public static final String REGION_PROVIDER_BEAN_NAME = "org.springframework.cloud.aws.core.region.RegionProvider.BEAN_NAME"; + public static final String GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME = "com.amazonaws.ClientConfiguration.BEAN_NAME"; + // @checkstyle:on /** @@ -124,8 +126,8 @@ else if (StringUtils.hasText(customRegion)) { && beanDefinitionRegistry.containsBeanDefinition(clientConfigurationBeanName)) { builder.addPropertyReference("clientConfiguration", clientConfigurationBeanName); } - else if (beanDefinitionRegistry.containsBeanDefinition("globalClientConfiguration")) { - builder.addPropertyReference("clientConfiguration", "globalClientConfiguration"); + else if (beanDefinitionRegistry.containsBeanDefinition(GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME)) { + builder.addPropertyReference("clientConfiguration", GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME); } return builder.getBeanDefinition(); From 9f1980464ee53639031af0d0e73543eb88ecec39 Mon Sep 17 00:00:00 2001 From: Maciej Walkowiak Date: Tue, 24 Nov 2020 23:12:05 +0100 Subject: [PATCH 11/14] Polish. --- .../cache/ElastiCacheAutoConfigurationTest.java | 5 +++-- .../context/ContextResourceLoaderAutoConfigurationTest.java | 5 +++-- .../jdbc/AmazonRdsDatabaseAutoConfigurationTest.java | 5 +++-- .../autoconfigure/messaging/SnsAutoConfigurationTest.java | 5 +++-- .../autoconfigure/messaging/SqsAutoConfigurationTest.java | 5 +++-- .../metrics/CloudWatchExportAutoConfigurationTest.java | 5 +++-- 6 files changed, 18 insertions(+), 12 deletions(-) diff --git a/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/cache/ElastiCacheAutoConfigurationTest.java b/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/cache/ElastiCacheAutoConfigurationTest.java index 90df927de..cee1bcb94 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/cache/ElastiCacheAutoConfigurationTest.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/cache/ElastiCacheAutoConfigurationTest.java @@ -43,6 +43,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; +import static org.springframework.cloud.aws.core.config.AmazonWebserviceClientConfigurationUtils.GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME; /** * Tests for {@link ElastiCacheAutoConfiguration}. @@ -295,7 +296,7 @@ AmazonElastiCache customAmazonElastiCache() { @Configuration(proxyBeanMethods = false) static class ConfigurationWithGlobalClientConfiguration { - @Bean + @Bean(name = GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME) ClientConfiguration globalClientConfiguration() { return new ClientConfiguration().withProxyHost("global"); } @@ -320,7 +321,7 @@ ClientConfiguration elastiCacheClientConfiguration() { return new ClientConfiguration().withProxyHost("elastiCache"); } - @Bean + @Bean(name = GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME) ClientConfiguration globalClientConfiguration() { return new ClientConfiguration().withProxyHost("global"); } diff --git a/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/context/ContextResourceLoaderAutoConfigurationTest.java b/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/context/ContextResourceLoaderAutoConfigurationTest.java index 837794973..e31a580c0 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/context/ContextResourceLoaderAutoConfigurationTest.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/context/ContextResourceLoaderAutoConfigurationTest.java @@ -36,6 +36,7 @@ import org.springframework.test.util.ReflectionTestUtils; import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.cloud.aws.core.config.AmazonWebserviceClientConfigurationUtils.GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME; class ContextResourceLoaderAutoConfigurationTest { @@ -152,7 +153,7 @@ void configuration_withGlobalAndS3ClientConfigurations_shouldUseSqsConfiguration @Configuration(proxyBeanMethods = false) static class ConfigurationWithGlobalClientConfiguration { - @Bean + @Bean(name = GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME) ClientConfiguration globalClientConfiguration() { return new ClientConfiguration().withProxyHost("global"); } @@ -177,7 +178,7 @@ ClientConfiguration s3ClientConfiguration() { return new ClientConfiguration().withProxyHost("s3"); } - @Bean + @Bean(name = GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME) ClientConfiguration globalClientConfiguration() { return new ClientConfiguration().withProxyHost("global"); } diff --git a/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/jdbc/AmazonRdsDatabaseAutoConfigurationTest.java b/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/jdbc/AmazonRdsDatabaseAutoConfigurationTest.java index c37ef8868..76dff7af7 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/jdbc/AmazonRdsDatabaseAutoConfigurationTest.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/jdbc/AmazonRdsDatabaseAutoConfigurationTest.java @@ -43,6 +43,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.when; +import static org.springframework.cloud.aws.core.config.AmazonWebserviceClientConfigurationUtils.GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME; class AmazonRdsDatabaseAutoConfigurationTest { @@ -283,7 +284,7 @@ public RdsInstanceConfigurer instanceConfigurer() { @Configuration(proxyBeanMethods = false) static class ConfigurationWithGlobalClientConfiguration { - @Bean + @Bean(name = GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME) ClientConfiguration globalClientConfiguration() { return new ClientConfiguration().withProxyHost("global"); } @@ -308,7 +309,7 @@ ClientConfiguration rdsClientConfiguration() { return new ClientConfiguration().withProxyHost("rds"); } - @Bean + @Bean(name = GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME) ClientConfiguration globalClientConfiguration() { return new ClientConfiguration().withProxyHost("global"); } diff --git a/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/messaging/SnsAutoConfigurationTest.java b/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/messaging/SnsAutoConfigurationTest.java index c1f173191..e71476de5 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/messaging/SnsAutoConfigurationTest.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/messaging/SnsAutoConfigurationTest.java @@ -42,6 +42,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; +import static org.springframework.cloud.aws.core.config.AmazonWebserviceClientConfigurationUtils.GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME; import static org.springframework.cloud.aws.core.config.AmazonWebserviceClientConfigurationUtils.REGION_PROVIDER_BEAN_NAME; /** @@ -244,7 +245,7 @@ RegionProvider regionProvider() { @Configuration(proxyBeanMethods = false) static class ConfigurationWithGlobalClientConfiguration { - @Bean + @Bean(name = GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME) ClientConfiguration globalClientConfiguration() { return new ClientConfiguration().withProxyHost("global"); } @@ -269,7 +270,7 @@ ClientConfiguration snsClientConfiguration() { return new ClientConfiguration().withProxyHost("sns"); } - @Bean + @Bean(name = GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME) ClientConfiguration globalClientConfiguration() { return new ClientConfiguration().withProxyHost("global"); } diff --git a/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/messaging/SqsAutoConfigurationTest.java b/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/messaging/SqsAutoConfigurationTest.java index f0a324727..09e0a6787 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/messaging/SqsAutoConfigurationTest.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/messaging/SqsAutoConfigurationTest.java @@ -57,6 +57,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.withSettings; +import static org.springframework.cloud.aws.core.config.AmazonWebserviceClientConfigurationUtils.GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME; import static org.springframework.cloud.aws.core.config.AmazonWebserviceClientConfigurationUtils.REGION_PROVIDER_BEAN_NAME; /** @@ -511,7 +512,7 @@ RegionProvider regionProvider() { @Configuration(proxyBeanMethods = false) static class ConfigurationWithGlobalClientConfiguration { - @Bean + @Bean(name = GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME) ClientConfiguration globalClientConfiguration() { return new ClientConfiguration().withProxyHost("global"); } @@ -536,7 +537,7 @@ ClientConfiguration sqsClientConfiguration() { return new ClientConfiguration().withProxyHost("sqs"); } - @Bean + @Bean(name = GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME) ClientConfiguration globalClientConfiguration() { return new ClientConfiguration().withProxyHost("global"); } diff --git a/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/metrics/CloudWatchExportAutoConfigurationTest.java b/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/metrics/CloudWatchExportAutoConfigurationTest.java index cc7f01a1f..511c8c907 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/metrics/CloudWatchExportAutoConfigurationTest.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/metrics/CloudWatchExportAutoConfigurationTest.java @@ -33,6 +33,7 @@ import org.springframework.test.util.ReflectionTestUtils; import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.cloud.aws.core.config.AmazonWebserviceClientConfigurationUtils.GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME; /** * Test for the {@link CloudWatchExportAutoConfiguration}. @@ -161,7 +162,7 @@ void configuration_withGlobalAndCloudWatchClientConfigurations_shouldUseCloudWat @Configuration(proxyBeanMethods = false) static class ConfigurationWithGlobalClientConfiguration { - @Bean + @Bean(name = GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME) ClientConfiguration globalClientConfiguration() { return new ClientConfiguration().withProxyHost("global"); } @@ -186,7 +187,7 @@ ClientConfiguration cloudWatchClientConfiguration() { return new ClientConfiguration().withProxyHost("cloudWatch"); } - @Bean + @Bean(name = GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME) ClientConfiguration globalClientConfiguration() { return new ClientConfiguration().withProxyHost("global"); } From e3bbda675fc6150437713bc00fa654c8ebec83f3 Mon Sep 17 00:00:00 2001 From: Maciej Walkowiak Date: Tue, 15 Dec 2020 21:54:17 +0100 Subject: [PATCH 12/14] Enable custom client configuration for SES integration. --- .../mail/SesAutoConfiguration.java | 14 +++- .../mail/SesAutoConfigurationTest.java | 80 +++++++++++++++++++ 2 files changed, 92 insertions(+), 2 deletions(-) diff --git a/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/mail/SesAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/mail/SesAutoConfiguration.java index 973446a28..19176fa05 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/mail/SesAutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/mail/SesAutoConfiguration.java @@ -18,11 +18,13 @@ import javax.mail.Session; +import com.amazonaws.ClientConfiguration; import com.amazonaws.auth.AWSCredentialsProvider; import com.amazonaws.services.simpleemail.AmazonSimpleEmailService; import com.amazonaws.services.simpleemail.AmazonSimpleEmailServiceClient; import org.springframework.beans.factory.ObjectProvider; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; @@ -45,6 +47,8 @@ import org.springframework.mail.MailSender; import org.springframework.mail.javamail.JavaMailSender; +import static org.springframework.cloud.aws.core.config.AmazonWebserviceClientConfigurationUtils.GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME; + /** * {@link EnableAutoConfiguration Auto-configuration} for AWS Simple Email Service * support. @@ -66,18 +70,24 @@ public class SesAutoConfiguration { private final RegionProvider regionProvider; + private final ClientConfiguration clientConfiguration; + public SesAutoConfiguration(ObjectProvider regionProvider, - ObjectProvider credentialsProvider, SesProperties properties) { + ObjectProvider credentialsProvider, + @Qualifier(GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME) ObjectProvider globalClientConfiguration, + @Qualifier("sesClientConfiguration") ObjectProvider sesClientConfiguration, + SesProperties properties) { this.credentialsProvider = credentialsProvider.getIfAvailable(); this.regionProvider = properties.getRegion() == null ? regionProvider.getIfAvailable() : new StaticRegionProvider(properties.getRegion()); + this.clientConfiguration = sesClientConfiguration.getIfAvailable(globalClientConfiguration::getIfAvailable); } @Bean @ConditionalOnMissingAmazonClient(AmazonSimpleEmailService.class) public AmazonWebserviceClientFactoryBean amazonSimpleEmailService() { return new AmazonWebserviceClientFactoryBean<>(AmazonSimpleEmailServiceClient.class, this.credentialsProvider, - this.regionProvider); + this.regionProvider, this.clientConfiguration); } @Bean diff --git a/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/mail/SesAutoConfigurationTest.java b/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/mail/SesAutoConfigurationTest.java index 29cc659c4..e28800b38 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/mail/SesAutoConfigurationTest.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/mail/SesAutoConfigurationTest.java @@ -16,17 +16,22 @@ package org.springframework.cloud.aws.autoconfigure.mail; +import com.amazonaws.ClientConfiguration; +import com.amazonaws.services.simpleemail.AmazonSimpleEmailService; import com.amazonaws.services.simpleemail.AmazonSimpleEmailServiceClient; import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.FilteredClassLoader; import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.springframework.mail.MailSender; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.test.util.ReflectionTestUtils; import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.cloud.aws.core.config.AmazonWebserviceClientConfigurationUtils.GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME; class SesAutoConfigurationTest { @@ -97,4 +102,79 @@ void sesAutoConfigurationIsDisabledButSimpleEmailAutoConfigurationIsEnabled() { }); } + @Test + void configuration_withGlobalClientConfiguration_shouldUseItForClient() { + // Arrange & Act + this.contextRunner.withUserConfiguration(ConfigurationWithGlobalClientConfiguration.class).run((context) -> { + AmazonSimpleEmailServiceClient client = context.getBean(AmazonSimpleEmailServiceClient.class); + + // Assert + ClientConfiguration clientConfiguration = (ClientConfiguration) ReflectionTestUtils.getField(client, + "clientConfiguration"); + assertThat(clientConfiguration.getProxyHost()).isEqualTo("global"); + }); + } + + @Test + void configuration_withSesClientConfiguration_shouldUseItForClient() { + // Arrange & Act + this.contextRunner.withUserConfiguration(ConfigurationWithSesClientConfiguration.class).run((context) -> { + AmazonSimpleEmailServiceClient client = context.getBean(AmazonSimpleEmailServiceClient.class); + + // Assert + ClientConfiguration clientConfiguration = (ClientConfiguration) ReflectionTestUtils.getField(client, + "clientConfiguration"); + assertThat(clientConfiguration.getProxyHost()).isEqualTo("ses"); + }); + } + + @Test + void configuration_withGlobalAndSesClientConfigurations_shouldUseSqsConfigurationForClient() { + // Arrange & Act + this.contextRunner.withUserConfiguration(ConfigurationWithGlobalAndSesClientConfiguration.class) + .run((context) -> { + AmazonSimpleEmailServiceClient client = context.getBean(AmazonSimpleEmailServiceClient.class); + + // Assert + ClientConfiguration clientConfiguration = (ClientConfiguration) ReflectionTestUtils.getField(client, + "clientConfiguration"); + assertThat(clientConfiguration.getProxyHost()).isEqualTo("ses"); + }); + } + + @Configuration(proxyBeanMethods = false) + static class ConfigurationWithGlobalClientConfiguration { + + @Bean(name = GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME) + ClientConfiguration globalClientConfiguration() { + return new ClientConfiguration().withProxyHost("global"); + } + + } + + @Configuration(proxyBeanMethods = false) + static class ConfigurationWithSesClientConfiguration { + + @Bean + ClientConfiguration sesClientConfiguration() { + return new ClientConfiguration().withProxyHost("ses"); + } + + } + + @Configuration(proxyBeanMethods = false) + static class ConfigurationWithGlobalAndSesClientConfiguration { + + @Bean + ClientConfiguration sesClientConfiguration() { + return new ClientConfiguration().withProxyHost("ses"); + } + + @Bean(name = GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME) + ClientConfiguration globalClientConfiguration() { + return new ClientConfiguration().withProxyHost("global"); + } + + } + } From f940771f785bf491a844d4948b10aea3b899715f Mon Sep 17 00:00:00 2001 From: Maciej Walkowiak Date: Tue, 15 Dec 2020 22:01:05 +0100 Subject: [PATCH 13/14] Enable custom client configuration for the legacy SES integration. --- .../mail/SimpleEmailAutoConfiguration.java | 12 ++- .../SimpleEmailAutoConfigurationTest.java | 83 +++++++++++++++++++ 2 files changed, 94 insertions(+), 1 deletion(-) diff --git a/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/mail/SimpleEmailAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/mail/SimpleEmailAutoConfiguration.java index 61b7146a0..c4bfd67b7 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/mail/SimpleEmailAutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/org/springframework/cloud/aws/autoconfigure/mail/SimpleEmailAutoConfiguration.java @@ -20,11 +20,13 @@ import javax.mail.Session; +import com.amazonaws.ClientConfiguration; import com.amazonaws.auth.AWSCredentialsProvider; import com.amazonaws.services.simpleemail.AmazonSimpleEmailService; import com.amazonaws.services.simpleemail.AmazonSimpleEmailServiceClient; import org.springframework.beans.factory.ObjectProvider; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @@ -45,6 +47,8 @@ import org.springframework.mail.MailSender; import org.springframework.mail.javamail.JavaMailSender; +import static org.springframework.cloud.aws.core.config.AmazonWebserviceClientConfigurationUtils.GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME; + /** * @author Agim Emruli * @author Eddú Meléndez @@ -62,10 +66,15 @@ public class SimpleEmailAutoConfiguration { private final RegionProvider regionProvider; + private final ClientConfiguration clientConfiguration; + public SimpleEmailAutoConfiguration(ObjectProvider regionProvider, + @Qualifier(GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME) ObjectProvider globalClientConfiguration, + @Qualifier("sesClientConfiguration") ObjectProvider sesClientConfiguration, SimpleEmailProperties properties) { this.regionProvider = properties.getRegion() == null ? regionProvider.getIfAvailable() : new StaticRegionProvider(properties.getRegion()); + this.clientConfiguration = sesClientConfiguration.getIfAvailable(globalClientConfiguration::getIfAvailable); } @Bean @@ -73,7 +82,8 @@ public SimpleEmailAutoConfiguration(ObjectProvider regionProvide public AmazonWebserviceClientFactoryBean amazonSimpleEmailService( AWSCredentialsProvider credentialsProvider, SimpleEmailProperties properties) { AmazonWebserviceClientFactoryBean clientFactoryBean = new AmazonWebserviceClientFactoryBean<>( - AmazonSimpleEmailServiceClient.class, credentialsProvider, this.regionProvider); + AmazonSimpleEmailServiceClient.class, credentialsProvider, this.regionProvider, + this.clientConfiguration); Optional.ofNullable(properties.getEndpoint()).ifPresent(clientFactoryBean::setCustomEndpoint); return clientFactoryBean; } diff --git a/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/mail/SimpleEmailAutoConfigurationTest.java b/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/mail/SimpleEmailAutoConfigurationTest.java index 185f3bcf7..025e8ec69 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/mail/SimpleEmailAutoConfigurationTest.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/org/springframework/cloud/aws/autoconfigure/mail/SimpleEmailAutoConfigurationTest.java @@ -16,6 +16,7 @@ package org.springframework.cloud.aws.autoconfigure.mail; +import com.amazonaws.ClientConfiguration; import com.amazonaws.regions.Regions; import com.amazonaws.services.simpleemail.AmazonSimpleEmailServiceClient; import org.junit.jupiter.api.Test; @@ -23,11 +24,14 @@ import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.FilteredClassLoader; import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.springframework.mail.MailSender; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.test.util.ReflectionTestUtils; import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.cloud.aws.core.config.AmazonWebserviceClientConfigurationUtils.GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME; class SimpleEmailAutoConfigurationTest { @@ -79,4 +83,83 @@ void mailIsDisabled() { }); } + @Test + void configuration_withGlobalClientConfiguration_shouldUseItForClient() { + // Arrange & Act + this.contextRunner + .withUserConfiguration(SesAutoConfigurationTest.ConfigurationWithGlobalClientConfiguration.class) + .run((context) -> { + AmazonSimpleEmailServiceClient client = context.getBean(AmazonSimpleEmailServiceClient.class); + + // Assert + ClientConfiguration clientConfiguration = (ClientConfiguration) ReflectionTestUtils.getField(client, + "clientConfiguration"); + assertThat(clientConfiguration.getProxyHost()).isEqualTo("global"); + }); + } + + @Test + void configuration_withSesClientConfiguration_shouldUseItForClient() { + // Arrange & Act + this.contextRunner.withUserConfiguration(SesAutoConfigurationTest.ConfigurationWithSesClientConfiguration.class) + .run((context) -> { + AmazonSimpleEmailServiceClient client = context.getBean(AmazonSimpleEmailServiceClient.class); + + // Assert + ClientConfiguration clientConfiguration = (ClientConfiguration) ReflectionTestUtils.getField(client, + "clientConfiguration"); + assertThat(clientConfiguration.getProxyHost()).isEqualTo("ses"); + }); + } + + @Test + void configuration_withGlobalAndSesClientConfigurations_shouldUseSqsConfigurationForClient() { + // Arrange & Act + this.contextRunner + .withUserConfiguration(SesAutoConfigurationTest.ConfigurationWithGlobalAndSesClientConfiguration.class) + .run((context) -> { + AmazonSimpleEmailServiceClient client = context.getBean(AmazonSimpleEmailServiceClient.class); + + // Assert + ClientConfiguration clientConfiguration = (ClientConfiguration) ReflectionTestUtils.getField(client, + "clientConfiguration"); + assertThat(clientConfiguration.getProxyHost()).isEqualTo("ses"); + }); + } + + @Configuration(proxyBeanMethods = false) + static class ConfigurationWithGlobalClientConfiguration { + + @Bean(name = GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME) + ClientConfiguration globalClientConfiguration() { + return new ClientConfiguration().withProxyHost("global"); + } + + } + + @Configuration(proxyBeanMethods = false) + static class ConfigurationWithSesClientConfiguration { + + @Bean + ClientConfiguration sesClientConfiguration() { + return new ClientConfiguration().withProxyHost("ses"); + } + + } + + @Configuration(proxyBeanMethods = false) + static class ConfigurationWithGlobalAndSesClientConfiguration { + + @Bean + ClientConfiguration sesClientConfiguration() { + return new ClientConfiguration().withProxyHost("ses"); + } + + @Bean(name = GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME) + ClientConfiguration globalClientConfiguration() { + return new ClientConfiguration().withProxyHost("global"); + } + + } + } From ece3e0cbddb8504f752996a61d7429d71d9204d6 Mon Sep 17 00:00:00 2001 From: Maciej Walkowiak Date: Tue, 15 Dec 2020 22:21:57 +0100 Subject: [PATCH 14/14] Update reference docs. --- docs/src/main/asciidoc/_configprops.adoc | 81 ++++++++++---------- docs/src/main/asciidoc/spring-cloud-aws.adoc | 66 ++++++++++++++++ 2 files changed, 107 insertions(+), 40 deletions(-) diff --git a/docs/src/main/asciidoc/_configprops.adoc b/docs/src/main/asciidoc/_configprops.adoc index 5895a0097..304a7c7c8 100644 --- a/docs/src/main/asciidoc/_configprops.adoc +++ b/docs/src/main/asciidoc/_configprops.adoc @@ -1,67 +1,68 @@ |=== |Name | Default | Description -|aws.paramstore.default-context | application | -|aws.paramstore.enabled | true | Is AWS Parameter Store support enabled. +|aws.paramstore.default-context | `application` | +|aws.paramstore.enabled | `true` | Is AWS Parameter Store support enabled. |aws.paramstore.endpoint | | Overrides the default endpoint. -|aws.paramstore.fail-fast | true | Throw exceptions during config lookup if true, otherwise, log warnings. +|aws.paramstore.fail-fast | `true` | Throw exceptions during config lookup if true, otherwise, log warnings. |aws.paramstore.name | | Alternative to spring.application.name to use in looking up values in AWS Parameter Store. -|aws.paramstore.prefix | /config | Prefix indicating first level for every property. Value must start with a forward slash followed by a valid path segment or be empty. Defaults to "/config". -|aws.paramstore.profile-separator | _ | +|aws.paramstore.prefix | `/config` | Prefix indicating first level for every property. Value must start with a forward slash followed by a valid path segment or be empty. Defaults to "/config". +|aws.paramstore.profile-separator | `_` | |aws.paramstore.region | | If region value is not null or empty it will be used in creation of AWSSimpleSystemsManagement. -|aws.secretsmanager.default-context | application | -|aws.secretsmanager.enabled | true | Is AWS Secrets Manager support enabled. +|aws.secretsmanager.default-context | `application` | +|aws.secretsmanager.enabled | `true` | Is AWS Secrets Manager support enabled. |aws.secretsmanager.endpoint | | Overrides the default endpoint. -|aws.secretsmanager.fail-fast | true | Throw exceptions during config lookup if true, otherwise, log warnings. +|aws.secretsmanager.fail-fast | `true` | Throw exceptions during config lookup if true, otherwise, log warnings. |aws.secretsmanager.name | | Alternative to spring.application.name to use in looking up values in AWS Secrets Manager. -|aws.secretsmanager.prefix | /secret | Prefix indicating first level for every property. Value must start with a forward slash followed by a valid path segment or be empty. Defaults to "/config". -|aws.secretsmanager.profile-separator | _ | +|aws.secretsmanager.prefix | `/secret` | Prefix indicating first level for every property. Value must start with a forward slash followed by a valid path segment or be empty. Defaults to "/config". +|aws.secretsmanager.profile-separator | `_` | |aws.secretsmanager.region | | If region value is not null or empty it will be used in creation of AWSSecretsManager. |cloud.aws.credentials.access-key | | The access key to be used with a static provider. -|cloud.aws.credentials.instance-profile | false | Configures an instance profile credentials provider with no further configuration. +|cloud.aws.credentials.instance-profile | `false` | Configures an instance profile credentials provider with no further configuration. |cloud.aws.credentials.profile-name | | The AWS profile name. |cloud.aws.credentials.profile-path | | The AWS profile path. |cloud.aws.credentials.secret-key | | The secret key to be used with a static provider. -|cloud.aws.elasticache.cache-names | | +|cloud.aws.elasticache.cache-names | | |cloud.aws.elasticache.clusters | | Configures the cache clusters for the caching configuration. Support one or multiple caches {@link Cluster} configurations with their physical cache name (as configured in the ElastiCache service) or their logical cache name if the caches are configured inside a stack and {@link org.springframework.cloud.aws.context.config.annotation.EnableStackConfiguration} annotation is used inside the application. -|cloud.aws.elasticache.default-expiration | 0 | Configures the default expiration time in seconds if there is no custom expiration time configuration with a {@link Cluster} configuration for the cache. The expiration time is implementation specific (e.g. Redis or Memcached) and could therefore differ in the behaviour based on the cache implementation. -|cloud.aws.elasticache.enabled | true | Enables ElastiCache integration. -|cloud.aws.elasticache.expiry-time-per-cache | | -|cloud.aws.instance.data.enabled | false | Enables Instance Data integration. -|cloud.aws.loader.core-pool-size | 1 | The core pool size of the Task Executor used for parallel S3 interaction. @see org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor#setCorePoolSize(int) +|cloud.aws.elasticache.default-expiration | `0` | Configures the default expiration time in seconds if there is no custom expiration time configuration with a {@link Cluster} configuration for the cache. The expiration time is implementation specific (e.g. Redis or Memcached) and could therefore differ in the behaviour based on the cache implementation. +|cloud.aws.elasticache.enabled | `true` | Enables ElastiCache integration. +|cloud.aws.elasticache.expiry-time-per-cache | | +|cloud.aws.instance.data.enabled | `false` | Enables Instance Data integration. +|cloud.aws.loader.core-pool-size | `1` | The core pool size of the Task Executor used for parallel S3 interaction. @see org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor#setCorePoolSize(int) |cloud.aws.loader.max-pool-size | | The maximum pool size of the Task Executor used for parallel S3 interaction. @see org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor#setMaxPoolSize(int) |cloud.aws.loader.queue-capacity | | The maximum queue capacity for backed up S3 requests. @see org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor#setQueueCapacity(int) -|cloud.aws.mail.enabled | true | Enables Mail integration. -|cloud.aws.mail.endpoint | | -|cloud.aws.mail.region | | -|cloud.aws.rds.enabled | true | Enables RDS integration. -|cloud.aws.rds.endpoint | | +|cloud.aws.mail.enabled | `true` | Enables Mail integration. +|cloud.aws.mail.endpoint | | +|cloud.aws.mail.region | | +|cloud.aws.rds.enabled | `true` | Enables RDS integration. +|cloud.aws.rds.endpoint | | |cloud.aws.rds.instances | | List of RdsInstances. -|cloud.aws.rds.region | | +|cloud.aws.rds.region | | +|cloud.aws.region.static | | |cloud.aws.s3.endpoint | | Overrides the default endpoint. |cloud.aws.s3.region | | Overrides the default region. -|cloud.aws.sns.enabled | true | Enables SNS integration. -|cloud.aws.sns.endpoint | | -|cloud.aws.sns.region | | -|cloud.aws.sqs.enabled | true | Enables SQS integration. -|cloud.aws.sqs.endpoint | | +|cloud.aws.sns.enabled | `true` | Enables SNS integration. +|cloud.aws.sns.endpoint | | +|cloud.aws.sns.region | | +|cloud.aws.sqs.enabled | `true` | Enables SQS integration. +|cloud.aws.sqs.endpoint | | |cloud.aws.sqs.handler.default-deletion-policy | | Configures global deletion policy used if deletion policy is not explicitly set on {@link SqsListener}. -|cloud.aws.sqs.listener.auto-startup | true | Configures if this container should be automatically started. +|cloud.aws.sqs.listener.auto-startup | `true` | Configures if this container should be automatically started. |cloud.aws.sqs.listener.back-off-time | | The number of milliseconds the polling thread must wait before trying to recover when an error occurs (e.g. connection timeout). -|cloud.aws.sqs.listener.max-number-of-messages | 10 | The maximum number of messages that should be retrieved during one poll to the Amazon SQS system. This number must be a positive, non-zero number that has a maximum number of 10. Values higher then 10 are currently not supported by the queueing system. +|cloud.aws.sqs.listener.max-number-of-messages | `10` | The maximum number of messages that should be retrieved during one poll to the Amazon SQS system. This number must be a positive, non-zero number that has a maximum number of 10. Values higher then 10 are currently not supported by the queueing system. |cloud.aws.sqs.listener.queue-stop-timeout | | The queue stop timeout that waits for a queue to stop before interrupting the running thread. |cloud.aws.sqs.listener.visibility-timeout | | The duration (in seconds) that the received messages are hidden from subsequent poll requests after being retrieved from the system. -|cloud.aws.sqs.listener.wait-timeout | 20 | The wait timeout that the poll request will wait for new message to arrive if the are currently no messages on the queue. Higher values will reduce poll request to the system significantly. The value should be between 1 and 20. For more information read the documentation. -|cloud.aws.sqs.region | | -|cloud.aws.stack.auto | true | Enables the automatic stack name detection for the application. -|cloud.aws.stack.enabled | true | Enables Stack integration. +|cloud.aws.sqs.listener.wait-timeout | `20` | The wait timeout that the poll request will wait for new message to arrive if the are currently no messages on the queue. Higher values will reduce poll request to the system significantly. The value should be between 1 and 20. For more information read the documentation. +|cloud.aws.sqs.region | | +|cloud.aws.stack.auto | `true` | Enables the automatic stack name detection for the application. +|cloud.aws.stack.enabled | `true` | Enables Stack integration. |cloud.aws.stack.name | | The name of the manually configured stack name that will be used to retrieve the resources. -|spring.cloud.aws.security.cognito.algorithm | RS256 | Encryption algorithm used to sign the JWK token. +|spring.cloud.aws.security.cognito.algorithm | `RS256` | Encryption algorithm used to sign the JWK token. |spring.cloud.aws.security.cognito.app-client-id | | Non-dynamic audience string to validate. -|spring.cloud.aws.security.cognito.enabled | true | Enables Cognito integration. -|spring.cloud.aws.security.cognito.region | | -|spring.cloud.aws.security.cognito.user-pool-id | | -|spring.cloud.aws.ses.enabled | true | Enables Simple Email Service integration. +|spring.cloud.aws.security.cognito.enabled | `true` | Enables Cognito integration. +|spring.cloud.aws.security.cognito.region | | +|spring.cloud.aws.security.cognito.user-pool-id | | +|spring.cloud.aws.ses.enabled | `true` | Enables Simple Email Service integration. |spring.cloud.aws.ses.region | | Overrides the default region. -|=== +|=== \ No newline at end of file diff --git a/docs/src/main/asciidoc/spring-cloud-aws.adoc b/docs/src/main/asciidoc/spring-cloud-aws.adoc index 633d407ed..f2ee93c5b 100644 --- a/docs/src/main/asciidoc/spring-cloud-aws.adoc +++ b/docs/src/main/asciidoc/spring-cloud-aws.adoc @@ -383,6 +383,72 @@ cloud.aws.rds.endpoint=http://localhost:4566 Using custom endpoint can be especially useful when using https://github.com/localstack/localstack[Localstack] in integration tests or integrating with AWS compatible 3rd party services like https://min.io/[MinIO]. +===== Configuring client configuration + +For some AWS service integrations you can configure Spring Cloud AWS to use custom `ClientConfiguration`. + +To override the default `ClientConfiguration` used by all integrations, create a bean of type `ClientConfiguration` with a name `com.amazonaws.ClientConfiguration.BEAN_NAME`. + +[source,java,indent=0] +---- +@Configuration +class CustomAwsConfiguration { + + @Bean(name = "com.amazonaws.ClientConfiguration.BEAN_NAME") + ClientConfiguration clientConfiguration() { + ClientConfiguration clientConfiguration= new ClientConfiguration(); + clientConfiguration.setProxyHost(proxyHost); + clientConfiguration.setProxyPort(proxyPort); + clientConfiguration.setProxyUsername(proxyUserName); + clientConfiguration.setProxyPassword(proxyPassword); + return clientConfiguration; + } +} +---- + +It's also possible to provide `ClientConfiguration` for particular integration by defining a bean of type `ClientConfiguration` and a name specific to the integration: + +[cols="2"] +|=== +| SQS +| `sqsClientConfiguration` + +| SNS +| `snsClientConfiguration` + +| SES +| `sesClientConfiguration` + +| RDS +| `rdsClientConfiguration` + +| ElastiCache +| `elastiCacheClientConfiguration` + +| CloudWatch +| `cloudWatchClientConfiguration` + +|=== + +For example: + +[source,java,indent=0] +---- +@Configuration +class CustomSqsConfiguration { + + @Bean + ClientConfiguration sqsClientConfiguration() { + ClientConfiguration clientConfiguration= new ClientConfiguration(); + clientConfiguration.setProxyHost(proxyHost); + clientConfiguration.setProxyPort(proxyPort); + clientConfiguration.setProxyUsername(proxyUserName); + clientConfiguration.setProxyPassword(proxyPassword); + return clientConfiguration; + } +} +---- + == Cloud environment Applications often need environment specific configuration information, especially in changing environments like in the Amazon cloud environment. Spring Cloud AWS provides a support to retrieve and use environment specific data inside the