Skip to content
This repository was archived by the owner on Jan 19, 2022. It is now read-only.

Add ability to provide custom client configuration #725

Merged
merged 15 commits into from
Dec 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 41 additions & 40 deletions docs/src/main/asciidoc/_configprops.adoc
Original file line number Diff line number Diff line change
@@ -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 <a href= "https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-long-polling.html">documentation</a>.
|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 <a href= "https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-long-polling.html">documentation</a>.
|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.

|===
|===
66 changes: 66 additions & 0 deletions docs/src/main/asciidoc/spring-cloud-aws.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -46,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
Expand All @@ -62,18 +66,24 @@ public class ElastiCacheAutoConfiguration {

private final ListableStackResourceFactory stackResourceFactory;

private final ClientConfiguration clientConfiguration;

public ElastiCacheAutoConfiguration(ElastiCacheProperties properties,
ObjectProvider<ListableStackResourceFactory> stackResourceFactory) {
ObjectProvider<ListableStackResourceFactory> stackResourceFactory,
@Qualifier(GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME) ObjectProvider<ClientConfiguration> globalClientConfiguration,
@Qualifier("elastiCacheClientConfiguration") ObjectProvider<ClientConfiguration> elastiCacheClientConfiguration) {
this.properties = properties;
this.stackResourceFactory = stackResourceFactory.getIfAvailable();
this.clientConfiguration = elastiCacheClientConfiguration
.getIfAvailable(globalClientConfiguration::getIfAvailable);
}

@Bean
@ConditionalOnMissingBean(AmazonElastiCache.class)
public AmazonWebserviceClientFactoryBean<AmazonElastiCacheClient> amazonElastiCache(
ObjectProvider<RegionProvider> regionProvider, ObjectProvider<AWSCredentialsProvider> credentialsProvider) {
return new AmazonWebserviceClientFactoryBean<>(AmazonElastiCacheClient.class,
credentialsProvider.getIfAvailable(), regionProvider.getIfAvailable());
credentialsProvider.getIfAvailable(), regionProvider.getIfAvailable(), clientConfiguration);
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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.
Expand All @@ -66,18 +70,24 @@ public class SesAutoConfiguration {

private final RegionProvider regionProvider;

private final ClientConfiguration clientConfiguration;

public SesAutoConfiguration(ObjectProvider<RegionProvider> regionProvider,
ObjectProvider<AWSCredentialsProvider> credentialsProvider, SesProperties properties) {
ObjectProvider<AWSCredentialsProvider> credentialsProvider,
@Qualifier(GLOBAL_CLIENT_CONFIGURATION_BEAN_NAME) ObjectProvider<ClientConfiguration> globalClientConfiguration,
@Qualifier("sesClientConfiguration") ObjectProvider<ClientConfiguration> 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<AmazonSimpleEmailServiceClient> amazonSimpleEmailService() {
return new AmazonWebserviceClientFactoryBean<>(AmazonSimpleEmailServiceClient.class, this.credentialsProvider,
this.regionProvider);
this.regionProvider, this.clientConfiguration);
}

@Bean
Expand Down
Loading