From 36aeed897e77058f4831f5b736cce3aec3a17ab1 Mon Sep 17 00:00:00 2001 From: krimsz Date: Tue, 5 Jul 2022 09:47:35 +0200 Subject: [PATCH 01/10] Rebase with upstream main --- spring-cloud-aws-autoconfigure/pom.xml | 5 ++++ .../autoconfigure/AwsClientProperties.java | 15 ++++++++++ ...AbstractAwsConfigDataLocationResolver.java | 29 ++++++++++++++++--- .../core/AwsAutoConfiguration.java | 18 ++++++++++++ .../core/AwsClientBuilderConfigurer.java | 19 ++++++++---- .../autoconfigure/core/AwsProperties.java | 19 ++++++++++-- .../SpringCloudClientConfigurationTests.java | 8 ++--- 7 files changed, 96 insertions(+), 17 deletions(-) diff --git a/spring-cloud-aws-autoconfigure/pom.xml b/spring-cloud-aws-autoconfigure/pom.xml index d4131c45c..1ce9c13e5 100644 --- a/spring-cloud-aws-autoconfigure/pom.xml +++ b/spring-cloud-aws-autoconfigure/pom.xml @@ -75,6 +75,11 @@ s3-transfer-manager true + + software.amazon.awssdk + cloudwatch-metric-publisher + true + io.awspring.cloud spring-cloud-aws-s3-cross-region-client diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/AwsClientProperties.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/AwsClientProperties.java index 6bee7a541..e3bbffa25 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/AwsClientProperties.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/AwsClientProperties.java @@ -37,6 +37,12 @@ public abstract class AwsClientProperties { @Nullable private String region; + /** + * Overrides the global enablement of the CloudWatch MetricsPublisher. + */ + @Nullable + private Boolean metricsEnabled; + @Nullable public URI getEndpoint() { return this.endpoint; @@ -54,4 +60,13 @@ public String getRegion() { public void setRegion(String region) { this.region = region; } + + @Nullable + public Boolean getMetricsEnabled() { + return metricsEnabled; + } + + public void setMetricsEnabled(@Nullable Boolean metricsEnabled) { + this.metricsEnabled = metricsEnabled; + } } diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/config/AbstractAwsConfigDataLocationResolver.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/config/AbstractAwsConfigDataLocationResolver.java index 50a32999b..7299c0f9a 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/config/AbstractAwsConfigDataLocationResolver.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/config/AbstractAwsConfigDataLocationResolver.java @@ -22,9 +22,6 @@ import io.awspring.cloud.autoconfigure.core.RegionProperties; import io.awspring.cloud.autoconfigure.core.RegionProviderAutoConfiguration; import io.awspring.cloud.core.SpringCloudClientConfiguration; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; import org.springframework.boot.BootstrapContext; import org.springframework.boot.BootstrapRegistry; import org.springframework.boot.ConfigurableBootstrapContext; @@ -40,9 +37,17 @@ import org.springframework.util.StringUtils; import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; import software.amazon.awssdk.awscore.client.builder.AwsClientBuilder; +import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +import software.amazon.awssdk.metrics.MetricPublisher; +import software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.regions.providers.AwsRegionProvider; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + /** * Base class for AWS specific {@link ConfigDataLocationResolver}s. * @@ -151,7 +156,23 @@ else if (awsProperties.getEndpoint() != null) { builder.endpointOverride(awsProperties.getEndpoint()); } builder.credentialsProvider(credentialsProvider); - builder.overrideConfiguration(new SpringCloudClientConfiguration().clientOverrideConfiguration()); + + Optional metricPublisher; + try { + Class.forName("software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher"); + metricPublisher = Optional.of(context.get(CloudWatchMetricPublisher.class)); + } + catch (IllegalStateException | ClassNotFoundException e) { + metricPublisher = Optional.empty(); + } + ClientOverrideConfiguration.Builder clientOverrideConfigurationBuilder = new SpringCloudClientConfiguration() + .clientOverrideConfigurationBuilder(); + if ((awsProperties.getMetricsEnabled() == null || awsProperties.getMetricsEnabled()) + && (properties.getMetricsEnabled() == null || properties.getMetricsEnabled()) + && metricPublisher.isPresent()) { + clientOverrideConfigurationBuilder.addMetricPublisher(metricPublisher.get()); + } + builder.overrideConfiguration(clientOverrideConfigurationBuilder.build()); return builder; } diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsAutoConfiguration.java index 3aa49f1e1..26da285f7 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsAutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsAutoConfiguration.java @@ -15,12 +15,20 @@ */ package io.awspring.cloud.autoconfigure.core; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; +import software.amazon.awssdk.metrics.LoggingMetricPublisher; +import software.amazon.awssdk.metrics.MetricPublisher; +import software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher; import software.amazon.awssdk.regions.providers.AwsRegionProvider; +import java.time.Duration; + /** * Autoconfigures AWS environment. * @@ -37,6 +45,16 @@ public AwsAutoConfiguration(AwsProperties awsProperties) { this.awsProperties = awsProperties; } + @ConditionalOnClass(CloudWatchMetricPublisher.class) + static class MetricsAutoConfiguration { + @Bean + @ConditionalOnMissingBean + @ConditionalOnProperty(name = "spring.cloud.aws.metrics-enabled", havingValue = "true", matchIfMissing = true) + MetricPublisher cloudWatchMetricPublisher() { + return CloudWatchMetricPublisher.builder().build(); + } + } + @Bean public AwsClientBuilderConfigurer awsClientBuilderConfigurer(AwsCredentialsProvider credentialsProvider, AwsRegionProvider awsRegionProvider) { diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsClientBuilderConfigurer.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsClientBuilderConfigurer.java index f55569c2f..b60a2e70f 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsClientBuilderConfigurer.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsClientBuilderConfigurer.java @@ -17,16 +17,18 @@ import io.awspring.cloud.autoconfigure.AwsClientProperties; import io.awspring.cloud.core.SpringCloudClientConfiguration; -import java.util.Optional; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.StringUtils; import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; import software.amazon.awssdk.awscore.client.builder.AwsClientBuilder; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +import software.amazon.awssdk.metrics.MetricPublisher; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.regions.providers.AwsRegionProvider; +import java.util.Optional; + /** * Provides a convenience method to apply common configuration to any {@link AwsClientBuilder}. * @@ -44,20 +46,24 @@ public class AwsClientBuilderConfigurer { this.credentialsProvider = credentialsProvider; this.regionProvider = regionProvider; this.awsProperties = awsProperties; - this.clientOverrideConfiguration = new SpringCloudClientConfiguration().clientOverrideConfiguration(); + this.clientOverrideConfiguration = new SpringCloudClientConfiguration() + .clientOverrideConfiguration(); } public > T configure(T builder) { - return configure(builder, null, null); + return configure(builder, null, null, null); } public > T configure(T builder, @Nullable AwsClientProperties clientProperties, - @Nullable AwsClientCustomizer customizer) { + @Nullable AwsClientCustomizer customizer, MetricPublisher metricPublisher) { + ClientOverrideConfiguration.Builder clientOverrideConfigurationBuilder = clientOverrideConfiguration.toBuilder(); Assert.notNull(builder, "builder is required"); Assert.notNull(clientProperties, "clientProperties are required"); - + if(metricPublisher != null) { + clientOverrideConfigurationBuilder.addMetricPublisher(metricPublisher).build(); + } builder.credentialsProvider(this.credentialsProvider).region(resolveRegion(clientProperties)) - .overrideConfiguration(this.clientOverrideConfiguration); + .overrideConfiguration(clientOverrideConfigurationBuilder.build()); Optional.ofNullable(this.awsProperties.getEndpoint()).ifPresent(builder::endpointOverride); Optional.ofNullable(clientProperties).map(AwsClientProperties::getEndpoint) .ifPresent(builder::endpointOverride); @@ -68,6 +74,7 @@ public class AwsClientBuilderConfigurer { if (customizer != null) { AwsClientCustomizer.apply(customizer, builder); } + return builder; } diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsProperties.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsProperties.java index 014ca6834..30535df6a 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsProperties.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsProperties.java @@ -15,13 +15,14 @@ */ package io.awspring.cloud.autoconfigure.core; -import static io.awspring.cloud.autoconfigure.core.AwsProperties.CONFIG_PREFIX; - -import java.net.URI; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.lang.Nullable; import software.amazon.awssdk.awscore.defaultsmode.DefaultsMode; +import java.net.URI; + +import static io.awspring.cloud.autoconfigure.core.AwsProperties.CONFIG_PREFIX; + /** * Configuration properties for AWS environment. * @@ -60,6 +61,9 @@ public class AwsProperties { @Nullable private Boolean fipsEnabled; + @Nullable + private Boolean metricsEnabled; + @Nullable public URI getEndpoint() { return this.endpoint; @@ -95,4 +99,13 @@ public Boolean getFipsEnabled() { public void setFipsEnabled(@Nullable Boolean fipsEnabled) { this.fipsEnabled = fipsEnabled; } + + @Nullable + public Boolean getMetricsEnabled() { + return metricsEnabled; + } + + public void setMetricsEnabled(@Nullable Boolean metricsEnabled) { + this.metricsEnabled = metricsEnabled; + } } diff --git a/spring-cloud-aws-core/src/test/java/io/awspring/cloud/core/SpringCloudClientConfigurationTests.java b/spring-cloud-aws-core/src/test/java/io/awspring/cloud/core/SpringCloudClientConfigurationTests.java index 91ea18932..5c9719857 100644 --- a/spring-cloud-aws-core/src/test/java/io/awspring/cloud/core/SpringCloudClientConfigurationTests.java +++ b/spring-cloud-aws-core/src/test/java/io/awspring/cloud/core/SpringCloudClientConfigurationTests.java @@ -30,11 +30,11 @@ class SpringCloudClientConfigurationTests { @Test void returnsClientConfigurationWithVersion() { - ClientOverrideConfiguration clientOverrideConfiguration = new SpringCloudClientConfiguration() - .clientOverrideConfiguration(); + ClientOverrideConfiguration.Builder clientOverrideConfigurationBuilder = new SpringCloudClientConfiguration() + .clientOverrideConfigurationBuilder(); - assertThat(clientOverrideConfiguration.advancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX)).isPresent() - .hasValueSatisfying(value -> { + assertThat(clientOverrideConfigurationBuilder.build().advancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX)) + .isPresent().hasValueSatisfying(value -> { assertThat(value).startsWith("spring-cloud-aws"); }); } From 5b0b9521221129e6b9abe8ecac4801ff2accbf91 Mon Sep 17 00:00:00 2001 From: krimsz Date: Tue, 5 Jul 2022 09:47:35 +0200 Subject: [PATCH 02/10] Create custom CloudWatchMetricPublishers for SecretsManager and ParameterStore --- .../AbstractAwsConfigDataLocationResolver.java | 16 +++++++++++++++- ...ParameterStoreConfigDataLocationResolver.java | 2 +- ...SecretsManagerConfigDataLocationResolver.java | 3 +-- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/config/AbstractAwsConfigDataLocationResolver.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/config/AbstractAwsConfigDataLocationResolver.java index 7299c0f9a..8f10b4aa5 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/config/AbstractAwsConfigDataLocationResolver.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/config/AbstractAwsConfigDataLocationResolver.java @@ -16,12 +16,15 @@ package io.awspring.cloud.autoconfigure.config; import io.awspring.cloud.autoconfigure.AwsClientProperties; +import io.awspring.cloud.autoconfigure.config.parameterstore.ParameterStorePropertySources; import io.awspring.cloud.autoconfigure.core.AwsProperties; import io.awspring.cloud.autoconfigure.core.CredentialsProperties; import io.awspring.cloud.autoconfigure.core.CredentialsProviderAutoConfiguration; import io.awspring.cloud.autoconfigure.core.RegionProperties; import io.awspring.cloud.autoconfigure.core.RegionProviderAutoConfiguration; import io.awspring.cloud.core.SpringCloudClientConfiguration; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.springframework.boot.BootstrapContext; import org.springframework.boot.BootstrapRegistry; import org.springframework.boot.ConfigurableBootstrapContext; @@ -160,7 +163,7 @@ else if (awsProperties.getEndpoint() != null) { Optional metricPublisher; try { Class.forName("software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher"); - metricPublisher = Optional.of(context.get(CloudWatchMetricPublisher.class)); + metricPublisher = Optional.of(context.get(MetricPublisher.class)); } catch (IllegalStateException | ClassNotFoundException e) { metricPublisher = Optional.empty(); @@ -176,4 +179,15 @@ else if (awsProperties.getEndpoint() != null) { return builder; } + protected void createMetricPublisher(ConfigDataLocationResolverContext resolverContext) { + try { + Class.forName("software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher"); + } + catch (IllegalStateException | ClassNotFoundException ignored) { + // ignored, means that the optional dependency is not in the classpath + return; + } + registerBean(resolverContext, MetricPublisher.class, CloudWatchMetricPublisher.builder().build()); + } + } diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/config/parameterstore/ParameterStoreConfigDataLocationResolver.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/config/parameterstore/ParameterStoreConfigDataLocationResolver.java index 569c47d53..5548b5b46 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/config/parameterstore/ParameterStoreConfigDataLocationResolver.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/config/parameterstore/ParameterStoreConfigDataLocationResolver.java @@ -65,7 +65,7 @@ public List resolveProfileSpecific( registerBean(resolverContext, CredentialsProperties.class, loadCredentialsProperties(resolverContext.getBinder())); registerBean(resolverContext, RegionProperties.class, loadRegionProperties(resolverContext.getBinder())); - + createMetricPublisher(resolverContext); registerAndPromoteBean(resolverContext, SsmClient.class, this::createSimpleSystemManagementClient); ParameterStorePropertySources sources = new ParameterStorePropertySources(); diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/config/secretsmanager/SecretsManagerConfigDataLocationResolver.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/config/secretsmanager/SecretsManagerConfigDataLocationResolver.java index 4c40cff61..32c779ec4 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/config/secretsmanager/SecretsManagerConfigDataLocationResolver.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/config/secretsmanager/SecretsManagerConfigDataLocationResolver.java @@ -69,9 +69,8 @@ public List resolveProfileSpecific( registerBean(resolverContext, CredentialsProperties.class, loadCredentialsProperties(resolverContext.getBinder())); registerBean(resolverContext, RegionProperties.class, loadRegionProperties(resolverContext.getBinder())); - + createMetricPublisher(resolverContext); registerAndPromoteBean(resolverContext, SecretsManagerClient.class, this::createAwsSecretsManagerClient); - SecretsManagerPropertySources propertySources = new SecretsManagerPropertySources(); List contexts = getCustomContexts(location.getNonPrefixedValue(PREFIX)); From 5c393fd8180743aab3b51ff954adeed78658e683 Mon Sep 17 00:00:00 2001 From: krimsz Date: Tue, 5 Jul 2022 09:47:35 +0200 Subject: [PATCH 03/10] Rework the existing metricsEnabled into a more complex object with extra properties --- .../autoconfigure/AwsClientProperties.java | 11 +- ...AbstractAwsConfigDataLocationResolver.java | 43 +- .../core/AwsAutoConfiguration.java | 3 - .../core/AwsClientBuilderConfigurer.java | 13 +- .../autoconfigure/core/AwsProperties.java | 26 +- .../CloudWatchMetricsPublisherProperties.java | 54 + .../dynamodb/DynamoDbAutoConfiguration.java | 8 +- .../CloudWatchExportAutoConfiguration.java | 8 +- .../autoconfigure/s3/S3AutoConfiguration.java | 6 +- .../ses/SesAutoConfiguration.java | 8 +- .../sns/SnsAutoConfiguration.java | 8 +- .../SpringCloudClientConfigurationTests.java | 8 +- .../s3/crossregion/CrossRegionS3Client.java | 1393 +++++++---------- 13 files changed, 721 insertions(+), 868 deletions(-) create mode 100644 spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/CloudWatchMetricsPublisherProperties.java diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/AwsClientProperties.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/AwsClientProperties.java index e3bbffa25..a7c85207e 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/AwsClientProperties.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/AwsClientProperties.java @@ -15,6 +15,7 @@ */ package io.awspring.cloud.autoconfigure; +import io.awspring.cloud.autoconfigure.core.CloudWatchMetricsPublisherProperties; import java.net.URI; import org.springframework.lang.Nullable; @@ -41,7 +42,7 @@ public abstract class AwsClientProperties { * Overrides the global enablement of the CloudWatch MetricsPublisher. */ @Nullable - private Boolean metricsEnabled; + private CloudWatchMetricsPublisherProperties metrics; @Nullable public URI getEndpoint() { @@ -62,11 +63,11 @@ public void setRegion(String region) { } @Nullable - public Boolean getMetricsEnabled() { - return metricsEnabled; + public CloudWatchMetricsPublisherProperties getMetrics() { + return metrics; } - public void setMetricsEnabled(@Nullable Boolean metricsEnabled) { - this.metricsEnabled = metricsEnabled; + public void setMetrics(@Nullable CloudWatchMetricsPublisherProperties metrics) { + this.metrics = metrics; } } diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/config/AbstractAwsConfigDataLocationResolver.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/config/AbstractAwsConfigDataLocationResolver.java index 8f10b4aa5..7f7aebfd9 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/config/AbstractAwsConfigDataLocationResolver.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/config/AbstractAwsConfigDataLocationResolver.java @@ -16,15 +16,16 @@ package io.awspring.cloud.autoconfigure.config; import io.awspring.cloud.autoconfigure.AwsClientProperties; -import io.awspring.cloud.autoconfigure.config.parameterstore.ParameterStorePropertySources; import io.awspring.cloud.autoconfigure.core.AwsProperties; import io.awspring.cloud.autoconfigure.core.CredentialsProperties; import io.awspring.cloud.autoconfigure.core.CredentialsProviderAutoConfiguration; import io.awspring.cloud.autoconfigure.core.RegionProperties; import io.awspring.cloud.autoconfigure.core.RegionProviderAutoConfiguration; import io.awspring.cloud.core.SpringCloudClientConfiguration; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; +import io.micrometer.core.lang.Nullable; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; import org.springframework.boot.BootstrapContext; import org.springframework.boot.BootstrapRegistry; import org.springframework.boot.ConfigurableBootstrapContext; @@ -42,15 +43,9 @@ import software.amazon.awssdk.awscore.client.builder.AwsClientBuilder; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.metrics.MetricPublisher; -import software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.regions.providers.AwsRegionProvider; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Optional; - /** * Base class for AWS specific {@link ConfigDataLocationResolver}s. * @@ -160,23 +155,27 @@ else if (awsProperties.getEndpoint() != null) { } builder.credentialsProvider(credentialsProvider); - Optional metricPublisher; + MetricPublisher metricPublisher = getMetricPublisher(context); + + if ((awsProperties.getMetrics() == null || awsProperties.getMetrics().getEnabled() == null + || (awsProperties.getMetrics().getEnabled() != null && awsProperties.getMetrics().getEnabled())) + && metricPublisher != null) { + ClientOverrideConfiguration.Builder clientOverrideConfigurationBuilder = new SpringCloudClientConfiguration() + .clientOverrideConfiguration().toBuilder(); + clientOverrideConfigurationBuilder.addMetricPublisher(metricPublisher); + builder.overrideConfiguration(clientOverrideConfigurationBuilder.build()); + } + return builder; + } + + private static @Nullable MetricPublisher getMetricPublisher(BootstrapContext context) { try { Class.forName("software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher"); - metricPublisher = Optional.of(context.get(MetricPublisher.class)); + return context.get(MetricPublisher.class); } catch (IllegalStateException | ClassNotFoundException e) { - metricPublisher = Optional.empty(); + return null; } - ClientOverrideConfiguration.Builder clientOverrideConfigurationBuilder = new SpringCloudClientConfiguration() - .clientOverrideConfigurationBuilder(); - if ((awsProperties.getMetricsEnabled() == null || awsProperties.getMetricsEnabled()) - && (properties.getMetricsEnabled() == null || properties.getMetricsEnabled()) - && metricPublisher.isPresent()) { - clientOverrideConfigurationBuilder.addMetricPublisher(metricPublisher.get()); - } - builder.overrideConfiguration(clientOverrideConfigurationBuilder.build()); - return builder; } protected void createMetricPublisher(ConfigDataLocationResolverContext resolverContext) { @@ -187,7 +186,7 @@ protected void createMetricPublisher(ConfigDataLocationResolverContext resolverC // ignored, means that the optional dependency is not in the classpath return; } - registerBean(resolverContext, MetricPublisher.class, CloudWatchMetricPublisher.builder().build()); + } } diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsAutoConfiguration.java index 26da285f7..fb8425d93 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsAutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsAutoConfiguration.java @@ -22,13 +22,10 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; -import software.amazon.awssdk.metrics.LoggingMetricPublisher; import software.amazon.awssdk.metrics.MetricPublisher; import software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher; import software.amazon.awssdk.regions.providers.AwsRegionProvider; -import java.time.Duration; - /** * Autoconfigures AWS environment. * diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsClientBuilderConfigurer.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsClientBuilderConfigurer.java index b60a2e70f..f734273e1 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsClientBuilderConfigurer.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsClientBuilderConfigurer.java @@ -17,6 +17,7 @@ import io.awspring.cloud.autoconfigure.AwsClientProperties; import io.awspring.cloud.core.SpringCloudClientConfiguration; +import java.util.Optional; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -27,8 +28,6 @@ import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.regions.providers.AwsRegionProvider; -import java.util.Optional; - /** * Provides a convenience method to apply common configuration to any {@link AwsClientBuilder}. * @@ -46,8 +45,7 @@ public class AwsClientBuilderConfigurer { this.credentialsProvider = credentialsProvider; this.regionProvider = regionProvider; this.awsProperties = awsProperties; - this.clientOverrideConfiguration = new SpringCloudClientConfiguration() - .clientOverrideConfiguration(); + this.clientOverrideConfiguration = new SpringCloudClientConfiguration().clientOverrideConfiguration(); } public > T configure(T builder) { @@ -56,14 +54,15 @@ public class AwsClientBuilderConfigurer { public > T configure(T builder, @Nullable AwsClientProperties clientProperties, @Nullable AwsClientCustomizer customizer, MetricPublisher metricPublisher) { - ClientOverrideConfiguration.Builder clientOverrideConfigurationBuilder = clientOverrideConfiguration.toBuilder(); + ClientOverrideConfiguration.Builder clientOverrideConfigurationBuilder = clientOverrideConfiguration + .toBuilder(); Assert.notNull(builder, "builder is required"); Assert.notNull(clientProperties, "clientProperties are required"); - if(metricPublisher != null) { + if (metricPublisher != null) { clientOverrideConfigurationBuilder.addMetricPublisher(metricPublisher).build(); } builder.credentialsProvider(this.credentialsProvider).region(resolveRegion(clientProperties)) - .overrideConfiguration(clientOverrideConfigurationBuilder.build()); + .overrideConfiguration(clientOverrideConfigurationBuilder.build()); Optional.ofNullable(this.awsProperties.getEndpoint()).ifPresent(builder::endpointOverride); Optional.ofNullable(clientProperties).map(AwsClientProperties::getEndpoint) .ifPresent(builder::endpointOverride); diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsProperties.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsProperties.java index 30535df6a..62e8d606f 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsProperties.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsProperties.java @@ -15,14 +15,14 @@ */ package io.awspring.cloud.autoconfigure.core; +import static io.awspring.cloud.autoconfigure.core.AwsProperties.CONFIG_PREFIX; + +import java.net.URI; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.NestedConfigurationProperty; import org.springframework.lang.Nullable; import software.amazon.awssdk.awscore.defaultsmode.DefaultsMode; -import java.net.URI; - -import static io.awspring.cloud.autoconfigure.core.AwsProperties.CONFIG_PREFIX; - /** * Configuration properties for AWS environment. * @@ -56,13 +56,17 @@ public class AwsProperties { private Boolean dualstackEnabled; /** - * Configure whether the SDK should use the AWS fips endpoints. + * Configure metrics properties to send to CloudWatch if needed */ + @NestedConfigurationProperty @Nullable - private Boolean fipsEnabled; + private CloudWatchMetricsPublisherProperties metrics; + /** + * Configure whether the SDK should use the AWS fips endpoints. + */ @Nullable - private Boolean metricsEnabled; + private Boolean fipsEnabled; @Nullable public URI getEndpoint() { @@ -101,11 +105,11 @@ public void setFipsEnabled(@Nullable Boolean fipsEnabled) { } @Nullable - public Boolean getMetricsEnabled() { - return metricsEnabled; + public CloudWatchMetricsPublisherProperties getMetrics() { + return metrics; } - public void setMetricsEnabled(@Nullable Boolean metricsEnabled) { - this.metricsEnabled = metricsEnabled; + public void setMetrics(@Nullable CloudWatchMetricsPublisherProperties metrics) { + this.metrics = metrics; } } diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/CloudWatchMetricsPublisherProperties.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/CloudWatchMetricsPublisherProperties.java new file mode 100644 index 000000000..828db06dd --- /dev/null +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/CloudWatchMetricsPublisherProperties.java @@ -0,0 +1,54 @@ +/* + * Copyright 2013-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.awspring.cloud.autoconfigure.core; + +import org.springframework.lang.Nullable; + +public class CloudWatchMetricsPublisherProperties { + @Nullable + Boolean enabled; + @Nullable + String namespace; + @Nullable + Long uploadFrequencyInSeconds; + + @Nullable + public Boolean getEnabled() { + return enabled; + } + + public void setEnabled(@Nullable Boolean enabled) { + this.enabled = enabled; + } + + @Nullable + public String getNamespace() { + return namespace; + } + + public void setNamespace(@Nullable String namespace) { + this.namespace = namespace; + } + + @Nullable + public Long getUploadFrequencyInSeconds() { + return uploadFrequencyInSeconds; + } + + public void setUploadFrequencyInSeconds(@Nullable Long uploadFrequencyInSeconds) { + this.uploadFrequencyInSeconds = uploadFrequencyInSeconds; + } +} diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfiguration.java index 246a7f71b..793767e85 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfiguration.java @@ -31,6 +31,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient; +import software.amazon.awssdk.metrics.MetricPublisher; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.services.dynamodb.DynamoDbClientBuilder; @@ -56,9 +57,10 @@ public DynamoDbAutoConfiguration(DynamoDbProperties properties) { @ConditionalOnMissingBean @Bean public DynamoDbClient dynamoDbClient(AwsClientBuilderConfigurer awsClientBuilderConfigurer, - ObjectProvider> configurer) { - return awsClientBuilderConfigurer.configure(DynamoDbClient.builder(), properties, configurer.getIfAvailable()) - .build(); + ObjectProvider> configurer, + ObjectProvider metricPublisher) { + return awsClientBuilderConfigurer.configure(DynamoDbClient.builder(), properties, configurer.getIfAvailable(), + metricPublisher.getIfAvailable()).build(); } @ConditionalOnMissingBean diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/metrics/CloudWatchExportAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/metrics/CloudWatchExportAutoConfiguration.java index a3881c9ee..d7fff4ab3 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/metrics/CloudWatchExportAutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/metrics/CloudWatchExportAutoConfiguration.java @@ -34,6 +34,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import software.amazon.awssdk.metrics.MetricPublisher; import software.amazon.awssdk.regions.providers.AwsRegionProvider; import software.amazon.awssdk.services.cloudwatch.CloudWatchAsyncClient; import software.amazon.awssdk.services.cloudwatch.CloudWatchAsyncClientBuilder; @@ -67,9 +68,10 @@ public CloudWatchMeterRegistry cloudWatchMeterRegistry(CloudWatchConfig config, @ConditionalOnMissingBean public CloudWatchAsyncClient cloudWatchAsyncClient(CloudWatchProperties properties, AwsClientBuilderConfigurer awsClientBuilderConfigurer, - ObjectProvider> configurer) { - return awsClientBuilderConfigurer - .configure(CloudWatchAsyncClient.builder(), properties, configurer.getIfAvailable()).build(); + ObjectProvider> configurer, + ObjectProvider metricPublisher) { + return awsClientBuilderConfigurer.configure(CloudWatchAsyncClient.builder(), properties, + configurer.getIfAvailable(), metricPublisher.getIfAvailable()).build(); } @Bean diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/S3AutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/S3AutoConfiguration.java index c670caeda..e4337a4e5 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/S3AutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/S3AutoConfiguration.java @@ -43,6 +43,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import software.amazon.awssdk.metrics.MetricPublisher; import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.s3.S3ClientBuilder; import software.amazon.awssdk.services.s3.S3Configuration; @@ -68,9 +69,10 @@ public S3AutoConfiguration(S3Properties properties) { @Bean @ConditionalOnMissingBean S3ClientBuilder s3ClientBuilder(AwsClientBuilderConfigurer awsClientBuilderConfigurer, - ObjectProvider> configurer) { + ObjectProvider> configurer, + ObjectProvider metricPublisher) { S3ClientBuilder builder = awsClientBuilderConfigurer.configure(S3Client.builder(), this.properties, - configurer.getIfAvailable()); + configurer.getIfAvailable(), metricPublisher.getIfAvailable()); builder.serviceConfiguration(s3ServiceConfiguration()); return builder; } diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/ses/SesAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/ses/SesAutoConfiguration.java index 5fb865fcf..cacb26d05 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/ses/SesAutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/ses/SesAutoConfiguration.java @@ -33,6 +33,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.mail.MailSender; import org.springframework.mail.javamail.JavaMailSender; +import software.amazon.awssdk.metrics.MetricPublisher; import software.amazon.awssdk.services.ses.SesClient; import software.amazon.awssdk.services.ses.SesClientBuilder; @@ -54,9 +55,10 @@ public class SesAutoConfiguration { @Bean @ConditionalOnMissingBean public SesClient sesClient(SesProperties properties, AwsClientBuilderConfigurer awsClientBuilderConfigurer, - ObjectProvider> configurer) { - return awsClientBuilderConfigurer.configure(SesClient.builder(), properties, configurer.getIfAvailable()) - .build(); + ObjectProvider> configurer, + ObjectProvider metricPublisher) { + return awsClientBuilderConfigurer.configure(SesClient.builder(), properties, configurer.getIfAvailable(), + metricPublisher.getIfAvailable()).build(); } @Bean diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/sns/SnsAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/sns/SnsAutoConfiguration.java index 1708095a4..23e50c395 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/sns/SnsAutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/sns/SnsAutoConfiguration.java @@ -38,6 +38,7 @@ import org.springframework.messaging.converter.MappingJackson2MessageConverter; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import software.amazon.awssdk.metrics.MetricPublisher; import software.amazon.awssdk.services.sns.SnsClient; import software.amazon.awssdk.services.sns.SnsClientBuilder; @@ -61,9 +62,10 @@ public class SnsAutoConfiguration { @ConditionalOnMissingBean @Bean public SnsClient snsClient(SnsProperties properties, AwsClientBuilderConfigurer awsClientBuilderConfigurer, - ObjectProvider> configurer) { - return awsClientBuilderConfigurer.configure(SnsClient.builder(), properties, configurer.getIfAvailable()) - .build(); + ObjectProvider> configurer, + ObjectProvider metricPublisher) { + return awsClientBuilderConfigurer.configure(SnsClient.builder(), properties, configurer.getIfAvailable(), + metricPublisher.getIfAvailable()).build(); } @ConditionalOnMissingBean diff --git a/spring-cloud-aws-core/src/test/java/io/awspring/cloud/core/SpringCloudClientConfigurationTests.java b/spring-cloud-aws-core/src/test/java/io/awspring/cloud/core/SpringCloudClientConfigurationTests.java index 5c9719857..91ea18932 100644 --- a/spring-cloud-aws-core/src/test/java/io/awspring/cloud/core/SpringCloudClientConfigurationTests.java +++ b/spring-cloud-aws-core/src/test/java/io/awspring/cloud/core/SpringCloudClientConfigurationTests.java @@ -30,11 +30,11 @@ class SpringCloudClientConfigurationTests { @Test void returnsClientConfigurationWithVersion() { - ClientOverrideConfiguration.Builder clientOverrideConfigurationBuilder = new SpringCloudClientConfiguration() - .clientOverrideConfigurationBuilder(); + ClientOverrideConfiguration clientOverrideConfiguration = new SpringCloudClientConfiguration() + .clientOverrideConfiguration(); - assertThat(clientOverrideConfigurationBuilder.build().advancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX)) - .isPresent().hasValueSatisfying(value -> { + assertThat(clientOverrideConfiguration.advancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX)).isPresent() + .hasValueSatisfying(value -> { assertThat(value).startsWith("spring-cloud-aws"); }); } diff --git a/spring-cloud-aws-s3-parent/spring-cloud-aws-s3-cross-region-client/src/main/java/io/awspring/cloud/s3/crossregion/CrossRegionS3Client.java b/spring-cloud-aws-s3-parent/spring-cloud-aws-s3-cross-region-client/src/main/java/io/awspring/cloud/s3/crossregion/CrossRegionS3Client.java index bbda6fdb8..c0d604a42 100644 --- a/spring-cloud-aws-s3-parent/spring-cloud-aws-s3-cross-region-client/src/main/java/io/awspring/cloud/s3/crossregion/CrossRegionS3Client.java +++ b/spring-cloud-aws-s3-parent/spring-cloud-aws-s3-cross-region-client/src/main/java/io/awspring/cloud/s3/crossregion/CrossRegionS3Client.java @@ -38,806 +38,595 @@ public class CrossRegionS3Client implements S3Client { - private static final Logger LOGGER = LoggerFactory.getLogger("io.awspring.cloud.s3.CrossRegionS3Client"); - - private static final int DEFAULT_BUCKET_CACHE_SIZE = 20; - - private final Map clientCache = new ConcurrentHashMap<>(Region.regions().size()); - - private final S3Client defaultS3Client; - - private final ConcurrentLruCache bucketCache; - - public CrossRegionS3Client(S3ClientBuilder clientBuilder) { - this(DEFAULT_BUCKET_CACHE_SIZE, clientBuilder); - } - - public CrossRegionS3Client(int bucketCacheSize, S3ClientBuilder clientBuilder) { - this.defaultS3Client = clientBuilder.build(); - this.bucketCache = new ConcurrentLruCache<>(bucketCacheSize, bucket -> { - Region region = resolveBucketRegion(bucket); - return clientCache.computeIfAbsent(region, r -> { - LOGGER.debug("Creating new S3 client for region: {}", r); - return clientBuilder.region(r).build(); - }); - }); - } - - @Override - public ListBucketsResponse listBuckets(ListBucketsRequest request) throws AwsServiceException, SdkClientException { - return defaultS3Client.listBuckets(request); - } - - @Override - public WriteGetObjectResponseResponse writeGetObjectResponse(WriteGetObjectResponseRequest request, - RequestBody requestBody) throws AwsServiceException, SdkClientException { - return defaultS3Client.writeGetObjectResponse(request, requestBody); - } - - // visible for testing - Map getClientCache() { - return clientCache; - } - - private Result executeInBucketRegion(String bucket, Function fn) { - try { - if (bucketCache.contains(bucket)) { - return fn.apply(bucketCache.get(bucket)); - } - else { - return fn.apply(defaultS3Client); - } - } - catch (S3Exception e) { - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Exception when requesting S3: {}", e.awsErrorDetails().errorCode(), e); - } - else { - LOGGER.debug("Exception when requesting S3 for bucket: {}: [{}] {}", bucket, - e.awsErrorDetails().errorCode(), e.awsErrorDetails().errorMessage()); - } - // "PermanentRedirect" means that the bucket is in different region than the - // defaultS3Client is configured for - if ("PermanentRedirect".equals(e.awsErrorDetails().errorCode())) { - return fn.apply(bucketCache.get(bucket)); - } - else { - throw e; - } - } - } - - private Region resolveBucketRegion(String bucket) { - LOGGER.debug("Resolving region for bucket {}", bucket); - String bucketLocation = defaultS3Client - .getBucketLocation(GetBucketLocationRequest.builder().bucket(bucket).build()) - .locationConstraintAsString(); - Region region = StringUtils.hasLength(bucketLocation) ? Region.of(bucketLocation) : Region.US_EAST_1; - LOGGER.debug("Region for bucket {} is {}", bucket, region); - return region; - } - - @Override - public String serviceName() { - return S3Client.SERVICE_NAME; - } - - @Override - public void close() { - this.clientCache.values().forEach(SdkAutoCloseable::close); - } - - @Override - public software.amazon.awssdk.services.s3.model.AbortMultipartUploadResponse abortMultipartUpload( - software.amazon.awssdk.services.s3.model.AbortMultipartUploadRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.abortMultipartUpload(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.CompleteMultipartUploadResponse completeMultipartUpload( - software.amazon.awssdk.services.s3.model.CompleteMultipartUploadRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.completeMultipartUpload(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.CopyObjectResponse copyObject( - software.amazon.awssdk.services.s3.model.CopyObjectRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.copyObject(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.CreateBucketResponse createBucket( - software.amazon.awssdk.services.s3.model.CreateBucketRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.createBucket(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.CreateMultipartUploadResponse createMultipartUpload( - software.amazon.awssdk.services.s3.model.CreateMultipartUploadRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.createMultipartUpload(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.DeleteBucketResponse deleteBucket( - software.amazon.awssdk.services.s3.model.DeleteBucketRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucket(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.DeleteBucketAnalyticsConfigurationResponse deleteBucketAnalyticsConfiguration( - software.amazon.awssdk.services.s3.model.DeleteBucketAnalyticsConfigurationRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketAnalyticsConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.DeleteBucketCorsResponse deleteBucketCors( - software.amazon.awssdk.services.s3.model.DeleteBucketCorsRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketCors(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.DeleteBucketEncryptionResponse deleteBucketEncryption( - software.amazon.awssdk.services.s3.model.DeleteBucketEncryptionRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketEncryption(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.DeleteBucketIntelligentTieringConfigurationResponse deleteBucketIntelligentTieringConfiguration( - software.amazon.awssdk.services.s3.model.DeleteBucketIntelligentTieringConfigurationRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketIntelligentTieringConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.DeleteBucketInventoryConfigurationResponse deleteBucketInventoryConfiguration( - software.amazon.awssdk.services.s3.model.DeleteBucketInventoryConfigurationRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketInventoryConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.DeleteBucketLifecycleResponse deleteBucketLifecycle( - software.amazon.awssdk.services.s3.model.DeleteBucketLifecycleRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketLifecycle(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.DeleteBucketMetricsConfigurationResponse deleteBucketMetricsConfiguration( - software.amazon.awssdk.services.s3.model.DeleteBucketMetricsConfigurationRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketMetricsConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.DeleteBucketOwnershipControlsResponse deleteBucketOwnershipControls( - software.amazon.awssdk.services.s3.model.DeleteBucketOwnershipControlsRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketOwnershipControls(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.DeleteBucketPolicyResponse deleteBucketPolicy( - software.amazon.awssdk.services.s3.model.DeleteBucketPolicyRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketPolicy(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.DeleteBucketReplicationResponse deleteBucketReplication( - software.amazon.awssdk.services.s3.model.DeleteBucketReplicationRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketReplication(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.DeleteBucketTaggingResponse deleteBucketTagging( - software.amazon.awssdk.services.s3.model.DeleteBucketTaggingRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketTagging(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.DeleteBucketWebsiteResponse deleteBucketWebsite( - software.amazon.awssdk.services.s3.model.DeleteBucketWebsiteRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketWebsite(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.DeleteObjectResponse deleteObject( - software.amazon.awssdk.services.s3.model.DeleteObjectRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteObject(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.DeleteObjectTaggingResponse deleteObjectTagging( - software.amazon.awssdk.services.s3.model.DeleteObjectTaggingRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteObjectTagging(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.DeleteObjectsResponse deleteObjects( - software.amazon.awssdk.services.s3.model.DeleteObjectsRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteObjects(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.DeletePublicAccessBlockResponse deletePublicAccessBlock( - software.amazon.awssdk.services.s3.model.DeletePublicAccessBlockRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deletePublicAccessBlock(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketAccelerateConfigurationResponse getBucketAccelerateConfiguration( - software.amazon.awssdk.services.s3.model.GetBucketAccelerateConfigurationRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketAccelerateConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketAclResponse getBucketAcl( - software.amazon.awssdk.services.s3.model.GetBucketAclRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketAcl(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketAnalyticsConfigurationResponse getBucketAnalyticsConfiguration( - software.amazon.awssdk.services.s3.model.GetBucketAnalyticsConfigurationRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketAnalyticsConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketCorsResponse getBucketCors( - software.amazon.awssdk.services.s3.model.GetBucketCorsRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketCors(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketEncryptionResponse getBucketEncryption( - software.amazon.awssdk.services.s3.model.GetBucketEncryptionRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketEncryption(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketIntelligentTieringConfigurationResponse getBucketIntelligentTieringConfiguration( - software.amazon.awssdk.services.s3.model.GetBucketIntelligentTieringConfigurationRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketIntelligentTieringConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketInventoryConfigurationResponse getBucketInventoryConfiguration( - software.amazon.awssdk.services.s3.model.GetBucketInventoryConfigurationRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketInventoryConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketLifecycleConfigurationResponse getBucketLifecycleConfiguration( - software.amazon.awssdk.services.s3.model.GetBucketLifecycleConfigurationRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketLifecycleConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketLocationResponse getBucketLocation( - software.amazon.awssdk.services.s3.model.GetBucketLocationRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketLocation(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketLoggingResponse getBucketLogging( - software.amazon.awssdk.services.s3.model.GetBucketLoggingRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketLogging(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketMetricsConfigurationResponse getBucketMetricsConfiguration( - software.amazon.awssdk.services.s3.model.GetBucketMetricsConfigurationRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketMetricsConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketNotificationConfigurationResponse getBucketNotificationConfiguration( - software.amazon.awssdk.services.s3.model.GetBucketNotificationConfigurationRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketNotificationConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketOwnershipControlsResponse getBucketOwnershipControls( - software.amazon.awssdk.services.s3.model.GetBucketOwnershipControlsRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketOwnershipControls(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketPolicyResponse getBucketPolicy( - software.amazon.awssdk.services.s3.model.GetBucketPolicyRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketPolicy(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketPolicyStatusResponse getBucketPolicyStatus( - software.amazon.awssdk.services.s3.model.GetBucketPolicyStatusRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketPolicyStatus(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketReplicationResponse getBucketReplication( - software.amazon.awssdk.services.s3.model.GetBucketReplicationRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketReplication(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketRequestPaymentResponse getBucketRequestPayment( - software.amazon.awssdk.services.s3.model.GetBucketRequestPaymentRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketRequestPayment(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketTaggingResponse getBucketTagging( - software.amazon.awssdk.services.s3.model.GetBucketTaggingRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketTagging(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketVersioningResponse getBucketVersioning( - software.amazon.awssdk.services.s3.model.GetBucketVersioningRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketVersioning(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketWebsiteResponse getBucketWebsite( - software.amazon.awssdk.services.s3.model.GetBucketWebsiteRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketWebsite(p0)); - } - - @Override - public software.amazon.awssdk.core.ResponseInputStream getObject( - software.amazon.awssdk.services.s3.model.GetObjectRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObject(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetObjectResponse getObject( - software.amazon.awssdk.services.s3.model.GetObjectRequest p0, java.nio.file.Path p1) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObject(p0, p1)); - } - - @Override - public ReturnT getObject(software.amazon.awssdk.services.s3.model.GetObjectRequest p0, - software.amazon.awssdk.core.sync.ResponseTransformer p1) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObject(p0, p1)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetObjectAclResponse getObjectAcl( - software.amazon.awssdk.services.s3.model.GetObjectAclRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectAcl(p0)); - } - - @Override - public software.amazon.awssdk.core.ResponseBytes getObjectAsBytes( - software.amazon.awssdk.services.s3.model.GetObjectRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectAsBytes(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetObjectAttributesResponse getObjectAttributes( - software.amazon.awssdk.services.s3.model.GetObjectAttributesRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectAttributes(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetObjectLegalHoldResponse getObjectLegalHold( - software.amazon.awssdk.services.s3.model.GetObjectLegalHoldRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectLegalHold(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetObjectLockConfigurationResponse getObjectLockConfiguration( - software.amazon.awssdk.services.s3.model.GetObjectLockConfigurationRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectLockConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetObjectRetentionResponse getObjectRetention( - software.amazon.awssdk.services.s3.model.GetObjectRetentionRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectRetention(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetObjectTaggingResponse getObjectTagging( - software.amazon.awssdk.services.s3.model.GetObjectTaggingRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectTagging(p0)); - } - - @Override - public software.amazon.awssdk.core.ResponseInputStream getObjectTorrent( - software.amazon.awssdk.services.s3.model.GetObjectTorrentRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectTorrent(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetObjectTorrentResponse getObjectTorrent( - software.amazon.awssdk.services.s3.model.GetObjectTorrentRequest p0, java.nio.file.Path p1) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectTorrent(p0, p1)); - } - - @Override - public ReturnT getObjectTorrent(software.amazon.awssdk.services.s3.model.GetObjectTorrentRequest p0, - software.amazon.awssdk.core.sync.ResponseTransformer p1) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectTorrent(p0, p1)); - } - - @Override - public software.amazon.awssdk.core.ResponseBytes getObjectTorrentAsBytes( - software.amazon.awssdk.services.s3.model.GetObjectTorrentRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectTorrentAsBytes(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetPublicAccessBlockResponse getPublicAccessBlock( - software.amazon.awssdk.services.s3.model.GetPublicAccessBlockRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getPublicAccessBlock(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.HeadBucketResponse headBucket( - software.amazon.awssdk.services.s3.model.HeadBucketRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.headBucket(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.HeadObjectResponse headObject( - software.amazon.awssdk.services.s3.model.HeadObjectRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.headObject(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.ListBucketAnalyticsConfigurationsResponse listBucketAnalyticsConfigurations( - software.amazon.awssdk.services.s3.model.ListBucketAnalyticsConfigurationsRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listBucketAnalyticsConfigurations(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.ListBucketIntelligentTieringConfigurationsResponse listBucketIntelligentTieringConfigurations( - software.amazon.awssdk.services.s3.model.ListBucketIntelligentTieringConfigurationsRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listBucketIntelligentTieringConfigurations(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.ListBucketInventoryConfigurationsResponse listBucketInventoryConfigurations( - software.amazon.awssdk.services.s3.model.ListBucketInventoryConfigurationsRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listBucketInventoryConfigurations(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.ListBucketMetricsConfigurationsResponse listBucketMetricsConfigurations( - software.amazon.awssdk.services.s3.model.ListBucketMetricsConfigurationsRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listBucketMetricsConfigurations(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.ListMultipartUploadsResponse listMultipartUploads( - software.amazon.awssdk.services.s3.model.ListMultipartUploadsRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listMultipartUploads(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.paginators.ListMultipartUploadsIterable listMultipartUploadsPaginator( - software.amazon.awssdk.services.s3.model.ListMultipartUploadsRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listMultipartUploadsPaginator(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.ListObjectVersionsResponse listObjectVersions( - software.amazon.awssdk.services.s3.model.ListObjectVersionsRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listObjectVersions(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.paginators.ListObjectVersionsIterable listObjectVersionsPaginator( - software.amazon.awssdk.services.s3.model.ListObjectVersionsRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listObjectVersionsPaginator(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.ListObjectsResponse listObjects( - software.amazon.awssdk.services.s3.model.ListObjectsRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listObjects(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.ListObjectsV2Response listObjectsV2( - software.amazon.awssdk.services.s3.model.ListObjectsV2Request p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listObjectsV2(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.paginators.ListObjectsV2Iterable listObjectsV2Paginator( - software.amazon.awssdk.services.s3.model.ListObjectsV2Request p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listObjectsV2Paginator(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.ListPartsResponse listParts( - software.amazon.awssdk.services.s3.model.ListPartsRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listParts(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.paginators.ListPartsIterable listPartsPaginator( - software.amazon.awssdk.services.s3.model.ListPartsRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listPartsPaginator(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutBucketAccelerateConfigurationResponse putBucketAccelerateConfiguration( - software.amazon.awssdk.services.s3.model.PutBucketAccelerateConfigurationRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketAccelerateConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutBucketAclResponse putBucketAcl( - software.amazon.awssdk.services.s3.model.PutBucketAclRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketAcl(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutBucketAnalyticsConfigurationResponse putBucketAnalyticsConfiguration( - software.amazon.awssdk.services.s3.model.PutBucketAnalyticsConfigurationRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketAnalyticsConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutBucketCorsResponse putBucketCors( - software.amazon.awssdk.services.s3.model.PutBucketCorsRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketCors(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutBucketEncryptionResponse putBucketEncryption( - software.amazon.awssdk.services.s3.model.PutBucketEncryptionRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketEncryption(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutBucketIntelligentTieringConfigurationResponse putBucketIntelligentTieringConfiguration( - software.amazon.awssdk.services.s3.model.PutBucketIntelligentTieringConfigurationRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketIntelligentTieringConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutBucketInventoryConfigurationResponse putBucketInventoryConfiguration( - software.amazon.awssdk.services.s3.model.PutBucketInventoryConfigurationRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketInventoryConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutBucketLifecycleConfigurationResponse putBucketLifecycleConfiguration( - software.amazon.awssdk.services.s3.model.PutBucketLifecycleConfigurationRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketLifecycleConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutBucketLoggingResponse putBucketLogging( - software.amazon.awssdk.services.s3.model.PutBucketLoggingRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketLogging(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutBucketMetricsConfigurationResponse putBucketMetricsConfiguration( - software.amazon.awssdk.services.s3.model.PutBucketMetricsConfigurationRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketMetricsConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutBucketNotificationConfigurationResponse putBucketNotificationConfiguration( - software.amazon.awssdk.services.s3.model.PutBucketNotificationConfigurationRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketNotificationConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutBucketOwnershipControlsResponse putBucketOwnershipControls( - software.amazon.awssdk.services.s3.model.PutBucketOwnershipControlsRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketOwnershipControls(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutBucketPolicyResponse putBucketPolicy( - software.amazon.awssdk.services.s3.model.PutBucketPolicyRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketPolicy(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutBucketReplicationResponse putBucketReplication( - software.amazon.awssdk.services.s3.model.PutBucketReplicationRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketReplication(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutBucketRequestPaymentResponse putBucketRequestPayment( - software.amazon.awssdk.services.s3.model.PutBucketRequestPaymentRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketRequestPayment(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutBucketTaggingResponse putBucketTagging( - software.amazon.awssdk.services.s3.model.PutBucketTaggingRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketTagging(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutBucketVersioningResponse putBucketVersioning( - software.amazon.awssdk.services.s3.model.PutBucketVersioningRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketVersioning(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutBucketWebsiteResponse putBucketWebsite( - software.amazon.awssdk.services.s3.model.PutBucketWebsiteRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketWebsite(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutObjectResponse putObject( - software.amazon.awssdk.services.s3.model.PutObjectRequest p0, java.nio.file.Path p1) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putObject(p0, p1)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutObjectResponse putObject( - software.amazon.awssdk.services.s3.model.PutObjectRequest p0, - software.amazon.awssdk.core.sync.RequestBody p1) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putObject(p0, p1)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutObjectAclResponse putObjectAcl( - software.amazon.awssdk.services.s3.model.PutObjectAclRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putObjectAcl(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutObjectLegalHoldResponse putObjectLegalHold( - software.amazon.awssdk.services.s3.model.PutObjectLegalHoldRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putObjectLegalHold(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutObjectLockConfigurationResponse putObjectLockConfiguration( - software.amazon.awssdk.services.s3.model.PutObjectLockConfigurationRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putObjectLockConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutObjectRetentionResponse putObjectRetention( - software.amazon.awssdk.services.s3.model.PutObjectRetentionRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putObjectRetention(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutObjectTaggingResponse putObjectTagging( - software.amazon.awssdk.services.s3.model.PutObjectTaggingRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putObjectTagging(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutPublicAccessBlockResponse putPublicAccessBlock( - software.amazon.awssdk.services.s3.model.PutPublicAccessBlockRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putPublicAccessBlock(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.RestoreObjectResponse restoreObject( - software.amazon.awssdk.services.s3.model.RestoreObjectRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.restoreObject(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.UploadPartResponse uploadPart( - software.amazon.awssdk.services.s3.model.UploadPartRequest p0, java.nio.file.Path p1) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.uploadPart(p0, p1)); - } - - @Override - public software.amazon.awssdk.services.s3.model.UploadPartResponse uploadPart( - software.amazon.awssdk.services.s3.model.UploadPartRequest p0, - software.amazon.awssdk.core.sync.RequestBody p1) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.uploadPart(p0, p1)); - } - - @Override - public software.amazon.awssdk.services.s3.model.UploadPartCopyResponse uploadPartCopy( - software.amazon.awssdk.services.s3.model.UploadPartCopyRequest p0) - throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.uploadPartCopy(p0)); - } + private static final Logger LOGGER = LoggerFactory.getLogger("io.awspring.cloud.s3.CrossRegionS3Client"); + + private static final int DEFAULT_BUCKET_CACHE_SIZE = 20; + + private final Map clientCache = new ConcurrentHashMap<>(Region.regions().size()); + + private final S3Client defaultS3Client; + + private final ConcurrentLruCache bucketCache; + + public CrossRegionS3Client(S3ClientBuilder clientBuilder) { + this(DEFAULT_BUCKET_CACHE_SIZE, clientBuilder); + } + + public CrossRegionS3Client(int bucketCacheSize, S3ClientBuilder clientBuilder) { + this.defaultS3Client = clientBuilder.build(); + this.bucketCache = new ConcurrentLruCache<>(bucketCacheSize, bucket -> { + Region region = resolveBucketRegion(bucket); + return clientCache.computeIfAbsent(region, r -> { + LOGGER.debug("Creating new S3 client for region: {}", r); + return clientBuilder.region(r).build(); + }); + }); + } + + @Override + public ListBucketsResponse listBuckets(ListBucketsRequest request) throws AwsServiceException, SdkClientException { + return defaultS3Client.listBuckets(request); + } + + @Override + public WriteGetObjectResponseResponse writeGetObjectResponse(WriteGetObjectResponseRequest request, RequestBody requestBody) throws AwsServiceException, SdkClientException { + return defaultS3Client.writeGetObjectResponse(request, requestBody); + } + + // visible for testing + Map getClientCache() { + return clientCache; + } + + private Result executeInBucketRegion(String bucket, Function fn) { + try { + if (bucketCache.contains(bucket)) { + return fn.apply(bucketCache.get(bucket)); + } else { + return fn.apply(defaultS3Client); + } + } catch (S3Exception e) { + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Exception when requesting S3: {}", e.awsErrorDetails().errorCode(), e); + } else { + LOGGER.debug("Exception when requesting S3 for bucket: {}: [{}] {}", bucket, e.awsErrorDetails().errorCode(), e.awsErrorDetails().errorMessage()); + } + // "PermanentRedirect" means that the bucket is in different region than the + // defaultS3Client is configured for + if ("PermanentRedirect".equals(e.awsErrorDetails().errorCode())) { + return fn.apply(bucketCache.get(bucket)); + } else { + throw e; + } + } + } + + private Region resolveBucketRegion(String bucket) { + LOGGER.debug("Resolving region for bucket {}", bucket); + String bucketLocation = defaultS3Client.getBucketLocation(GetBucketLocationRequest.builder().bucket(bucket).build()).locationConstraintAsString(); + Region region = StringUtils.hasLength(bucketLocation) ? Region.of(bucketLocation) : Region.US_EAST_1; + LOGGER.debug("Region for bucket {} is {}", bucket, region); + return region; + } + + @Override + public String serviceName() { + return S3Client.SERVICE_NAME; + } + + @Override + public void close() { + this.clientCache.values().forEach(SdkAutoCloseable::close); + } + + @Override + public software.amazon.awssdk.services.s3.model.AbortMultipartUploadResponse abortMultipartUpload(software.amazon.awssdk.services.s3.model.AbortMultipartUploadRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.abortMultipartUpload(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.CompleteMultipartUploadResponse completeMultipartUpload(software.amazon.awssdk.services.s3.model.CompleteMultipartUploadRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.completeMultipartUpload(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.CopyObjectResponse copyObject(software.amazon.awssdk.services.s3.model.CopyObjectRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.copyObject(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.CreateBucketResponse createBucket(software.amazon.awssdk.services.s3.model.CreateBucketRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.createBucket(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.CreateMultipartUploadResponse createMultipartUpload(software.amazon.awssdk.services.s3.model.CreateMultipartUploadRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.createMultipartUpload(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.DeleteBucketResponse deleteBucket(software.amazon.awssdk.services.s3.model.DeleteBucketRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucket(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.DeleteBucketAnalyticsConfigurationResponse deleteBucketAnalyticsConfiguration(software.amazon.awssdk.services.s3.model.DeleteBucketAnalyticsConfigurationRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketAnalyticsConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.DeleteBucketCorsResponse deleteBucketCors(software.amazon.awssdk.services.s3.model.DeleteBucketCorsRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketCors(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.DeleteBucketEncryptionResponse deleteBucketEncryption(software.amazon.awssdk.services.s3.model.DeleteBucketEncryptionRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketEncryption(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.DeleteBucketIntelligentTieringConfigurationResponse deleteBucketIntelligentTieringConfiguration(software.amazon.awssdk.services.s3.model.DeleteBucketIntelligentTieringConfigurationRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketIntelligentTieringConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.DeleteBucketInventoryConfigurationResponse deleteBucketInventoryConfiguration(software.amazon.awssdk.services.s3.model.DeleteBucketInventoryConfigurationRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketInventoryConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.DeleteBucketLifecycleResponse deleteBucketLifecycle(software.amazon.awssdk.services.s3.model.DeleteBucketLifecycleRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketLifecycle(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.DeleteBucketMetricsConfigurationResponse deleteBucketMetricsConfiguration(software.amazon.awssdk.services.s3.model.DeleteBucketMetricsConfigurationRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketMetricsConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.DeleteBucketOwnershipControlsResponse deleteBucketOwnershipControls(software.amazon.awssdk.services.s3.model.DeleteBucketOwnershipControlsRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketOwnershipControls(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.DeleteBucketPolicyResponse deleteBucketPolicy(software.amazon.awssdk.services.s3.model.DeleteBucketPolicyRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketPolicy(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.DeleteBucketReplicationResponse deleteBucketReplication(software.amazon.awssdk.services.s3.model.DeleteBucketReplicationRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketReplication(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.DeleteBucketTaggingResponse deleteBucketTagging(software.amazon.awssdk.services.s3.model.DeleteBucketTaggingRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketTagging(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.DeleteBucketWebsiteResponse deleteBucketWebsite(software.amazon.awssdk.services.s3.model.DeleteBucketWebsiteRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketWebsite(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.DeleteObjectResponse deleteObject(software.amazon.awssdk.services.s3.model.DeleteObjectRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteObject(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.DeleteObjectTaggingResponse deleteObjectTagging(software.amazon.awssdk.services.s3.model.DeleteObjectTaggingRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteObjectTagging(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.DeleteObjectsResponse deleteObjects(software.amazon.awssdk.services.s3.model.DeleteObjectsRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteObjects(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.DeletePublicAccessBlockResponse deletePublicAccessBlock(software.amazon.awssdk.services.s3.model.DeletePublicAccessBlockRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deletePublicAccessBlock(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketAccelerateConfigurationResponse getBucketAccelerateConfiguration(software.amazon.awssdk.services.s3.model.GetBucketAccelerateConfigurationRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketAccelerateConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketAclResponse getBucketAcl(software.amazon.awssdk.services.s3.model.GetBucketAclRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketAcl(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketAnalyticsConfigurationResponse getBucketAnalyticsConfiguration(software.amazon.awssdk.services.s3.model.GetBucketAnalyticsConfigurationRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketAnalyticsConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketCorsResponse getBucketCors(software.amazon.awssdk.services.s3.model.GetBucketCorsRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketCors(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketEncryptionResponse getBucketEncryption(software.amazon.awssdk.services.s3.model.GetBucketEncryptionRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketEncryption(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketIntelligentTieringConfigurationResponse getBucketIntelligentTieringConfiguration(software.amazon.awssdk.services.s3.model.GetBucketIntelligentTieringConfigurationRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketIntelligentTieringConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketInventoryConfigurationResponse getBucketInventoryConfiguration(software.amazon.awssdk.services.s3.model.GetBucketInventoryConfigurationRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketInventoryConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketLifecycleConfigurationResponse getBucketLifecycleConfiguration(software.amazon.awssdk.services.s3.model.GetBucketLifecycleConfigurationRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketLifecycleConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketLocationResponse getBucketLocation(software.amazon.awssdk.services.s3.model.GetBucketLocationRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketLocation(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketLoggingResponse getBucketLogging(software.amazon.awssdk.services.s3.model.GetBucketLoggingRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketLogging(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketMetricsConfigurationResponse getBucketMetricsConfiguration(software.amazon.awssdk.services.s3.model.GetBucketMetricsConfigurationRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketMetricsConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketNotificationConfigurationResponse getBucketNotificationConfiguration(software.amazon.awssdk.services.s3.model.GetBucketNotificationConfigurationRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketNotificationConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketOwnershipControlsResponse getBucketOwnershipControls(software.amazon.awssdk.services.s3.model.GetBucketOwnershipControlsRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketOwnershipControls(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketPolicyResponse getBucketPolicy(software.amazon.awssdk.services.s3.model.GetBucketPolicyRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketPolicy(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketPolicyStatusResponse getBucketPolicyStatus(software.amazon.awssdk.services.s3.model.GetBucketPolicyStatusRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketPolicyStatus(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketReplicationResponse getBucketReplication(software.amazon.awssdk.services.s3.model.GetBucketReplicationRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketReplication(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketRequestPaymentResponse getBucketRequestPayment(software.amazon.awssdk.services.s3.model.GetBucketRequestPaymentRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketRequestPayment(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketTaggingResponse getBucketTagging(software.amazon.awssdk.services.s3.model.GetBucketTaggingRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketTagging(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketVersioningResponse getBucketVersioning(software.amazon.awssdk.services.s3.model.GetBucketVersioningRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketVersioning(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketWebsiteResponse getBucketWebsite(software.amazon.awssdk.services.s3.model.GetBucketWebsiteRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketWebsite(p0)); + } + + @Override + public software.amazon.awssdk.core.ResponseInputStream getObject(software.amazon.awssdk.services.s3.model.GetObjectRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObject(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetObjectResponse getObject(software.amazon.awssdk.services.s3.model.GetObjectRequest p0, java.nio.file.Path p1) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObject(p0, p1)); + } + + @Override + public ReturnT getObject(software.amazon.awssdk.services.s3.model.GetObjectRequest p0, software.amazon.awssdk.core.sync.ResponseTransformer p1) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObject(p0, p1)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetObjectAclResponse getObjectAcl(software.amazon.awssdk.services.s3.model.GetObjectAclRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectAcl(p0)); + } + + @Override + public software.amazon.awssdk.core.ResponseBytes getObjectAsBytes(software.amazon.awssdk.services.s3.model.GetObjectRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectAsBytes(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetObjectAttributesResponse getObjectAttributes(software.amazon.awssdk.services.s3.model.GetObjectAttributesRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectAttributes(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetObjectLegalHoldResponse getObjectLegalHold(software.amazon.awssdk.services.s3.model.GetObjectLegalHoldRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectLegalHold(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetObjectLockConfigurationResponse getObjectLockConfiguration(software.amazon.awssdk.services.s3.model.GetObjectLockConfigurationRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectLockConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetObjectRetentionResponse getObjectRetention(software.amazon.awssdk.services.s3.model.GetObjectRetentionRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectRetention(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetObjectTaggingResponse getObjectTagging(software.amazon.awssdk.services.s3.model.GetObjectTaggingRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectTagging(p0)); + } + + @Override + public software.amazon.awssdk.core.ResponseInputStream getObjectTorrent(software.amazon.awssdk.services.s3.model.GetObjectTorrentRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectTorrent(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetObjectTorrentResponse getObjectTorrent(software.amazon.awssdk.services.s3.model.GetObjectTorrentRequest p0, java.nio.file.Path p1) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectTorrent(p0, p1)); + } + + @Override + public ReturnT getObjectTorrent(software.amazon.awssdk.services.s3.model.GetObjectTorrentRequest p0, software.amazon.awssdk.core.sync.ResponseTransformer p1) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectTorrent(p0, p1)); + } + + @Override + public software.amazon.awssdk.core.ResponseBytes getObjectTorrentAsBytes(software.amazon.awssdk.services.s3.model.GetObjectTorrentRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectTorrentAsBytes(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetPublicAccessBlockResponse getPublicAccessBlock(software.amazon.awssdk.services.s3.model.GetPublicAccessBlockRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getPublicAccessBlock(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.HeadBucketResponse headBucket(software.amazon.awssdk.services.s3.model.HeadBucketRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.headBucket(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.HeadObjectResponse headObject(software.amazon.awssdk.services.s3.model.HeadObjectRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.headObject(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.ListBucketAnalyticsConfigurationsResponse listBucketAnalyticsConfigurations(software.amazon.awssdk.services.s3.model.ListBucketAnalyticsConfigurationsRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listBucketAnalyticsConfigurations(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.ListBucketIntelligentTieringConfigurationsResponse listBucketIntelligentTieringConfigurations(software.amazon.awssdk.services.s3.model.ListBucketIntelligentTieringConfigurationsRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listBucketIntelligentTieringConfigurations(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.ListBucketInventoryConfigurationsResponse listBucketInventoryConfigurations(software.amazon.awssdk.services.s3.model.ListBucketInventoryConfigurationsRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listBucketInventoryConfigurations(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.ListBucketMetricsConfigurationsResponse listBucketMetricsConfigurations(software.amazon.awssdk.services.s3.model.ListBucketMetricsConfigurationsRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listBucketMetricsConfigurations(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.ListMultipartUploadsResponse listMultipartUploads(software.amazon.awssdk.services.s3.model.ListMultipartUploadsRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listMultipartUploads(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.paginators.ListMultipartUploadsIterable listMultipartUploadsPaginator(software.amazon.awssdk.services.s3.model.ListMultipartUploadsRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listMultipartUploadsPaginator(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.ListObjectVersionsResponse listObjectVersions(software.amazon.awssdk.services.s3.model.ListObjectVersionsRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listObjectVersions(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.paginators.ListObjectVersionsIterable listObjectVersionsPaginator(software.amazon.awssdk.services.s3.model.ListObjectVersionsRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listObjectVersionsPaginator(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.ListObjectsResponse listObjects(software.amazon.awssdk.services.s3.model.ListObjectsRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listObjects(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.ListObjectsV2Response listObjectsV2(software.amazon.awssdk.services.s3.model.ListObjectsV2Request p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listObjectsV2(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.paginators.ListObjectsV2Iterable listObjectsV2Paginator(software.amazon.awssdk.services.s3.model.ListObjectsV2Request p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listObjectsV2Paginator(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.ListPartsResponse listParts(software.amazon.awssdk.services.s3.model.ListPartsRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listParts(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.paginators.ListPartsIterable listPartsPaginator(software.amazon.awssdk.services.s3.model.ListPartsRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listPartsPaginator(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutBucketAccelerateConfigurationResponse putBucketAccelerateConfiguration(software.amazon.awssdk.services.s3.model.PutBucketAccelerateConfigurationRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketAccelerateConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutBucketAclResponse putBucketAcl(software.amazon.awssdk.services.s3.model.PutBucketAclRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketAcl(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutBucketAnalyticsConfigurationResponse putBucketAnalyticsConfiguration(software.amazon.awssdk.services.s3.model.PutBucketAnalyticsConfigurationRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketAnalyticsConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutBucketCorsResponse putBucketCors(software.amazon.awssdk.services.s3.model.PutBucketCorsRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketCors(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutBucketEncryptionResponse putBucketEncryption(software.amazon.awssdk.services.s3.model.PutBucketEncryptionRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketEncryption(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutBucketIntelligentTieringConfigurationResponse putBucketIntelligentTieringConfiguration(software.amazon.awssdk.services.s3.model.PutBucketIntelligentTieringConfigurationRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketIntelligentTieringConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutBucketInventoryConfigurationResponse putBucketInventoryConfiguration(software.amazon.awssdk.services.s3.model.PutBucketInventoryConfigurationRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketInventoryConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutBucketLifecycleConfigurationResponse putBucketLifecycleConfiguration(software.amazon.awssdk.services.s3.model.PutBucketLifecycleConfigurationRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketLifecycleConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutBucketLoggingResponse putBucketLogging(software.amazon.awssdk.services.s3.model.PutBucketLoggingRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketLogging(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutBucketMetricsConfigurationResponse putBucketMetricsConfiguration(software.amazon.awssdk.services.s3.model.PutBucketMetricsConfigurationRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketMetricsConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutBucketNotificationConfigurationResponse putBucketNotificationConfiguration(software.amazon.awssdk.services.s3.model.PutBucketNotificationConfigurationRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketNotificationConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutBucketOwnershipControlsResponse putBucketOwnershipControls(software.amazon.awssdk.services.s3.model.PutBucketOwnershipControlsRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketOwnershipControls(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutBucketPolicyResponse putBucketPolicy(software.amazon.awssdk.services.s3.model.PutBucketPolicyRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketPolicy(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutBucketReplicationResponse putBucketReplication(software.amazon.awssdk.services.s3.model.PutBucketReplicationRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketReplication(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutBucketRequestPaymentResponse putBucketRequestPayment(software.amazon.awssdk.services.s3.model.PutBucketRequestPaymentRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketRequestPayment(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutBucketTaggingResponse putBucketTagging(software.amazon.awssdk.services.s3.model.PutBucketTaggingRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketTagging(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutBucketVersioningResponse putBucketVersioning(software.amazon.awssdk.services.s3.model.PutBucketVersioningRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketVersioning(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutBucketWebsiteResponse putBucketWebsite(software.amazon.awssdk.services.s3.model.PutBucketWebsiteRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketWebsite(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutObjectResponse putObject(software.amazon.awssdk.services.s3.model.PutObjectRequest p0, java.nio.file.Path p1) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putObject(p0, p1)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutObjectResponse putObject(software.amazon.awssdk.services.s3.model.PutObjectRequest p0, software.amazon.awssdk.core.sync.RequestBody p1) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putObject(p0, p1)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutObjectAclResponse putObjectAcl(software.amazon.awssdk.services.s3.model.PutObjectAclRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putObjectAcl(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutObjectLegalHoldResponse putObjectLegalHold(software.amazon.awssdk.services.s3.model.PutObjectLegalHoldRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putObjectLegalHold(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutObjectLockConfigurationResponse putObjectLockConfiguration(software.amazon.awssdk.services.s3.model.PutObjectLockConfigurationRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putObjectLockConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutObjectRetentionResponse putObjectRetention(software.amazon.awssdk.services.s3.model.PutObjectRetentionRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putObjectRetention(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutObjectTaggingResponse putObjectTagging(software.amazon.awssdk.services.s3.model.PutObjectTaggingRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putObjectTagging(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutPublicAccessBlockResponse putPublicAccessBlock(software.amazon.awssdk.services.s3.model.PutPublicAccessBlockRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putPublicAccessBlock(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.RestoreObjectResponse restoreObject(software.amazon.awssdk.services.s3.model.RestoreObjectRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.restoreObject(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.UploadPartResponse uploadPart(software.amazon.awssdk.services.s3.model.UploadPartRequest p0, java.nio.file.Path p1) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.uploadPart(p0, p1)); + } + + @Override + public software.amazon.awssdk.services.s3.model.UploadPartResponse uploadPart(software.amazon.awssdk.services.s3.model.UploadPartRequest p0, software.amazon.awssdk.core.sync.RequestBody p1) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.uploadPart(p0, p1)); + } + + @Override + public software.amazon.awssdk.services.s3.model.UploadPartCopyResponse uploadPartCopy(software.amazon.awssdk.services.s3.model.UploadPartCopyRequest p0) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.uploadPartCopy(p0)); + } } + From 9fca942b24ed3df0f001aacced4799b2eaa64748 Mon Sep 17 00:00:00 2001 From: krimsz Date: Tue, 5 Jul 2022 09:47:35 +0200 Subject: [PATCH 04/10] Add tests for clients using normal Autoconfiguration --- .../core/AwsAutoConfiguration.java | 16 ++++++++++--- .../core/AwsClientBuilderConfigurer.java | 2 +- .../dynamodb/DynamoDbAutoConfiguration.java | 10 ++++++-- .../CloudWatchExportAutoConfiguration.java | 17 ++++++++++---- .../ses/SesAutoConfiguration.java | 13 +++++++---- .../sns/SnsAutoConfiguration.java | 15 ++++++++---- .../DynamoDbAutoConfigurationTest.java | 20 ++++++++++++++++ ...CloudWatchExportAutoConfigurationTest.java | 23 +++++++++++++++++++ .../s3/S3AutoConfigurationTests.java | 20 ++++++++++++++++ .../ses/SesAutoConfigurationTest.java | 20 ++++++++++++++++ .../sns/SnsAutoConfigurationTest.java | 21 +++++++++++++++++ 11 files changed, 158 insertions(+), 19 deletions(-) diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsAutoConfiguration.java index fb8425d93..e2835fc60 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsAutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsAutoConfiguration.java @@ -19,6 +19,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; @@ -26,6 +27,8 @@ import software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher; import software.amazon.awssdk.regions.providers.AwsRegionProvider; +import java.time.Duration; + /** * Autoconfigures AWS environment. * @@ -36,7 +39,7 @@ @EnableConfigurationProperties(AwsProperties.class) public class AwsAutoConfiguration { - private final AwsProperties awsProperties; + private static AwsProperties awsProperties; public AwsAutoConfiguration(AwsProperties awsProperties) { this.awsProperties = awsProperties; @@ -46,9 +49,16 @@ public AwsAutoConfiguration(AwsProperties awsProperties) { static class MetricsAutoConfiguration { @Bean @ConditionalOnMissingBean - @ConditionalOnProperty(name = "spring.cloud.aws.metrics-enabled", havingValue = "true", matchIfMissing = true) + @ConditionalOnProperty(name = "spring.cloud.aws.metrics.enabled", havingValue = "true", matchIfMissing = true) MetricPublisher cloudWatchMetricPublisher() { - return CloudWatchMetricPublisher.builder().build(); + CloudWatchMetricPublisher.Builder builder = CloudWatchMetricPublisher.builder(); + PropertyMapper propertyMapper = PropertyMapper.get(); + if (awsProperties.getMetrics() != null) { + propertyMapper.from(awsProperties.getMetrics()::getNamespace).whenNonNull().to(builder::namespace); + propertyMapper.from(awsProperties.getMetrics()::getUploadFrequencyInSeconds).whenNonNull() + .to(v -> builder.uploadFrequency(Duration.ofSeconds(v))); + } + return builder.build(); } } diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsClientBuilderConfigurer.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsClientBuilderConfigurer.java index f734273e1..4332fcd96 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsClientBuilderConfigurer.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsClientBuilderConfigurer.java @@ -53,7 +53,7 @@ public class AwsClientBuilderConfigurer { } public > T configure(T builder, @Nullable AwsClientProperties clientProperties, - @Nullable AwsClientCustomizer customizer, MetricPublisher metricPublisher) { + @Nullable AwsClientCustomizer customizer, @Nullable MetricPublisher metricPublisher) { ClientOverrideConfiguration.Builder clientOverrideConfigurationBuilder = clientOverrideConfiguration .toBuilder(); Assert.notNull(builder, "builder is required"); diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfiguration.java index 793767e85..68d3fbbbe 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfiguration.java @@ -56,11 +56,17 @@ public DynamoDbAutoConfiguration(DynamoDbProperties properties) { @ConditionalOnMissingBean @Bean - public DynamoDbClient dynamoDbClient(AwsClientBuilderConfigurer awsClientBuilderConfigurer, + public DynamoDbClientBuilder dynamoDbClientBuilder(AwsClientBuilderConfigurer awsClientBuilderConfigurer, ObjectProvider> configurer, ObjectProvider metricPublisher) { return awsClientBuilderConfigurer.configure(DynamoDbClient.builder(), properties, configurer.getIfAvailable(), - metricPublisher.getIfAvailable()).build(); + metricPublisher.getIfAvailable()); + } + + @ConditionalOnMissingBean + @Bean + public DynamoDbClient dynamoDbClient(DynamoDbClientBuilder dynamoDbClientBuilder) { + return dynamoDbClientBuilder.build(); } @ConditionalOnMissingBean diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/metrics/CloudWatchExportAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/metrics/CloudWatchExportAutoConfiguration.java index d7fff4ab3..336550834 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/metrics/CloudWatchExportAutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/metrics/CloudWatchExportAutoConfiguration.java @@ -38,6 +38,7 @@ import software.amazon.awssdk.regions.providers.AwsRegionProvider; import software.amazon.awssdk.services.cloudwatch.CloudWatchAsyncClient; import software.amazon.awssdk.services.cloudwatch.CloudWatchAsyncClientBuilder; +import software.amazon.awssdk.services.cloudwatch.CloudWatchClientBuilder; /** * Configuration for exporting metrics to CloudWatch. @@ -64,14 +65,20 @@ public CloudWatchMeterRegistry cloudWatchMeterRegistry(CloudWatchConfig config, return new CloudWatchMeterRegistry(config, clock, client); } + @Bean @ConditionalOnMissingBean - public CloudWatchAsyncClient cloudWatchAsyncClient(CloudWatchProperties properties, - AwsClientBuilderConfigurer awsClientBuilderConfigurer, - ObjectProvider> configurer, - ObjectProvider metricPublisher) { + public CloudWatchAsyncClientBuilder cloudWatchAsyncClientBuilder(CloudWatchProperties properties, + AwsClientBuilderConfigurer awsClientBuilderConfigurer, + ObjectProvider> configurer, + ObjectProvider metricPublisher) { return awsClientBuilderConfigurer.configure(CloudWatchAsyncClient.builder(), properties, - configurer.getIfAvailable(), metricPublisher.getIfAvailable()).build(); + configurer.getIfAvailable(), metricPublisher.getIfAvailable()); + } + @Bean + @ConditionalOnMissingBean + public CloudWatchAsyncClient cloudWatchAsyncClient(CloudWatchAsyncClientBuilder cloudWatchAsyncClientBuilder) { + return cloudWatchAsyncClientBuilder.build(); } @Bean diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/ses/SesAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/ses/SesAutoConfiguration.java index cacb26d05..d1b88f8f3 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/ses/SesAutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/ses/SesAutoConfiguration.java @@ -54,11 +54,16 @@ public class SesAutoConfiguration { @Bean @ConditionalOnMissingBean - public SesClient sesClient(SesProperties properties, AwsClientBuilderConfigurer awsClientBuilderConfigurer, - ObjectProvider> configurer, - ObjectProvider metricPublisher) { + public SesClientBuilder sesClientBuilder(SesProperties properties, AwsClientBuilderConfigurer awsClientBuilderConfigurer, + ObjectProvider> configurer, + ObjectProvider metricPublisher) { return awsClientBuilderConfigurer.configure(SesClient.builder(), properties, configurer.getIfAvailable(), - metricPublisher.getIfAvailable()).build(); + metricPublisher.getIfAvailable()); + } + @Bean + @ConditionalOnMissingBean + public SesClient sesClient(SesClientBuilder sesClientBuilder) { + return sesClientBuilder.build(); } @Bean diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/sns/SnsAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/sns/SnsAutoConfiguration.java index 23e50c395..79ac3d56c 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/sns/SnsAutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/sns/SnsAutoConfiguration.java @@ -59,13 +59,20 @@ @ConditionalOnProperty(name = "spring.cloud.aws.sns.enabled", havingValue = "true", matchIfMissing = true) public class SnsAutoConfiguration { + @ConditionalOnMissingBean @Bean - public SnsClient snsClient(SnsProperties properties, AwsClientBuilderConfigurer awsClientBuilderConfigurer, - ObjectProvider> configurer, - ObjectProvider metricPublisher) { + public SnsClientBuilder snsClientBuilder(SnsProperties properties, AwsClientBuilderConfigurer awsClientBuilderConfigurer, + ObjectProvider> configurer, + ObjectProvider metricPublisher) { return awsClientBuilderConfigurer.configure(SnsClient.builder(), properties, configurer.getIfAvailable(), - metricPublisher.getIfAvailable()).build(); + metricPublisher.getIfAvailable()); + } + + @ConditionalOnMissingBean + @Bean + public SnsClient snsClient(SnsClientBuilder snsClientBuilder) { + return snsClientBuilder.build(); } @ConditionalOnMissingBean diff --git a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfigurationTest.java b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfigurationTest.java index ef41420e1..ce95d58ba 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfigurationTest.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfigurationTest.java @@ -29,6 +29,7 @@ import java.time.Duration; 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; @@ -38,8 +39,11 @@ import software.amazon.awssdk.enhanced.dynamodb.TableSchema; import software.amazon.awssdk.http.SdkHttpClient; import software.amazon.awssdk.http.apache.ApacheHttpClient; +import software.amazon.awssdk.metrics.MetricPublisher; +import software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.services.dynamodb.DynamoDbClientBuilder; +import software.amazon.awssdk.services.s3.S3ClientBuilder; /** * @@ -104,7 +108,23 @@ void customTableResolverResolverCanBeConfigured() { }); } + @Test + void usesMetricsPublisherIfAvailable() { + this.contextRunner.run(context -> { + assertThat(context).hasSingleBean(MetricPublisher.class); + assertThat(context).hasSingleBean(DynamoDbClientBuilder.class); + assertThat(context.getBean(DynamoDbClientBuilder.class).overrideConfiguration().metricPublishers().size()).isEqualTo(1); + }); + } + @Test + void doesNotUseMetricsPublisherIfNotAvailable() { + this.contextRunner.withClassLoader(new FilteredClassLoader(CloudWatchMetricPublisher.class)).run(context -> { + assertThat(context).doesNotHaveBean(MetricPublisher.class); + assertThat(context).hasSingleBean(DynamoDbClientBuilder.class); + assertThat(context.getBean(DynamoDbClientBuilder.class).overrideConfiguration().metricPublishers().size()).isEqualTo(0); + }); + } @Test void customDynamoDbClientConfigurer() { this.contextRunner.withUserConfiguration(DynamoDbAutoConfigurationTest.CustomAwsClientConfig.class) diff --git a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/metrics/CloudWatchExportAutoConfigurationTest.java b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/metrics/CloudWatchExportAutoConfigurationTest.java index 391e677e3..e1ebfd99b 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/metrics/CloudWatchExportAutoConfigurationTest.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/metrics/CloudWatchExportAutoConfigurationTest.java @@ -29,6 +29,7 @@ import java.time.Duration; 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; @@ -36,9 +37,13 @@ import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.http.async.SdkAsyncHttpClient; import software.amazon.awssdk.http.nio.netty.NettyNioAsyncHttpClient; +import software.amazon.awssdk.metrics.MetricPublisher; +import software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.cloudwatch.CloudWatchAsyncClient; import software.amazon.awssdk.services.cloudwatch.CloudWatchAsyncClientBuilder; +import software.amazon.awssdk.services.cloudwatch.CloudWatchClientBuilder; +import software.amazon.awssdk.services.ses.SesClientBuilder; /** * Test for the {@link CloudWatchExportAutoConfiguration}. @@ -134,6 +139,24 @@ void useAwsConfigurerClient() { }); } + @Test + void usesMetricsPublisherIfAvailable() { + this.contextRunner.withPropertyValues("management.metrics.export.cloudwatch.namespace:test").run(context -> { + assertThat(context).hasSingleBean(MetricPublisher.class); + assertThat(context).getBean(CloudWatchAsyncClientBuilder.class); + assertThat(context.getBean(CloudWatchAsyncClientBuilder.class).overrideConfiguration().metricPublishers().size()).isEqualTo(1); + }); + } + + @Test + void doesNotUseMetricsPublisherIfNotAvailable() { + this.contextRunner.withClassLoader(new FilteredClassLoader(CloudWatchMetricPublisher.class)).withPropertyValues("management.metrics.export.cloudwatch.namespace:test").run(context -> { + assertThat(context).doesNotHaveBean(MetricPublisher.class); + assertThat(context).hasSingleBean(CloudWatchAsyncClientBuilder.class); + assertThat(context.getBean(CloudWatchAsyncClientBuilder.class).overrideConfiguration().metricPublishers().size()).isEqualTo(0); + }); + } + @Configuration(proxyBeanMethods = false) static class CustomAwsConfigurerClient { diff --git a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/s3/S3AutoConfigurationTests.java b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/s3/S3AutoConfigurationTests.java index 985385b47..8d32110a8 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/s3/S3AutoConfigurationTests.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/s3/S3AutoConfigurationTests.java @@ -51,6 +51,8 @@ import software.amazon.awssdk.core.client.config.SdkClientOption; import software.amazon.awssdk.http.SdkHttpClient; import software.amazon.awssdk.http.apache.ApacheHttpClient; +import software.amazon.awssdk.metrics.MetricPublisher; +import software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher; import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.s3.S3ClientBuilder; @@ -88,6 +90,24 @@ void s3AutoConfigurationIsDisabled() { }); } + @Test + void usesMetricsPublisherIfAvailable() { + this.contextRunner.run(context -> { + assertThat(context).hasSingleBean(MetricPublisher.class); + assertThat(context).hasSingleBean(S3ClientBuilder.class); + assertThat(context.getBean(S3ClientBuilder.class).overrideConfiguration().metricPublishers().size()).isEqualTo(1); + }); + } + + @Test + void doesNotUseMetricsPublisherIfNotAvailable() { + this.contextRunner.withClassLoader(new FilteredClassLoader(CloudWatchMetricPublisher.class)).run(context -> { + assertThat(context).doesNotHaveBean(MetricPublisher.class); + assertThat(context).hasSingleBean(S3ClientBuilder.class); + assertThat(context.getBean(S3ClientBuilder.class).overrideConfiguration().metricPublishers().size()).isEqualTo(0); + }); + } + @Test void autoconfigurationIsNotTriggeredWhenS3ModuleIsNotOnClasspath() { this.contextRunner.withClassLoader(new FilteredClassLoader(S3OutputStreamProvider.class)).run(context -> { diff --git a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/ses/SesAutoConfigurationTest.java b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/ses/SesAutoConfigurationTest.java index a5b1414fb..98ee70eac 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/ses/SesAutoConfigurationTest.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/ses/SesAutoConfigurationTest.java @@ -35,6 +35,8 @@ import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.http.SdkHttpClient; import software.amazon.awssdk.http.apache.ApacheHttpClient; +import software.amazon.awssdk.metrics.MetricPublisher; +import software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher; import software.amazon.awssdk.services.ses.SesClient; import software.amazon.awssdk.services.ses.SesClientBuilder; @@ -86,6 +88,24 @@ void sesAutoConfigurationIsDisabled() { }); } + @Test + void usesMetricsPublisherIfAvailable() { + this.contextRunner.run(context -> { + assertThat(context).hasSingleBean(MetricPublisher.class); + assertThat(context).hasSingleBean(SesClientBuilder.class); + assertThat(context.getBean(SesClientBuilder.class).overrideConfiguration().metricPublishers().size()).isEqualTo(1); + }); + } + + @Test + void doesNotUseMetricsPublisherIfNotAvailable() { + this.contextRunner.withClassLoader(new FilteredClassLoader(CloudWatchMetricPublisher.class)).run(context -> { + assertThat(context).doesNotHaveBean(MetricPublisher.class); + assertThat(context).hasSingleBean(SesClientBuilder.class); + assertThat(context.getBean(SesClientBuilder.class).overrideConfiguration().metricPublishers().size()).isEqualTo(0); + }); + } + @Test void withCustomEndpoint() { this.contextRunner.withPropertyValues("spring.cloud.aws.ses.endpoint:http://localhost:8090").run(context -> { diff --git a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/sns/SnsAutoConfigurationTest.java b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/sns/SnsAutoConfigurationTest.java index bb43960b0..46831c28f 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/sns/SnsAutoConfigurationTest.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/sns/SnsAutoConfigurationTest.java @@ -41,6 +41,9 @@ import software.amazon.awssdk.core.client.config.SdkClientOption; import software.amazon.awssdk.http.SdkHttpClient; import software.amazon.awssdk.http.apache.ApacheHttpClient; +import software.amazon.awssdk.metrics.MetricPublisher; +import software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher; +import software.amazon.awssdk.services.dynamodb.DynamoDbClientBuilder; import software.amazon.awssdk.services.sns.SnsClient; import software.amazon.awssdk.services.sns.SnsClientBuilder; @@ -106,6 +109,24 @@ void customSnsClientConfigurer() { }); } + @Test + void usesMetricsPublisherIfAvailable() { + this.contextRunner.run(context -> { + assertThat(context).hasSingleBean(MetricPublisher.class); + assertThat(context).hasSingleBean(SnsClientBuilder.class); + assertThat(context.getBean(SnsClientBuilder.class).overrideConfiguration().metricPublishers().size()).isEqualTo(1); + }); + } + + @Test + void doesNotUseMetricsPublisherIfNotAvailable() { + this.contextRunner.withClassLoader(new FilteredClassLoader(CloudWatchMetricPublisher.class)).run(context -> { + assertThat(context).doesNotHaveBean(MetricPublisher.class); + assertThat(context).hasSingleBean(SnsClientBuilder.class); + assertThat(context.getBean(SnsClientBuilder.class).overrideConfiguration().metricPublishers().size()).isEqualTo(0); + }); + } + @Test void doesNotConfigureArgumentResolversWhenSpringWebNotOnTheClasspath() { this.contextRunner.withClassLoader(new FilteredClassLoader(WebMvcConfigurer.class)).run(context -> { From 21ebd2924d5d0d7faec2ca4328a684c5259fe423 Mon Sep 17 00:00:00 2001 From: krimsz Date: Tue, 5 Jul 2022 09:47:35 +0200 Subject: [PATCH 05/10] Add opt-out for specific clients with normal autoconfiguration --- .../core/AwsAutoConfiguration.java | 5 +- .../core/AwsClientBuilderConfigurer.java | 24 ++++++++ .../dynamodb/DynamoDbAutoConfiguration.java | 8 ++- .../CloudWatchExportAutoConfiguration.java | 17 ++---- .../autoconfigure/s3/S3AutoConfiguration.java | 11 ++-- .../ses/SesAutoConfiguration.java | 14 +++-- .../sns/SnsAutoConfiguration.java | 13 +++-- .../core/AwsAutoConfigurationTests.java | 57 +++++++++++++++++++ .../core/CustomRegionProvider.java | 28 +++++++++ .../RegionProviderAutoConfigurationTests.java | 9 --- .../DynamoDbAutoConfigurationTest.java | 36 +++++++++++- ...CloudWatchExportAutoConfigurationTest.java | 23 -------- .../s3/S3AutoConfigurationTests.java | 32 ++++++++++- .../ses/SesAutoConfigurationTest.java | 34 ++++++++++- .../sns/SnsAutoConfigurationTest.java | 34 ++++++++++- 15 files changed, 273 insertions(+), 72 deletions(-) create mode 100644 spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/core/AwsAutoConfigurationTests.java create mode 100644 spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/core/CustomRegionProvider.java diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsAutoConfiguration.java index e2835fc60..14e33baf7 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsAutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsAutoConfiguration.java @@ -15,6 +15,7 @@ */ package io.awspring.cloud.autoconfigure.core; +import java.time.Duration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -27,8 +28,6 @@ import software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher; import software.amazon.awssdk.regions.providers.AwsRegionProvider; -import java.time.Duration; - /** * Autoconfigures AWS environment. * @@ -56,7 +55,7 @@ MetricPublisher cloudWatchMetricPublisher() { if (awsProperties.getMetrics() != null) { propertyMapper.from(awsProperties.getMetrics()::getNamespace).whenNonNull().to(builder::namespace); propertyMapper.from(awsProperties.getMetrics()::getUploadFrequencyInSeconds).whenNonNull() - .to(v -> builder.uploadFrequency(Duration.ofSeconds(v))); + .to(v -> builder.uploadFrequency(Duration.ofSeconds(v))); } return builder.build(); } diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsClientBuilderConfigurer.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsClientBuilderConfigurer.java index 4332fcd96..4f5176ae4 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsClientBuilderConfigurer.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsClientBuilderConfigurer.java @@ -17,14 +17,18 @@ import io.awspring.cloud.autoconfigure.AwsClientProperties; import io.awspring.cloud.core.SpringCloudClientConfiguration; +import java.time.Duration; import java.util.Optional; +import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.lang.Nullable; import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; import software.amazon.awssdk.awscore.client.builder.AwsClientBuilder; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.metrics.MetricPublisher; +import software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.regions.providers.AwsRegionProvider; @@ -82,4 +86,24 @@ public Region resolveRegion(@Nullable AwsClientProperties clientProperties) { ? Region.of(clientProperties.getRegion()) : this.regionProvider.getRegion(); } + + public static @Nullable MetricPublisher createSpecificMetricPublisher(MetricPublisher metricPublisher, + AwsClientProperties properties) { + if (ClassUtils.isPresent("software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher", null) + && properties.getMetrics() != null) { + if (properties.getMetrics().getEnabled() == null || properties.getMetrics().getEnabled()) { + CloudWatchMetricPublisher.Builder builder = CloudWatchMetricPublisher.builder(); + PropertyMapper propertyMapper = PropertyMapper.get(); + propertyMapper.from(properties.getMetrics()::getNamespace).whenNonNull().to(builder::namespace); + propertyMapper.from(properties.getMetrics()::getUploadFrequencyInSeconds).whenNonNull() + .to(v -> builder.uploadFrequency(Duration.ofSeconds(v))); + return builder.build(); + } + if (properties.getMetrics().getEnabled() != null && !properties.getMetrics().getEnabled()) { + return null; + } + + } + return metricPublisher; + } } diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfiguration.java index 68d3fbbbe..2184737b6 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfiguration.java @@ -15,6 +15,8 @@ */ package io.awspring.cloud.autoconfigure.dynamodb; +import static io.awspring.cloud.autoconfigure.core.AwsClientBuilderConfigurer.createSpecificMetricPublisher; + import io.awspring.cloud.autoconfigure.core.AwsClientBuilderConfigurer; import io.awspring.cloud.autoconfigure.core.AwsClientCustomizer; import io.awspring.cloud.autoconfigure.core.CredentialsProviderAutoConfiguration; @@ -58,9 +60,11 @@ public DynamoDbAutoConfiguration(DynamoDbProperties properties) { @Bean public DynamoDbClientBuilder dynamoDbClientBuilder(AwsClientBuilderConfigurer awsClientBuilderConfigurer, ObjectProvider> configurer, - ObjectProvider metricPublisher) { + ObjectProvider metricPublisherObjectProvider) { + MetricPublisher metricPublisher = createSpecificMetricPublisher(metricPublisherObjectProvider.getIfAvailable(), + properties); return awsClientBuilderConfigurer.configure(DynamoDbClient.builder(), properties, configurer.getIfAvailable(), - metricPublisher.getIfAvailable()); + metricPublisher); } @ConditionalOnMissingBean diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/metrics/CloudWatchExportAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/metrics/CloudWatchExportAutoConfiguration.java index 336550834..28c0aa024 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/metrics/CloudWatchExportAutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/metrics/CloudWatchExportAutoConfiguration.java @@ -38,7 +38,6 @@ import software.amazon.awssdk.regions.providers.AwsRegionProvider; import software.amazon.awssdk.services.cloudwatch.CloudWatchAsyncClient; import software.amazon.awssdk.services.cloudwatch.CloudWatchAsyncClientBuilder; -import software.amazon.awssdk.services.cloudwatch.CloudWatchClientBuilder; /** * Configuration for exporting metrics to CloudWatch. @@ -65,20 +64,14 @@ public CloudWatchMeterRegistry cloudWatchMeterRegistry(CloudWatchConfig config, return new CloudWatchMeterRegistry(config, clock, client); } - @Bean @ConditionalOnMissingBean - public CloudWatchAsyncClientBuilder cloudWatchAsyncClientBuilder(CloudWatchProperties properties, - AwsClientBuilderConfigurer awsClientBuilderConfigurer, - ObjectProvider> configurer, - ObjectProvider metricPublisher) { + public CloudWatchAsyncClient cloudWatchAsyncClient(CloudWatchProperties properties, + AwsClientBuilderConfigurer awsClientBuilderConfigurer, + ObjectProvider> configurer, + ObjectProvider metricPublisherObjectProvider) { return awsClientBuilderConfigurer.configure(CloudWatchAsyncClient.builder(), properties, - configurer.getIfAvailable(), metricPublisher.getIfAvailable()); - } - @Bean - @ConditionalOnMissingBean - public CloudWatchAsyncClient cloudWatchAsyncClient(CloudWatchAsyncClientBuilder cloudWatchAsyncClientBuilder) { - return cloudWatchAsyncClientBuilder.build(); + configurer.getIfAvailable(), metricPublisherObjectProvider.getIfAvailable()).build(); } @Bean diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/S3AutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/S3AutoConfiguration.java index e4337a4e5..4e002a4c2 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/S3AutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/S3AutoConfiguration.java @@ -15,6 +15,8 @@ */ package io.awspring.cloud.autoconfigure.s3; +import static io.awspring.cloud.autoconfigure.core.AwsClientBuilderConfigurer.createSpecificMetricPublisher; + import com.fasterxml.jackson.databind.ObjectMapper; import io.awspring.cloud.autoconfigure.core.AwsClientBuilderConfigurer; import io.awspring.cloud.autoconfigure.core.AwsClientCustomizer; @@ -60,7 +62,7 @@ @ConditionalOnProperty(name = "spring.cloud.aws.s3.enabled", havingValue = "true", matchIfMissing = true) public class S3AutoConfiguration { - private final S3Properties properties; + private static S3Properties properties; public S3AutoConfiguration(S3Properties properties) { this.properties = properties; @@ -70,9 +72,11 @@ public S3AutoConfiguration(S3Properties properties) { @ConditionalOnMissingBean S3ClientBuilder s3ClientBuilder(AwsClientBuilderConfigurer awsClientBuilderConfigurer, ObjectProvider> configurer, - ObjectProvider metricPublisher) { + ObjectProvider metricPublisherObjectProvider) { + MetricPublisher metricPublisher = createSpecificMetricPublisher(metricPublisherObjectProvider.getIfAvailable(), + properties); S3ClientBuilder builder = awsClientBuilderConfigurer.configure(S3Client.builder(), this.properties, - configurer.getIfAvailable(), metricPublisher.getIfAvailable()); + configurer.getIfAvailable(), metricPublisher); builder.serviceConfiguration(s3ServiceConfiguration()); return builder; } @@ -139,5 +143,4 @@ S3OutputStreamProvider inMemoryBufferingS3StreamProvider(S3Client s3Client, return new InMemoryBufferingS3OutputStreamProvider(s3Client, contentTypeResolver.orElseGet(PropertiesS3ObjectContentTypeResolver::new)); } - } diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/ses/SesAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/ses/SesAutoConfiguration.java index d1b88f8f3..796e6bfa2 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/ses/SesAutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/ses/SesAutoConfiguration.java @@ -15,6 +15,8 @@ */ package io.awspring.cloud.autoconfigure.ses; +import static io.awspring.cloud.autoconfigure.core.AwsClientBuilderConfigurer.createSpecificMetricPublisher; + import io.awspring.cloud.autoconfigure.core.AwsClientBuilderConfigurer; import io.awspring.cloud.autoconfigure.core.AwsClientCustomizer; import io.awspring.cloud.autoconfigure.core.CredentialsProviderAutoConfiguration; @@ -54,12 +56,16 @@ public class SesAutoConfiguration { @Bean @ConditionalOnMissingBean - public SesClientBuilder sesClientBuilder(SesProperties properties, AwsClientBuilderConfigurer awsClientBuilderConfigurer, - ObjectProvider> configurer, - ObjectProvider metricPublisher) { + public SesClientBuilder sesClientBuilder(SesProperties properties, + AwsClientBuilderConfigurer awsClientBuilderConfigurer, + ObjectProvider> configurer, + ObjectProvider metricPublisherObjectProvider) { + MetricPublisher metricPublisher = createSpecificMetricPublisher(metricPublisherObjectProvider.getIfAvailable(), + properties); return awsClientBuilderConfigurer.configure(SesClient.builder(), properties, configurer.getIfAvailable(), - metricPublisher.getIfAvailable()); + metricPublisher); } + @Bean @ConditionalOnMissingBean public SesClient sesClient(SesClientBuilder sesClientBuilder) { diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/sns/SnsAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/sns/SnsAutoConfiguration.java index 79ac3d56c..676ac533e 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/sns/SnsAutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/sns/SnsAutoConfiguration.java @@ -15,6 +15,7 @@ */ package io.awspring.cloud.autoconfigure.sns; +import static io.awspring.cloud.autoconfigure.core.AwsClientBuilderConfigurer.createSpecificMetricPublisher; import static io.awspring.cloud.sns.configuration.NotificationHandlerMethodArgumentResolverConfigurationUtils.getNotificationHandlerMethodArgumentResolver; import com.fasterxml.jackson.databind.ObjectMapper; @@ -59,14 +60,16 @@ @ConditionalOnProperty(name = "spring.cloud.aws.sns.enabled", havingValue = "true", matchIfMissing = true) public class SnsAutoConfiguration { - @ConditionalOnMissingBean @Bean - public SnsClientBuilder snsClientBuilder(SnsProperties properties, AwsClientBuilderConfigurer awsClientBuilderConfigurer, - ObjectProvider> configurer, - ObjectProvider metricPublisher) { + public SnsClientBuilder snsClientBuilder(SnsProperties properties, + AwsClientBuilderConfigurer awsClientBuilderConfigurer, + ObjectProvider> configurer, + ObjectProvider metricPublisherObjectProvider) { + MetricPublisher metricPublisher = createSpecificMetricPublisher(metricPublisherObjectProvider.getIfAvailable(), + properties); return awsClientBuilderConfigurer.configure(SnsClient.builder(), properties, configurer.getIfAvailable(), - metricPublisher.getIfAvailable()); + metricPublisher); } @ConditionalOnMissingBean diff --git a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/core/AwsAutoConfigurationTests.java b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/core/AwsAutoConfigurationTests.java new file mode 100644 index 000000000..342cbb30a --- /dev/null +++ b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/core/AwsAutoConfigurationTests.java @@ -0,0 +1,57 @@ +/* + * Copyright 2013-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.awspring.cloud.autoconfigure.core; + +import static org.assertj.core.api.Assertions.assertThat; + +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 software.amazon.awssdk.metrics.MetricPublisher; +import software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher; + +class AwsAutoConfigurationTests { + + private static ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withConfiguration( + AutoConfigurations.of(CredentialsProviderAutoConfiguration.class, AwsAutoConfiguration.class)) + .withBean(CustomRegionProvider.class); + + @Test + void createsMetricsPublisherByDefaultWhenDependencyInClasspath() { + contextRunner.run((context) -> assertThat(context).hasSingleBean(MetricPublisher.class)); + } + + @Test + void createsMetricsPublisherWhenSpecifiedExplicitlyAndDependencyInClasspath() { + contextRunner.withPropertyValues("spring.cloud.aws.metrics.enabled:true") + .run((context) -> assertThat(context).hasSingleBean(MetricPublisher.class)); + } + + @Test + void doesNotCreateMetricsPublisherWhenDisabledExplicitlyAndDependencyInClasspath() { + contextRunner.withPropertyValues("spring.cloud.aws.metrics.enabled:false") + .run((context) -> assertThat(context).doesNotHaveBean(MetricPublisher.class)); + } + + @Test + void doesNotCreateMetricsPublisherWhenDependencyNotInClasspath() { + contextRunner.withClassLoader(new FilteredClassLoader(CloudWatchMetricPublisher.class)) + .run((context) -> assertThat(context).doesNotHaveBean(MetricPublisher.class)); + } + +} diff --git a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/core/CustomRegionProvider.java b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/core/CustomRegionProvider.java new file mode 100644 index 000000000..1523a9c57 --- /dev/null +++ b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/core/CustomRegionProvider.java @@ -0,0 +1,28 @@ +/* + * Copyright 2013-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.awspring.cloud.autoconfigure.core; + +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.regions.providers.AwsRegionProvider; + +class CustomRegionProvider implements AwsRegionProvider { + + @Override + public Region getRegion() { + return null; + } + +} diff --git a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/core/RegionProviderAutoConfigurationTests.java b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/core/RegionProviderAutoConfigurationTests.java index 4e3056095..f0e722e0a 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/core/RegionProviderAutoConfigurationTests.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/core/RegionProviderAutoConfigurationTests.java @@ -143,13 +143,4 @@ public AwsRegionProvider customRegionProvider() { } - static class CustomRegionProvider implements AwsRegionProvider { - - @Override - public Region getRegion() { - return null; - } - - } - } diff --git a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfigurationTest.java b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfigurationTest.java index ce95d58ba..7aca78020 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfigurationTest.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfigurationTest.java @@ -34,6 +34,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.lang.Nullable; +import org.springframework.test.util.ReflectionTestUtils; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient; import software.amazon.awssdk.enhanced.dynamodb.TableSchema; @@ -41,9 +42,9 @@ import software.amazon.awssdk.http.apache.ApacheHttpClient; import software.amazon.awssdk.metrics.MetricPublisher; import software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher; +import software.amazon.awssdk.metrics.publishers.cloudwatch.internal.transform.MetricCollectionAggregator; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.services.dynamodb.DynamoDbClientBuilder; -import software.amazon.awssdk.services.s3.S3ClientBuilder; /** * @@ -108,12 +109,39 @@ void customTableResolverResolverCanBeConfigured() { }); } + + @Test + void usesSpecificMetricsClientPropertiesIfSpecified() { + this.contextRunner.withPropertyValues("spring.cloud.aws.dynamodb.metrics.enabled:true", + "spring.cloud.aws.dynamodb.metrics.namespace:custom").run(context -> { + assertThat(context).hasSingleBean(MetricPublisher.class); + assertThat(context).hasSingleBean(DynamoDbClientBuilder.class); + assertThat(context.getBean(DynamoDbClientBuilder.class).overrideConfiguration().metricPublishers() + .size()).isEqualTo(1); + CloudWatchMetricPublisher metricPublisher = (CloudWatchMetricPublisher) context + .getBean(DynamoDbClientBuilder.class).overrideConfiguration().metricPublishers().get(0); + MetricCollectionAggregator metricAggregator = (MetricCollectionAggregator) ReflectionTestUtils + .getField(metricPublisher, "metricAggregator"); + String namespace = (String) ReflectionTestUtils.getField(metricAggregator, "namespace"); + assertThat(namespace).isEqualTo("custom"); + }); + } + + @Test + void doesNotUseMetricsClientIfDisabledForclient() { + this.contextRunner.withPropertyValues("spring.cloud.aws.dynamodb.metrics.enabled:false").run(context -> { + assertThat(context.getBean(DynamoDbClientBuilder.class).overrideConfiguration().metricPublishers().size()) + .isEqualTo(0); + }); + } + @Test void usesMetricsPublisherIfAvailable() { this.contextRunner.run(context -> { assertThat(context).hasSingleBean(MetricPublisher.class); assertThat(context).hasSingleBean(DynamoDbClientBuilder.class); - assertThat(context.getBean(DynamoDbClientBuilder.class).overrideConfiguration().metricPublishers().size()).isEqualTo(1); + assertThat(context.getBean(DynamoDbClientBuilder.class).overrideConfiguration().metricPublishers().size()) + .isEqualTo(1); }); } @@ -122,9 +150,11 @@ void doesNotUseMetricsPublisherIfNotAvailable() { this.contextRunner.withClassLoader(new FilteredClassLoader(CloudWatchMetricPublisher.class)).run(context -> { assertThat(context).doesNotHaveBean(MetricPublisher.class); assertThat(context).hasSingleBean(DynamoDbClientBuilder.class); - assertThat(context.getBean(DynamoDbClientBuilder.class).overrideConfiguration().metricPublishers().size()).isEqualTo(0); + assertThat(context.getBean(DynamoDbClientBuilder.class).overrideConfiguration().metricPublishers().size()) + .isEqualTo(0); }); } + @Test void customDynamoDbClientConfigurer() { this.contextRunner.withUserConfiguration(DynamoDbAutoConfigurationTest.CustomAwsClientConfig.class) diff --git a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/metrics/CloudWatchExportAutoConfigurationTest.java b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/metrics/CloudWatchExportAutoConfigurationTest.java index e1ebfd99b..391e677e3 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/metrics/CloudWatchExportAutoConfigurationTest.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/metrics/CloudWatchExportAutoConfigurationTest.java @@ -29,7 +29,6 @@ import java.time.Duration; 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; @@ -37,13 +36,9 @@ import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.http.async.SdkAsyncHttpClient; import software.amazon.awssdk.http.nio.netty.NettyNioAsyncHttpClient; -import software.amazon.awssdk.metrics.MetricPublisher; -import software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.cloudwatch.CloudWatchAsyncClient; import software.amazon.awssdk.services.cloudwatch.CloudWatchAsyncClientBuilder; -import software.amazon.awssdk.services.cloudwatch.CloudWatchClientBuilder; -import software.amazon.awssdk.services.ses.SesClientBuilder; /** * Test for the {@link CloudWatchExportAutoConfiguration}. @@ -139,24 +134,6 @@ void useAwsConfigurerClient() { }); } - @Test - void usesMetricsPublisherIfAvailable() { - this.contextRunner.withPropertyValues("management.metrics.export.cloudwatch.namespace:test").run(context -> { - assertThat(context).hasSingleBean(MetricPublisher.class); - assertThat(context).getBean(CloudWatchAsyncClientBuilder.class); - assertThat(context.getBean(CloudWatchAsyncClientBuilder.class).overrideConfiguration().metricPublishers().size()).isEqualTo(1); - }); - } - - @Test - void doesNotUseMetricsPublisherIfNotAvailable() { - this.contextRunner.withClassLoader(new FilteredClassLoader(CloudWatchMetricPublisher.class)).withPropertyValues("management.metrics.export.cloudwatch.namespace:test").run(context -> { - assertThat(context).doesNotHaveBean(MetricPublisher.class); - assertThat(context).hasSingleBean(CloudWatchAsyncClientBuilder.class); - assertThat(context.getBean(CloudWatchAsyncClientBuilder.class).overrideConfiguration().metricPublishers().size()).isEqualTo(0); - }); - } - @Configuration(proxyBeanMethods = false) static class CustomAwsConfigurerClient { diff --git a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/s3/S3AutoConfigurationTests.java b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/s3/S3AutoConfigurationTests.java index 8d32110a8..5109605ad 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/s3/S3AutoConfigurationTests.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/s3/S3AutoConfigurationTests.java @@ -53,6 +53,7 @@ import software.amazon.awssdk.http.apache.ApacheHttpClient; import software.amazon.awssdk.metrics.MetricPublisher; import software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher; +import software.amazon.awssdk.metrics.publishers.cloudwatch.internal.transform.MetricCollectionAggregator; import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.s3.S3ClientBuilder; @@ -95,7 +96,33 @@ void usesMetricsPublisherIfAvailable() { this.contextRunner.run(context -> { assertThat(context).hasSingleBean(MetricPublisher.class); assertThat(context).hasSingleBean(S3ClientBuilder.class); - assertThat(context.getBean(S3ClientBuilder.class).overrideConfiguration().metricPublishers().size()).isEqualTo(1); + assertThat(context.getBean(S3ClientBuilder.class).overrideConfiguration().metricPublishers().size()) + .isEqualTo(1); + }); + } + + @Test + void usesSpecificMetricsClientPropertiesIfSpecified() { + this.contextRunner.withPropertyValues("spring.cloud.aws.s3.metrics.enabled:true", + "spring.cloud.aws.s3.metrics.namespace:custom").run(context -> { + assertThat(context).hasSingleBean(MetricPublisher.class); + assertThat(context).hasSingleBean(S3ClientBuilder.class); + assertThat(context.getBean(S3ClientBuilder.class).overrideConfiguration().metricPublishers().size()) + .isEqualTo(1); + CloudWatchMetricPublisher metricPublisher = (CloudWatchMetricPublisher) context + .getBean(S3ClientBuilder.class).overrideConfiguration().metricPublishers().get(0); + MetricCollectionAggregator metricAggregator = (MetricCollectionAggregator) ReflectionTestUtils + .getField(metricPublisher, "metricAggregator"); + String namespace = (String) ReflectionTestUtils.getField(metricAggregator, "namespace"); + assertThat(namespace).isEqualTo("custom"); + }); + } + + @Test + void doesNotUseMetricsClientIfDisabledForclient() { + this.contextRunner.withPropertyValues("spring.cloud.aws.s3.metrics.enabled:false").run(context -> { + assertThat(context.getBean(S3ClientBuilder.class).overrideConfiguration().metricPublishers().size()) + .isEqualTo(0); }); } @@ -104,7 +131,8 @@ void doesNotUseMetricsPublisherIfNotAvailable() { this.contextRunner.withClassLoader(new FilteredClassLoader(CloudWatchMetricPublisher.class)).run(context -> { assertThat(context).doesNotHaveBean(MetricPublisher.class); assertThat(context).hasSingleBean(S3ClientBuilder.class); - assertThat(context.getBean(S3ClientBuilder.class).overrideConfiguration().metricPublishers().size()).isEqualTo(0); + assertThat(context.getBean(S3ClientBuilder.class).overrideConfiguration().metricPublishers().size()) + .isEqualTo(0); }); } diff --git a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/ses/SesAutoConfigurationTest.java b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/ses/SesAutoConfigurationTest.java index 98ee70eac..64f8b96c9 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/ses/SesAutoConfigurationTest.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/ses/SesAutoConfigurationTest.java @@ -32,11 +32,13 @@ import org.springframework.context.annotation.Configuration; import org.springframework.mail.MailSender; import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.test.util.ReflectionTestUtils; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.http.SdkHttpClient; import software.amazon.awssdk.http.apache.ApacheHttpClient; import software.amazon.awssdk.metrics.MetricPublisher; import software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher; +import software.amazon.awssdk.metrics.publishers.cloudwatch.internal.transform.MetricCollectionAggregator; import software.amazon.awssdk.services.ses.SesClient; import software.amazon.awssdk.services.ses.SesClientBuilder; @@ -88,12 +90,39 @@ void sesAutoConfigurationIsDisabled() { }); } + @Test + void usesSpecificMetricsClientPropertiesIfSpecified() { + this.contextRunner.withPropertyValues("spring.cloud.aws.ses.metrics.enabled:true", + "spring.cloud.aws.ses.metrics.namespace:custom").run(context -> { + assertThat(context).hasSingleBean(MetricPublisher.class); + assertThat(context).hasSingleBean(SesClientBuilder.class); + assertThat( + context.getBean(SesClientBuilder.class).overrideConfiguration().metricPublishers().size()) + .isEqualTo(1); + CloudWatchMetricPublisher metricPublisher = (CloudWatchMetricPublisher) context + .getBean(SesClientBuilder.class).overrideConfiguration().metricPublishers().get(0); + MetricCollectionAggregator metricAggregator = (MetricCollectionAggregator) ReflectionTestUtils + .getField(metricPublisher, "metricAggregator"); + String namespace = (String) ReflectionTestUtils.getField(metricAggregator, "namespace"); + assertThat(namespace).isEqualTo("custom"); + }); + } + + @Test + void doesNotUseMetricsClientIfDisabledForclient() { + this.contextRunner.withPropertyValues("spring.cloud.aws.ses.metrics.enabled:false").run(context -> { + assertThat(context.getBean(SesClientBuilder.class).overrideConfiguration().metricPublishers().size()) + .isEqualTo(0); + }); + } + @Test void usesMetricsPublisherIfAvailable() { this.contextRunner.run(context -> { assertThat(context).hasSingleBean(MetricPublisher.class); assertThat(context).hasSingleBean(SesClientBuilder.class); - assertThat(context.getBean(SesClientBuilder.class).overrideConfiguration().metricPublishers().size()).isEqualTo(1); + assertThat(context.getBean(SesClientBuilder.class).overrideConfiguration().metricPublishers().size()) + .isEqualTo(1); }); } @@ -102,7 +131,8 @@ void doesNotUseMetricsPublisherIfNotAvailable() { this.contextRunner.withClassLoader(new FilteredClassLoader(CloudWatchMetricPublisher.class)).run(context -> { assertThat(context).doesNotHaveBean(MetricPublisher.class); assertThat(context).hasSingleBean(SesClientBuilder.class); - assertThat(context.getBean(SesClientBuilder.class).overrideConfiguration().metricPublishers().size()).isEqualTo(0); + assertThat(context.getBean(SesClientBuilder.class).overrideConfiguration().metricPublishers().size()) + .isEqualTo(0); }); } diff --git a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/sns/SnsAutoConfigurationTest.java b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/sns/SnsAutoConfigurationTest.java index 46831c28f..97de1f48e 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/sns/SnsAutoConfigurationTest.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/sns/SnsAutoConfigurationTest.java @@ -43,7 +43,7 @@ import software.amazon.awssdk.http.apache.ApacheHttpClient; import software.amazon.awssdk.metrics.MetricPublisher; import software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher; -import software.amazon.awssdk.services.dynamodb.DynamoDbClientBuilder; +import software.amazon.awssdk.metrics.publishers.cloudwatch.internal.transform.MetricCollectionAggregator; import software.amazon.awssdk.services.sns.SnsClient; import software.amazon.awssdk.services.sns.SnsClientBuilder; @@ -109,12 +109,39 @@ void customSnsClientConfigurer() { }); } + @Test + void usesSpecificMetricsClientPropertiesIfSpecified() { + this.contextRunner.withPropertyValues("spring.cloud.aws.sns.metrics.enabled:true", + "spring.cloud.aws.sns.metrics.namespace:custom").run(context -> { + assertThat(context).hasSingleBean(MetricPublisher.class); + assertThat(context).hasSingleBean(SnsClientBuilder.class); + assertThat( + context.getBean(SnsClientBuilder.class).overrideConfiguration().metricPublishers().size()) + .isEqualTo(1); + CloudWatchMetricPublisher metricPublisher = (CloudWatchMetricPublisher) context + .getBean(SnsClientBuilder.class).overrideConfiguration().metricPublishers().get(0); + MetricCollectionAggregator metricAggregator = (MetricCollectionAggregator) ReflectionTestUtils + .getField(metricPublisher, "metricAggregator"); + String namespace = (String) ReflectionTestUtils.getField(metricAggregator, "namespace"); + assertThat(namespace).isEqualTo("custom"); + }); + } + + @Test + void doesNotUseMetricsClientIfDisabledForclient() { + this.contextRunner.withPropertyValues("spring.cloud.aws.sns.metrics.enabled:false").run(context -> { + assertThat(context.getBean(SnsClientBuilder.class).overrideConfiguration().metricPublishers().size()) + .isEqualTo(0); + }); + } + @Test void usesMetricsPublisherIfAvailable() { this.contextRunner.run(context -> { assertThat(context).hasSingleBean(MetricPublisher.class); assertThat(context).hasSingleBean(SnsClientBuilder.class); - assertThat(context.getBean(SnsClientBuilder.class).overrideConfiguration().metricPublishers().size()).isEqualTo(1); + assertThat(context.getBean(SnsClientBuilder.class).overrideConfiguration().metricPublishers().size()) + .isEqualTo(1); }); } @@ -123,7 +150,8 @@ void doesNotUseMetricsPublisherIfNotAvailable() { this.contextRunner.withClassLoader(new FilteredClassLoader(CloudWatchMetricPublisher.class)).run(context -> { assertThat(context).doesNotHaveBean(MetricPublisher.class); assertThat(context).hasSingleBean(SnsClientBuilder.class); - assertThat(context.getBean(SnsClientBuilder.class).overrideConfiguration().metricPublishers().size()).isEqualTo(0); + assertThat(context.getBean(SnsClientBuilder.class).overrideConfiguration().metricPublishers().size()) + .isEqualTo(0); }); } From aa40fb72b4c610f0700b1cac5e62c32d3a7ebdc8 Mon Sep 17 00:00:00 2001 From: krimsz Date: Tue, 5 Jul 2022 09:47:35 +0200 Subject: [PATCH 06/10] Add region to MetricsPublisher --- .../core/AwsAutoConfiguration.java | 22 +------ .../core/AwsClientBuilderConfigurer.java | 19 +++++- ...atchMetricsPublisherAutoConfiguration.java | 58 +++++++++++++++++++ .../dynamodb/DynamoDbAutoConfiguration.java | 2 +- .../autoconfigure/s3/S3AutoConfiguration.java | 2 +- .../ses/SesAutoConfiguration.java | 2 +- .../sns/SnsAutoConfiguration.java | 2 +- .../main/resources/META-INF/spring.factories | 1 + .../core/AwsAutoConfigurationTests.java | 11 ---- ...etricsPublisherAutoConfigurationTests.java | 45 ++++++++++++++ .../DynamoDbAutoConfigurationTest.java | 5 +- .../s3/S3AutoConfigurationTests.java | 3 +- .../ses/SesAutoConfigurationTest.java | 3 +- .../sns/SnsAutoConfigurationTest.java | 3 +- 14 files changed, 137 insertions(+), 41 deletions(-) create mode 100644 spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/CloudWatchMetricsPublisherAutoConfiguration.java create mode 100644 spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/core/CloudWatchMetricsPublisherAutoConfigurationTests.java diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsAutoConfiguration.java index 14e33baf7..fe51da8b7 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsAutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsAutoConfiguration.java @@ -15,7 +15,6 @@ */ package io.awspring.cloud.autoconfigure.core; -import java.time.Duration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -28,6 +27,8 @@ import software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher; import software.amazon.awssdk.regions.providers.AwsRegionProvider; +import java.time.Duration; + /** * Autoconfigures AWS environment. * @@ -38,29 +39,12 @@ @EnableConfigurationProperties(AwsProperties.class) public class AwsAutoConfiguration { - private static AwsProperties awsProperties; + private final AwsProperties awsProperties; public AwsAutoConfiguration(AwsProperties awsProperties) { this.awsProperties = awsProperties; } - @ConditionalOnClass(CloudWatchMetricPublisher.class) - static class MetricsAutoConfiguration { - @Bean - @ConditionalOnMissingBean - @ConditionalOnProperty(name = "spring.cloud.aws.metrics.enabled", havingValue = "true", matchIfMissing = true) - MetricPublisher cloudWatchMetricPublisher() { - CloudWatchMetricPublisher.Builder builder = CloudWatchMetricPublisher.builder(); - PropertyMapper propertyMapper = PropertyMapper.get(); - if (awsProperties.getMetrics() != null) { - propertyMapper.from(awsProperties.getMetrics()::getNamespace).whenNonNull().to(builder::namespace); - propertyMapper.from(awsProperties.getMetrics()::getUploadFrequencyInSeconds).whenNonNull() - .to(v -> builder.uploadFrequency(Duration.ofSeconds(v))); - } - return builder.build(); - } - } - @Bean public AwsClientBuilderConfigurer awsClientBuilderConfigurer(AwsCredentialsProvider credentialsProvider, AwsRegionProvider awsRegionProvider) { diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsClientBuilderConfigurer.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsClientBuilderConfigurer.java index 4f5176ae4..2c96ac57e 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsClientBuilderConfigurer.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsClientBuilderConfigurer.java @@ -16,9 +16,12 @@ package io.awspring.cloud.autoconfigure.core; import io.awspring.cloud.autoconfigure.AwsClientProperties; +import io.awspring.cloud.autoconfigure.metrics.CloudWatchProperties; import io.awspring.cloud.core.SpringCloudClientConfiguration; import java.time.Duration; import java.util.Optional; + +import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -26,11 +29,14 @@ import org.springframework.util.StringUtils; import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; import software.amazon.awssdk.awscore.client.builder.AwsClientBuilder; +import software.amazon.awssdk.core.client.builder.SdkClientBuilder; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.metrics.MetricPublisher; import software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.regions.providers.AwsRegionProvider; +import software.amazon.awssdk.services.cloudwatch.CloudWatchAsyncClient; +import software.amazon.awssdk.services.cloudwatch.CloudWatchAsyncClientBuilder; /** * Provides a convenience method to apply common configuration to any {@link AwsClientBuilder}. @@ -88,12 +94,21 @@ public Region resolveRegion(@Nullable AwsClientProperties clientProperties) { } public static @Nullable MetricPublisher createSpecificMetricPublisher(MetricPublisher metricPublisher, - AwsClientProperties properties) { + AwsClientProperties properties, AwsClientBuilderConfigurer awsClientBuilderConfigurer) { + if (ClassUtils.isPresent("software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher", null) && properties.getMetrics() != null) { if (properties.getMetrics().getEnabled() == null || properties.getMetrics().getEnabled()) { - CloudWatchMetricPublisher.Builder builder = CloudWatchMetricPublisher.builder(); PropertyMapper propertyMapper = PropertyMapper.get(); + + CloudWatchAsyncClientBuilder cloudWatchAsyncClientBuilder = CloudWatchAsyncClient.builder(); + CloudWatchProperties cloudWatchProperties = new CloudWatchProperties(); + propertyMapper.from(cloudWatchProperties.getEndpoint()).whenNonNull().to(cloudWatchProperties::setEndpoint); + propertyMapper.from(cloudWatchProperties.getRegion()).whenNonNull().to(cloudWatchProperties::setRegion); + CloudWatchAsyncClient cloudWatchAsyncClient = awsClientBuilderConfigurer.configure(cloudWatchAsyncClientBuilder, cloudWatchProperties, null, null).build(); + + CloudWatchMetricPublisher.Builder builder = CloudWatchMetricPublisher.builder(); + builder.cloudWatchClient(cloudWatchAsyncClient); propertyMapper.from(properties.getMetrics()::getNamespace).whenNonNull().to(builder::namespace); propertyMapper.from(properties.getMetrics()::getUploadFrequencyInSeconds).whenNonNull() .to(v -> builder.uploadFrequency(Duration.ofSeconds(v))); diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/CloudWatchMetricsPublisherAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/CloudWatchMetricsPublisherAutoConfiguration.java new file mode 100644 index 000000000..f3f9a0198 --- /dev/null +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/CloudWatchMetricsPublisherAutoConfiguration.java @@ -0,0 +1,58 @@ +package io.awspring.cloud.autoconfigure.core; + +import io.awspring.cloud.autoconfigure.AwsClientProperties; +import io.awspring.cloud.autoconfigure.metrics.CloudWatchProperties; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.context.properties.PropertyMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import software.amazon.awssdk.metrics.MetricPublisher; +import software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher; +import software.amazon.awssdk.regions.providers.AwsRegionProvider; +import software.amazon.awssdk.services.cloudwatch.CloudWatchAsyncClient; +import software.amazon.awssdk.services.cloudwatch.CloudWatchAsyncClientBuilder; +import software.amazon.awssdk.services.dynamodb.DynamoDbClientBuilder; + +import java.time.Duration; +import java.util.Optional; + +@Configuration(proxyBeanMethods = false) +@EnableConfigurationProperties(AwsProperties.class) +@ConditionalOnClass({ CloudWatchMetricPublisher.class }) +@AutoConfigureAfter({ CredentialsProviderAutoConfiguration.class, RegionProviderAutoConfiguration.class}) +public class CloudWatchMetricsPublisherAutoConfiguration { + + private final AwsProperties awsProperties; + + public CloudWatchMetricsPublisherAutoConfiguration(AwsProperties awsProperties) { + this.awsProperties = awsProperties; + } + + @Bean + @ConditionalOnMissingBean + @ConditionalOnProperty(name = "spring.cloud.aws.metrics.enabled", havingValue = "true", matchIfMissing = true) + MetricPublisher cloudWatchMetricPublisher(AwsClientBuilderConfigurer awsClientBuilderConfigurer, ObjectProvider> configurer) { + PropertyMapper propertyMapper = PropertyMapper.get(); + + CloudWatchAsyncClientBuilder cloudWatchAsyncClientBuilder = CloudWatchAsyncClient.builder(); + CloudWatchProperties cloudWatchProperties = new CloudWatchProperties(); + propertyMapper.from(cloudWatchProperties.getEndpoint()).whenNonNull().to(cloudWatchProperties::setEndpoint); + propertyMapper.from(cloudWatchProperties.getRegion()).whenNonNull().to(cloudWatchProperties::setRegion); + CloudWatchAsyncClient cloudWatchAsyncClient = awsClientBuilderConfigurer.configure(cloudWatchAsyncClientBuilder, cloudWatchProperties, configurer.getIfAvailable(), null).build(); + + CloudWatchMetricPublisher.Builder builder = CloudWatchMetricPublisher.builder(); + builder.cloudWatchClient(cloudWatchAsyncClient); + + if (awsProperties.getMetrics() != null) { + propertyMapper.from(awsProperties.getMetrics()::getNamespace).whenNonNull().to(builder::namespace); + propertyMapper.from(awsProperties.getMetrics()::getUploadFrequencyInSeconds).whenNonNull() + .to(v -> builder.uploadFrequency(Duration.ofSeconds(v))); + } + return builder.build(); + } +} diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfiguration.java index 2184737b6..96e214821 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfiguration.java @@ -62,7 +62,7 @@ public DynamoDbClientBuilder dynamoDbClientBuilder(AwsClientBuilderConfigurer aw ObjectProvider> configurer, ObjectProvider metricPublisherObjectProvider) { MetricPublisher metricPublisher = createSpecificMetricPublisher(metricPublisherObjectProvider.getIfAvailable(), - properties); + properties, awsClientBuilderConfigurer); return awsClientBuilderConfigurer.configure(DynamoDbClient.builder(), properties, configurer.getIfAvailable(), metricPublisher); } diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/S3AutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/S3AutoConfiguration.java index 4e002a4c2..1900cd33d 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/S3AutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/S3AutoConfiguration.java @@ -74,7 +74,7 @@ S3ClientBuilder s3ClientBuilder(AwsClientBuilderConfigurer awsClientBuilderConfi ObjectProvider> configurer, ObjectProvider metricPublisherObjectProvider) { MetricPublisher metricPublisher = createSpecificMetricPublisher(metricPublisherObjectProvider.getIfAvailable(), - properties); + properties, awsClientBuilderConfigurer); S3ClientBuilder builder = awsClientBuilderConfigurer.configure(S3Client.builder(), this.properties, configurer.getIfAvailable(), metricPublisher); builder.serviceConfiguration(s3ServiceConfiguration()); diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/ses/SesAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/ses/SesAutoConfiguration.java index 796e6bfa2..373a25acd 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/ses/SesAutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/ses/SesAutoConfiguration.java @@ -61,7 +61,7 @@ public SesClientBuilder sesClientBuilder(SesProperties properties, ObjectProvider> configurer, ObjectProvider metricPublisherObjectProvider) { MetricPublisher metricPublisher = createSpecificMetricPublisher(metricPublisherObjectProvider.getIfAvailable(), - properties); + properties, awsClientBuilderConfigurer); return awsClientBuilderConfigurer.configure(SesClient.builder(), properties, configurer.getIfAvailable(), metricPublisher); } diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/sns/SnsAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/sns/SnsAutoConfiguration.java index 676ac533e..96a2e41a7 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/sns/SnsAutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/sns/SnsAutoConfiguration.java @@ -67,7 +67,7 @@ public SnsClientBuilder snsClientBuilder(SnsProperties properties, ObjectProvider> configurer, ObjectProvider metricPublisherObjectProvider) { MetricPublisher metricPublisher = createSpecificMetricPublisher(metricPublisherObjectProvider.getIfAvailable(), - properties); + properties, awsClientBuilderConfigurer); return awsClientBuilderConfigurer.configure(SnsClient.builder(), properties, configurer.getIfAvailable(), metricPublisher); } diff --git a/spring-cloud-aws-autoconfigure/src/main/resources/META-INF/spring.factories b/spring-cloud-aws-autoconfigure/src/main/resources/META-INF/spring.factories index d8cb47a45..7e2068df8 100644 --- a/spring-cloud-aws-autoconfigure/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-aws-autoconfigure/src/main/resources/META-INF/spring.factories @@ -3,6 +3,7 @@ io.awspring.cloud.autoconfigure.core.AwsAutoConfiguration,\ io.awspring.cloud.autoconfigure.core.CredentialsProviderAutoConfiguration,\ io.awspring.cloud.autoconfigure.core.RegionProviderAutoConfiguration,\ io.awspring.cloud.autoconfigure.metrics.CloudWatchExportAutoConfiguration,\ +io.awspring.cloud.autoconfigure.core.CloudWatchMetricsPublisherAutoConfiguration,\ io.awspring.cloud.autoconfigure.ses.SesAutoConfiguration,\ io.awspring.cloud.autoconfigure.s3.S3TransferManagerAutoConfiguration,\ io.awspring.cloud.autoconfigure.s3.S3AutoConfiguration,\ diff --git a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/core/AwsAutoConfigurationTests.java b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/core/AwsAutoConfigurationTests.java index 342cbb30a..5e41536bb 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/core/AwsAutoConfigurationTests.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/core/AwsAutoConfigurationTests.java @@ -31,17 +31,6 @@ class AwsAutoConfigurationTests { AutoConfigurations.of(CredentialsProviderAutoConfiguration.class, AwsAutoConfiguration.class)) .withBean(CustomRegionProvider.class); - @Test - void createsMetricsPublisherByDefaultWhenDependencyInClasspath() { - contextRunner.run((context) -> assertThat(context).hasSingleBean(MetricPublisher.class)); - } - - @Test - void createsMetricsPublisherWhenSpecifiedExplicitlyAndDependencyInClasspath() { - contextRunner.withPropertyValues("spring.cloud.aws.metrics.enabled:true") - .run((context) -> assertThat(context).hasSingleBean(MetricPublisher.class)); - } - @Test void doesNotCreateMetricsPublisherWhenDisabledExplicitlyAndDependencyInClasspath() { contextRunner.withPropertyValues("spring.cloud.aws.metrics.enabled:false") diff --git a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/core/CloudWatchMetricsPublisherAutoConfigurationTests.java b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/core/CloudWatchMetricsPublisherAutoConfigurationTests.java new file mode 100644 index 000000000..03b9aa09c --- /dev/null +++ b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/core/CloudWatchMetricsPublisherAutoConfigurationTests.java @@ -0,0 +1,45 @@ +/* + * Copyright 2013-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.awspring.cloud.autoconfigure.core; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import software.amazon.awssdk.metrics.MetricPublisher; + +import static org.assertj.core.api.Assertions.assertThat; + +class CloudWatchMetricsPublisherAutoConfigurationTests { + + private static ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withPropertyValues("spring.cloud.aws.region.static:eu-west-1") + .withConfiguration(AutoConfigurations.of(RegionProviderAutoConfiguration.class, + CredentialsProviderAutoConfiguration.class, + CloudWatchMetricsPublisherAutoConfiguration.class, + AwsAutoConfiguration.class)); + + @Test + void createsMetricsPublisherByDefaultWhenDependencyInClasspath() { + contextRunner.run((context) -> assertThat(context).hasSingleBean(MetricPublisher.class)); + } + + @Test + void createsMetricsPublisherWhenSpecifiedExplicitlyAndDependencyInClasspath() { + contextRunner.withPropertyValues("spring.cloud.aws.metrics.enabled:true") + .run((context) -> assertThat(context).hasSingleBean(MetricPublisher.class)); + } + +} diff --git a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfigurationTest.java b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfigurationTest.java index 7aca78020..d72ef17d2 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfigurationTest.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfigurationTest.java @@ -20,6 +20,7 @@ import io.awspring.cloud.autoconfigure.ConfiguredAwsClient; import io.awspring.cloud.autoconfigure.core.AwsAutoConfiguration; import io.awspring.cloud.autoconfigure.core.AwsClientCustomizer; +import io.awspring.cloud.autoconfigure.core.CloudWatchMetricsPublisherAutoConfiguration; import io.awspring.cloud.autoconfigure.core.CredentialsProviderAutoConfiguration; import io.awspring.cloud.autoconfigure.core.RegionProviderAutoConfiguration; import io.awspring.cloud.dynamodb.DynamoDbTableNameResolver; @@ -55,8 +56,8 @@ class DynamoDbAutoConfigurationTest { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.cloud.aws.region.static:eu-west-1") .withConfiguration(AutoConfigurations.of(RegionProviderAutoConfiguration.class, - CredentialsProviderAutoConfiguration.class, DynamoDbAutoConfiguration.class, - AwsAutoConfiguration.class)); + CredentialsProviderAutoConfiguration.class, CloudWatchMetricsPublisherAutoConfiguration.class, + DynamoDbAutoConfiguration.class, AwsAutoConfiguration.class)); @Test void dynamoDBAutoConfigurationIsDisabled() { diff --git a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/s3/S3AutoConfigurationTests.java b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/s3/S3AutoConfigurationTests.java index 5109605ad..ddcda8466 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/s3/S3AutoConfigurationTests.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/s3/S3AutoConfigurationTests.java @@ -22,6 +22,7 @@ import io.awspring.cloud.autoconfigure.ConfiguredAwsClient; import io.awspring.cloud.autoconfigure.core.AwsAutoConfiguration; import io.awspring.cloud.autoconfigure.core.AwsClientCustomizer; +import io.awspring.cloud.autoconfigure.core.CloudWatchMetricsPublisherAutoConfiguration; import io.awspring.cloud.autoconfigure.core.CredentialsProviderAutoConfiguration; import io.awspring.cloud.autoconfigure.core.RegionProviderAutoConfiguration; import io.awspring.cloud.autoconfigure.s3.properties.S3Properties; @@ -67,7 +68,7 @@ class S3AutoConfigurationTests { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.cloud.aws.region.static:eu-west-1") .withConfiguration(AutoConfigurations.of(AwsAutoConfiguration.class, RegionProviderAutoConfiguration.class, - CredentialsProviderAutoConfiguration.class, S3AutoConfiguration.class)); + CloudWatchMetricsPublisherAutoConfiguration.class, CredentialsProviderAutoConfiguration.class, S3AutoConfiguration.class)); @Test void createsS3ClientBean() { diff --git a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/ses/SesAutoConfigurationTest.java b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/ses/SesAutoConfigurationTest.java index 64f8b96c9..b92837a18 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/ses/SesAutoConfigurationTest.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/ses/SesAutoConfigurationTest.java @@ -20,6 +20,7 @@ import io.awspring.cloud.autoconfigure.ConfiguredAwsClient; import io.awspring.cloud.autoconfigure.core.AwsAutoConfiguration; import io.awspring.cloud.autoconfigure.core.AwsClientCustomizer; +import io.awspring.cloud.autoconfigure.core.CloudWatchMetricsPublisherAutoConfiguration; import io.awspring.cloud.autoconfigure.core.CredentialsProviderAutoConfiguration; import io.awspring.cloud.autoconfigure.core.RegionProviderAutoConfiguration; import java.net.URI; @@ -54,7 +55,7 @@ class SesAutoConfigurationTest { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.cloud.aws.region.static:eu-west-1") .withConfiguration(AutoConfigurations.of(AwsAutoConfiguration.class, RegionProviderAutoConfiguration.class, - CredentialsProviderAutoConfiguration.class, SesAutoConfiguration.class)); + CloudWatchMetricsPublisherAutoConfiguration.class, CredentialsProviderAutoConfiguration.class, SesAutoConfiguration.class)); @Test void mailSenderWithJavaMail() { diff --git a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/sns/SnsAutoConfigurationTest.java b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/sns/SnsAutoConfigurationTest.java index 97de1f48e..edcf29cca 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/sns/SnsAutoConfigurationTest.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/sns/SnsAutoConfigurationTest.java @@ -20,6 +20,7 @@ import io.awspring.cloud.autoconfigure.ConfiguredAwsClient; import io.awspring.cloud.autoconfigure.core.AwsAutoConfiguration; import io.awspring.cloud.autoconfigure.core.AwsClientCustomizer; +import io.awspring.cloud.autoconfigure.core.CloudWatchMetricsPublisherAutoConfiguration; import io.awspring.cloud.autoconfigure.core.CredentialsProviderAutoConfiguration; import io.awspring.cloud.autoconfigure.core.RegionProviderAutoConfiguration; import io.awspring.cloud.sns.core.SnsTemplate; @@ -58,7 +59,7 @@ class SnsAutoConfigurationTest { .withPropertyValues("spring.cloud.aws.region.static:eu-west-1") .withConfiguration(AutoConfigurations.of(RegionProviderAutoConfiguration.class, CredentialsProviderAutoConfiguration.class, SnsAutoConfiguration.class, - AwsAutoConfiguration.class)); + CloudWatchMetricsPublisherAutoConfiguration.class, AwsAutoConfiguration.class)); @Test void snsAutoConfigurationIsDisabled() { From 91a64bdab4c74e1febfe4d749933398924fa88c3 Mon Sep 17 00:00:00 2001 From: krimsz Date: Tue, 5 Jul 2022 09:47:35 +0200 Subject: [PATCH 07/10] Reformat code --- .../core/AwsAutoConfiguration.java | 8 - .../core/AwsClientBuilderConfigurer.java | 9 +- ...atchMetricsPublisherAutoConfiguration.java | 33 +- ...etricsPublisherAutoConfigurationTests.java | 13 +- .../DynamoDbAutoConfigurationTest.java | 2 +- .../s3/S3AutoConfigurationTests.java | 3 +- .../ses/SesAutoConfigurationTest.java | 3 +- .../s3/crossregion/CrossRegionS3Client.java | 1393 ++++++++++------- 8 files changed, 840 insertions(+), 624 deletions(-) diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsAutoConfiguration.java index fe51da8b7..3aa49f1e1 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsAutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsAutoConfiguration.java @@ -15,20 +15,12 @@ */ package io.awspring.cloud.autoconfigure.core; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; -import software.amazon.awssdk.metrics.MetricPublisher; -import software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher; import software.amazon.awssdk.regions.providers.AwsRegionProvider; -import java.time.Duration; - /** * Autoconfigures AWS environment. * diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsClientBuilderConfigurer.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsClientBuilderConfigurer.java index 2c96ac57e..6311547ff 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsClientBuilderConfigurer.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsClientBuilderConfigurer.java @@ -20,8 +20,6 @@ import io.awspring.cloud.core.SpringCloudClientConfiguration; import java.time.Duration; import java.util.Optional; - -import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -29,7 +27,6 @@ import org.springframework.util.StringUtils; import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; import software.amazon.awssdk.awscore.client.builder.AwsClientBuilder; -import software.amazon.awssdk.core.client.builder.SdkClientBuilder; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.metrics.MetricPublisher; import software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher; @@ -103,9 +100,11 @@ public Region resolveRegion(@Nullable AwsClientProperties clientProperties) { CloudWatchAsyncClientBuilder cloudWatchAsyncClientBuilder = CloudWatchAsyncClient.builder(); CloudWatchProperties cloudWatchProperties = new CloudWatchProperties(); - propertyMapper.from(cloudWatchProperties.getEndpoint()).whenNonNull().to(cloudWatchProperties::setEndpoint); + propertyMapper.from(cloudWatchProperties.getEndpoint()).whenNonNull() + .to(cloudWatchProperties::setEndpoint); propertyMapper.from(cloudWatchProperties.getRegion()).whenNonNull().to(cloudWatchProperties::setRegion); - CloudWatchAsyncClient cloudWatchAsyncClient = awsClientBuilderConfigurer.configure(cloudWatchAsyncClientBuilder, cloudWatchProperties, null, null).build(); + CloudWatchAsyncClient cloudWatchAsyncClient = awsClientBuilderConfigurer + .configure(cloudWatchAsyncClientBuilder, cloudWatchProperties, null, null).build(); CloudWatchMetricPublisher.Builder builder = CloudWatchMetricPublisher.builder(); builder.cloudWatchClient(cloudWatchAsyncClient); diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/CloudWatchMetricsPublisherAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/CloudWatchMetricsPublisherAutoConfiguration.java index f3f9a0198..1f4444f86 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/CloudWatchMetricsPublisherAutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/CloudWatchMetricsPublisherAutoConfiguration.java @@ -1,7 +1,22 @@ +/* + * Copyright 2013-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package io.awspring.cloud.autoconfigure.core; -import io.awspring.cloud.autoconfigure.AwsClientProperties; import io.awspring.cloud.autoconfigure.metrics.CloudWatchProperties; +import java.time.Duration; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -13,18 +28,13 @@ import org.springframework.context.annotation.Configuration; import software.amazon.awssdk.metrics.MetricPublisher; import software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher; -import software.amazon.awssdk.regions.providers.AwsRegionProvider; import software.amazon.awssdk.services.cloudwatch.CloudWatchAsyncClient; import software.amazon.awssdk.services.cloudwatch.CloudWatchAsyncClientBuilder; -import software.amazon.awssdk.services.dynamodb.DynamoDbClientBuilder; - -import java.time.Duration; -import java.util.Optional; @Configuration(proxyBeanMethods = false) @EnableConfigurationProperties(AwsProperties.class) @ConditionalOnClass({ CloudWatchMetricPublisher.class }) -@AutoConfigureAfter({ CredentialsProviderAutoConfiguration.class, RegionProviderAutoConfiguration.class}) +@AutoConfigureAfter({ CredentialsProviderAutoConfiguration.class, RegionProviderAutoConfiguration.class }) public class CloudWatchMetricsPublisherAutoConfiguration { private final AwsProperties awsProperties; @@ -36,14 +46,17 @@ public CloudWatchMetricsPublisherAutoConfiguration(AwsProperties awsProperties) @Bean @ConditionalOnMissingBean @ConditionalOnProperty(name = "spring.cloud.aws.metrics.enabled", havingValue = "true", matchIfMissing = true) - MetricPublisher cloudWatchMetricPublisher(AwsClientBuilderConfigurer awsClientBuilderConfigurer, ObjectProvider> configurer) { + MetricPublisher cloudWatchMetricPublisher(AwsClientBuilderConfigurer awsClientBuilderConfigurer, + ObjectProvider> configurer) { PropertyMapper propertyMapper = PropertyMapper.get(); CloudWatchAsyncClientBuilder cloudWatchAsyncClientBuilder = CloudWatchAsyncClient.builder(); CloudWatchProperties cloudWatchProperties = new CloudWatchProperties(); propertyMapper.from(cloudWatchProperties.getEndpoint()).whenNonNull().to(cloudWatchProperties::setEndpoint); propertyMapper.from(cloudWatchProperties.getRegion()).whenNonNull().to(cloudWatchProperties::setRegion); - CloudWatchAsyncClient cloudWatchAsyncClient = awsClientBuilderConfigurer.configure(cloudWatchAsyncClientBuilder, cloudWatchProperties, configurer.getIfAvailable(), null).build(); + CloudWatchAsyncClient cloudWatchAsyncClient = awsClientBuilderConfigurer + .configure(cloudWatchAsyncClientBuilder, cloudWatchProperties, configurer.getIfAvailable(), null) + .build(); CloudWatchMetricPublisher.Builder builder = CloudWatchMetricPublisher.builder(); builder.cloudWatchClient(cloudWatchAsyncClient); @@ -51,7 +64,7 @@ MetricPublisher cloudWatchMetricPublisher(AwsClientBuilderConfigurer awsClientBu if (awsProperties.getMetrics() != null) { propertyMapper.from(awsProperties.getMetrics()::getNamespace).whenNonNull().to(builder::namespace); propertyMapper.from(awsProperties.getMetrics()::getUploadFrequencyInSeconds).whenNonNull() - .to(v -> builder.uploadFrequency(Duration.ofSeconds(v))); + .to(v -> builder.uploadFrequency(Duration.ofSeconds(v))); } return builder.build(); } diff --git a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/core/CloudWatchMetricsPublisherAutoConfigurationTests.java b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/core/CloudWatchMetricsPublisherAutoConfigurationTests.java index 03b9aa09c..b9627f8c0 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/core/CloudWatchMetricsPublisherAutoConfigurationTests.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/core/CloudWatchMetricsPublisherAutoConfigurationTests.java @@ -15,21 +15,20 @@ */ package io.awspring.cloud.autoconfigure.core; +import static org.assertj.core.api.Assertions.assertThat; + import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import software.amazon.awssdk.metrics.MetricPublisher; -import static org.assertj.core.api.Assertions.assertThat; - class CloudWatchMetricsPublisherAutoConfigurationTests { private static ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withPropertyValues("spring.cloud.aws.region.static:eu-west-1") - .withConfiguration(AutoConfigurations.of(RegionProviderAutoConfiguration.class, - CredentialsProviderAutoConfiguration.class, - CloudWatchMetricsPublisherAutoConfiguration.class, - AwsAutoConfiguration.class)); + .withPropertyValues("spring.cloud.aws.region.static:eu-west-1") + .withConfiguration(AutoConfigurations.of(RegionProviderAutoConfiguration.class, + CredentialsProviderAutoConfiguration.class, CloudWatchMetricsPublisherAutoConfiguration.class, + AwsAutoConfiguration.class)); @Test void createsMetricsPublisherByDefaultWhenDependencyInClasspath() { diff --git a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfigurationTest.java b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfigurationTest.java index d72ef17d2..93145e424 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfigurationTest.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/dynamodb/DynamoDbAutoConfigurationTest.java @@ -57,7 +57,7 @@ class DynamoDbAutoConfigurationTest { .withPropertyValues("spring.cloud.aws.region.static:eu-west-1") .withConfiguration(AutoConfigurations.of(RegionProviderAutoConfiguration.class, CredentialsProviderAutoConfiguration.class, CloudWatchMetricsPublisherAutoConfiguration.class, - DynamoDbAutoConfiguration.class, AwsAutoConfiguration.class)); + DynamoDbAutoConfiguration.class, AwsAutoConfiguration.class)); @Test void dynamoDBAutoConfigurationIsDisabled() { diff --git a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/s3/S3AutoConfigurationTests.java b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/s3/S3AutoConfigurationTests.java index ddcda8466..3b0ba79b3 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/s3/S3AutoConfigurationTests.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/s3/S3AutoConfigurationTests.java @@ -68,7 +68,8 @@ class S3AutoConfigurationTests { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.cloud.aws.region.static:eu-west-1") .withConfiguration(AutoConfigurations.of(AwsAutoConfiguration.class, RegionProviderAutoConfiguration.class, - CloudWatchMetricsPublisherAutoConfiguration.class, CredentialsProviderAutoConfiguration.class, S3AutoConfiguration.class)); + CloudWatchMetricsPublisherAutoConfiguration.class, CredentialsProviderAutoConfiguration.class, + S3AutoConfiguration.class)); @Test void createsS3ClientBean() { diff --git a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/ses/SesAutoConfigurationTest.java b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/ses/SesAutoConfigurationTest.java index b92837a18..a0f91b4ae 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/ses/SesAutoConfigurationTest.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/ses/SesAutoConfigurationTest.java @@ -55,7 +55,8 @@ class SesAutoConfigurationTest { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withPropertyValues("spring.cloud.aws.region.static:eu-west-1") .withConfiguration(AutoConfigurations.of(AwsAutoConfiguration.class, RegionProviderAutoConfiguration.class, - CloudWatchMetricsPublisherAutoConfiguration.class, CredentialsProviderAutoConfiguration.class, SesAutoConfiguration.class)); + CloudWatchMetricsPublisherAutoConfiguration.class, CredentialsProviderAutoConfiguration.class, + SesAutoConfiguration.class)); @Test void mailSenderWithJavaMail() { diff --git a/spring-cloud-aws-s3-parent/spring-cloud-aws-s3-cross-region-client/src/main/java/io/awspring/cloud/s3/crossregion/CrossRegionS3Client.java b/spring-cloud-aws-s3-parent/spring-cloud-aws-s3-cross-region-client/src/main/java/io/awspring/cloud/s3/crossregion/CrossRegionS3Client.java index c0d604a42..bbda6fdb8 100644 --- a/spring-cloud-aws-s3-parent/spring-cloud-aws-s3-cross-region-client/src/main/java/io/awspring/cloud/s3/crossregion/CrossRegionS3Client.java +++ b/spring-cloud-aws-s3-parent/spring-cloud-aws-s3-cross-region-client/src/main/java/io/awspring/cloud/s3/crossregion/CrossRegionS3Client.java @@ -38,595 +38,806 @@ public class CrossRegionS3Client implements S3Client { - private static final Logger LOGGER = LoggerFactory.getLogger("io.awspring.cloud.s3.CrossRegionS3Client"); - - private static final int DEFAULT_BUCKET_CACHE_SIZE = 20; - - private final Map clientCache = new ConcurrentHashMap<>(Region.regions().size()); - - private final S3Client defaultS3Client; - - private final ConcurrentLruCache bucketCache; - - public CrossRegionS3Client(S3ClientBuilder clientBuilder) { - this(DEFAULT_BUCKET_CACHE_SIZE, clientBuilder); - } - - public CrossRegionS3Client(int bucketCacheSize, S3ClientBuilder clientBuilder) { - this.defaultS3Client = clientBuilder.build(); - this.bucketCache = new ConcurrentLruCache<>(bucketCacheSize, bucket -> { - Region region = resolveBucketRegion(bucket); - return clientCache.computeIfAbsent(region, r -> { - LOGGER.debug("Creating new S3 client for region: {}", r); - return clientBuilder.region(r).build(); - }); - }); - } - - @Override - public ListBucketsResponse listBuckets(ListBucketsRequest request) throws AwsServiceException, SdkClientException { - return defaultS3Client.listBuckets(request); - } - - @Override - public WriteGetObjectResponseResponse writeGetObjectResponse(WriteGetObjectResponseRequest request, RequestBody requestBody) throws AwsServiceException, SdkClientException { - return defaultS3Client.writeGetObjectResponse(request, requestBody); - } - - // visible for testing - Map getClientCache() { - return clientCache; - } - - private Result executeInBucketRegion(String bucket, Function fn) { - try { - if (bucketCache.contains(bucket)) { - return fn.apply(bucketCache.get(bucket)); - } else { - return fn.apply(defaultS3Client); - } - } catch (S3Exception e) { - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Exception when requesting S3: {}", e.awsErrorDetails().errorCode(), e); - } else { - LOGGER.debug("Exception when requesting S3 for bucket: {}: [{}] {}", bucket, e.awsErrorDetails().errorCode(), e.awsErrorDetails().errorMessage()); - } - // "PermanentRedirect" means that the bucket is in different region than the - // defaultS3Client is configured for - if ("PermanentRedirect".equals(e.awsErrorDetails().errorCode())) { - return fn.apply(bucketCache.get(bucket)); - } else { - throw e; - } - } - } - - private Region resolveBucketRegion(String bucket) { - LOGGER.debug("Resolving region for bucket {}", bucket); - String bucketLocation = defaultS3Client.getBucketLocation(GetBucketLocationRequest.builder().bucket(bucket).build()).locationConstraintAsString(); - Region region = StringUtils.hasLength(bucketLocation) ? Region.of(bucketLocation) : Region.US_EAST_1; - LOGGER.debug("Region for bucket {} is {}", bucket, region); - return region; - } - - @Override - public String serviceName() { - return S3Client.SERVICE_NAME; - } - - @Override - public void close() { - this.clientCache.values().forEach(SdkAutoCloseable::close); - } - - @Override - public software.amazon.awssdk.services.s3.model.AbortMultipartUploadResponse abortMultipartUpload(software.amazon.awssdk.services.s3.model.AbortMultipartUploadRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.abortMultipartUpload(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.CompleteMultipartUploadResponse completeMultipartUpload(software.amazon.awssdk.services.s3.model.CompleteMultipartUploadRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.completeMultipartUpload(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.CopyObjectResponse copyObject(software.amazon.awssdk.services.s3.model.CopyObjectRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.copyObject(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.CreateBucketResponse createBucket(software.amazon.awssdk.services.s3.model.CreateBucketRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.createBucket(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.CreateMultipartUploadResponse createMultipartUpload(software.amazon.awssdk.services.s3.model.CreateMultipartUploadRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.createMultipartUpload(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.DeleteBucketResponse deleteBucket(software.amazon.awssdk.services.s3.model.DeleteBucketRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucket(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.DeleteBucketAnalyticsConfigurationResponse deleteBucketAnalyticsConfiguration(software.amazon.awssdk.services.s3.model.DeleteBucketAnalyticsConfigurationRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketAnalyticsConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.DeleteBucketCorsResponse deleteBucketCors(software.amazon.awssdk.services.s3.model.DeleteBucketCorsRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketCors(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.DeleteBucketEncryptionResponse deleteBucketEncryption(software.amazon.awssdk.services.s3.model.DeleteBucketEncryptionRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketEncryption(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.DeleteBucketIntelligentTieringConfigurationResponse deleteBucketIntelligentTieringConfiguration(software.amazon.awssdk.services.s3.model.DeleteBucketIntelligentTieringConfigurationRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketIntelligentTieringConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.DeleteBucketInventoryConfigurationResponse deleteBucketInventoryConfiguration(software.amazon.awssdk.services.s3.model.DeleteBucketInventoryConfigurationRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketInventoryConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.DeleteBucketLifecycleResponse deleteBucketLifecycle(software.amazon.awssdk.services.s3.model.DeleteBucketLifecycleRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketLifecycle(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.DeleteBucketMetricsConfigurationResponse deleteBucketMetricsConfiguration(software.amazon.awssdk.services.s3.model.DeleteBucketMetricsConfigurationRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketMetricsConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.DeleteBucketOwnershipControlsResponse deleteBucketOwnershipControls(software.amazon.awssdk.services.s3.model.DeleteBucketOwnershipControlsRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketOwnershipControls(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.DeleteBucketPolicyResponse deleteBucketPolicy(software.amazon.awssdk.services.s3.model.DeleteBucketPolicyRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketPolicy(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.DeleteBucketReplicationResponse deleteBucketReplication(software.amazon.awssdk.services.s3.model.DeleteBucketReplicationRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketReplication(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.DeleteBucketTaggingResponse deleteBucketTagging(software.amazon.awssdk.services.s3.model.DeleteBucketTaggingRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketTagging(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.DeleteBucketWebsiteResponse deleteBucketWebsite(software.amazon.awssdk.services.s3.model.DeleteBucketWebsiteRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketWebsite(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.DeleteObjectResponse deleteObject(software.amazon.awssdk.services.s3.model.DeleteObjectRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteObject(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.DeleteObjectTaggingResponse deleteObjectTagging(software.amazon.awssdk.services.s3.model.DeleteObjectTaggingRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteObjectTagging(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.DeleteObjectsResponse deleteObjects(software.amazon.awssdk.services.s3.model.DeleteObjectsRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteObjects(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.DeletePublicAccessBlockResponse deletePublicAccessBlock(software.amazon.awssdk.services.s3.model.DeletePublicAccessBlockRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deletePublicAccessBlock(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketAccelerateConfigurationResponse getBucketAccelerateConfiguration(software.amazon.awssdk.services.s3.model.GetBucketAccelerateConfigurationRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketAccelerateConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketAclResponse getBucketAcl(software.amazon.awssdk.services.s3.model.GetBucketAclRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketAcl(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketAnalyticsConfigurationResponse getBucketAnalyticsConfiguration(software.amazon.awssdk.services.s3.model.GetBucketAnalyticsConfigurationRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketAnalyticsConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketCorsResponse getBucketCors(software.amazon.awssdk.services.s3.model.GetBucketCorsRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketCors(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketEncryptionResponse getBucketEncryption(software.amazon.awssdk.services.s3.model.GetBucketEncryptionRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketEncryption(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketIntelligentTieringConfigurationResponse getBucketIntelligentTieringConfiguration(software.amazon.awssdk.services.s3.model.GetBucketIntelligentTieringConfigurationRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketIntelligentTieringConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketInventoryConfigurationResponse getBucketInventoryConfiguration(software.amazon.awssdk.services.s3.model.GetBucketInventoryConfigurationRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketInventoryConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketLifecycleConfigurationResponse getBucketLifecycleConfiguration(software.amazon.awssdk.services.s3.model.GetBucketLifecycleConfigurationRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketLifecycleConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketLocationResponse getBucketLocation(software.amazon.awssdk.services.s3.model.GetBucketLocationRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketLocation(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketLoggingResponse getBucketLogging(software.amazon.awssdk.services.s3.model.GetBucketLoggingRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketLogging(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketMetricsConfigurationResponse getBucketMetricsConfiguration(software.amazon.awssdk.services.s3.model.GetBucketMetricsConfigurationRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketMetricsConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketNotificationConfigurationResponse getBucketNotificationConfiguration(software.amazon.awssdk.services.s3.model.GetBucketNotificationConfigurationRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketNotificationConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketOwnershipControlsResponse getBucketOwnershipControls(software.amazon.awssdk.services.s3.model.GetBucketOwnershipControlsRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketOwnershipControls(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketPolicyResponse getBucketPolicy(software.amazon.awssdk.services.s3.model.GetBucketPolicyRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketPolicy(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketPolicyStatusResponse getBucketPolicyStatus(software.amazon.awssdk.services.s3.model.GetBucketPolicyStatusRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketPolicyStatus(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketReplicationResponse getBucketReplication(software.amazon.awssdk.services.s3.model.GetBucketReplicationRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketReplication(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketRequestPaymentResponse getBucketRequestPayment(software.amazon.awssdk.services.s3.model.GetBucketRequestPaymentRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketRequestPayment(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketTaggingResponse getBucketTagging(software.amazon.awssdk.services.s3.model.GetBucketTaggingRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketTagging(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketVersioningResponse getBucketVersioning(software.amazon.awssdk.services.s3.model.GetBucketVersioningRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketVersioning(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetBucketWebsiteResponse getBucketWebsite(software.amazon.awssdk.services.s3.model.GetBucketWebsiteRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketWebsite(p0)); - } - - @Override - public software.amazon.awssdk.core.ResponseInputStream getObject(software.amazon.awssdk.services.s3.model.GetObjectRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObject(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetObjectResponse getObject(software.amazon.awssdk.services.s3.model.GetObjectRequest p0, java.nio.file.Path p1) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObject(p0, p1)); - } - - @Override - public ReturnT getObject(software.amazon.awssdk.services.s3.model.GetObjectRequest p0, software.amazon.awssdk.core.sync.ResponseTransformer p1) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObject(p0, p1)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetObjectAclResponse getObjectAcl(software.amazon.awssdk.services.s3.model.GetObjectAclRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectAcl(p0)); - } - - @Override - public software.amazon.awssdk.core.ResponseBytes getObjectAsBytes(software.amazon.awssdk.services.s3.model.GetObjectRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectAsBytes(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetObjectAttributesResponse getObjectAttributes(software.amazon.awssdk.services.s3.model.GetObjectAttributesRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectAttributes(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetObjectLegalHoldResponse getObjectLegalHold(software.amazon.awssdk.services.s3.model.GetObjectLegalHoldRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectLegalHold(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetObjectLockConfigurationResponse getObjectLockConfiguration(software.amazon.awssdk.services.s3.model.GetObjectLockConfigurationRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectLockConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetObjectRetentionResponse getObjectRetention(software.amazon.awssdk.services.s3.model.GetObjectRetentionRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectRetention(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetObjectTaggingResponse getObjectTagging(software.amazon.awssdk.services.s3.model.GetObjectTaggingRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectTagging(p0)); - } - - @Override - public software.amazon.awssdk.core.ResponseInputStream getObjectTorrent(software.amazon.awssdk.services.s3.model.GetObjectTorrentRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectTorrent(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetObjectTorrentResponse getObjectTorrent(software.amazon.awssdk.services.s3.model.GetObjectTorrentRequest p0, java.nio.file.Path p1) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectTorrent(p0, p1)); - } - - @Override - public ReturnT getObjectTorrent(software.amazon.awssdk.services.s3.model.GetObjectTorrentRequest p0, software.amazon.awssdk.core.sync.ResponseTransformer p1) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectTorrent(p0, p1)); - } - - @Override - public software.amazon.awssdk.core.ResponseBytes getObjectTorrentAsBytes(software.amazon.awssdk.services.s3.model.GetObjectTorrentRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectTorrentAsBytes(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.GetPublicAccessBlockResponse getPublicAccessBlock(software.amazon.awssdk.services.s3.model.GetPublicAccessBlockRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getPublicAccessBlock(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.HeadBucketResponse headBucket(software.amazon.awssdk.services.s3.model.HeadBucketRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.headBucket(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.HeadObjectResponse headObject(software.amazon.awssdk.services.s3.model.HeadObjectRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.headObject(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.ListBucketAnalyticsConfigurationsResponse listBucketAnalyticsConfigurations(software.amazon.awssdk.services.s3.model.ListBucketAnalyticsConfigurationsRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listBucketAnalyticsConfigurations(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.ListBucketIntelligentTieringConfigurationsResponse listBucketIntelligentTieringConfigurations(software.amazon.awssdk.services.s3.model.ListBucketIntelligentTieringConfigurationsRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listBucketIntelligentTieringConfigurations(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.ListBucketInventoryConfigurationsResponse listBucketInventoryConfigurations(software.amazon.awssdk.services.s3.model.ListBucketInventoryConfigurationsRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listBucketInventoryConfigurations(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.ListBucketMetricsConfigurationsResponse listBucketMetricsConfigurations(software.amazon.awssdk.services.s3.model.ListBucketMetricsConfigurationsRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listBucketMetricsConfigurations(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.ListMultipartUploadsResponse listMultipartUploads(software.amazon.awssdk.services.s3.model.ListMultipartUploadsRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listMultipartUploads(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.paginators.ListMultipartUploadsIterable listMultipartUploadsPaginator(software.amazon.awssdk.services.s3.model.ListMultipartUploadsRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listMultipartUploadsPaginator(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.ListObjectVersionsResponse listObjectVersions(software.amazon.awssdk.services.s3.model.ListObjectVersionsRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listObjectVersions(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.paginators.ListObjectVersionsIterable listObjectVersionsPaginator(software.amazon.awssdk.services.s3.model.ListObjectVersionsRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listObjectVersionsPaginator(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.ListObjectsResponse listObjects(software.amazon.awssdk.services.s3.model.ListObjectsRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listObjects(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.ListObjectsV2Response listObjectsV2(software.amazon.awssdk.services.s3.model.ListObjectsV2Request p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listObjectsV2(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.paginators.ListObjectsV2Iterable listObjectsV2Paginator(software.amazon.awssdk.services.s3.model.ListObjectsV2Request p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listObjectsV2Paginator(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.ListPartsResponse listParts(software.amazon.awssdk.services.s3.model.ListPartsRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listParts(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.paginators.ListPartsIterable listPartsPaginator(software.amazon.awssdk.services.s3.model.ListPartsRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listPartsPaginator(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutBucketAccelerateConfigurationResponse putBucketAccelerateConfiguration(software.amazon.awssdk.services.s3.model.PutBucketAccelerateConfigurationRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketAccelerateConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutBucketAclResponse putBucketAcl(software.amazon.awssdk.services.s3.model.PutBucketAclRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketAcl(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutBucketAnalyticsConfigurationResponse putBucketAnalyticsConfiguration(software.amazon.awssdk.services.s3.model.PutBucketAnalyticsConfigurationRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketAnalyticsConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutBucketCorsResponse putBucketCors(software.amazon.awssdk.services.s3.model.PutBucketCorsRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketCors(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutBucketEncryptionResponse putBucketEncryption(software.amazon.awssdk.services.s3.model.PutBucketEncryptionRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketEncryption(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutBucketIntelligentTieringConfigurationResponse putBucketIntelligentTieringConfiguration(software.amazon.awssdk.services.s3.model.PutBucketIntelligentTieringConfigurationRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketIntelligentTieringConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutBucketInventoryConfigurationResponse putBucketInventoryConfiguration(software.amazon.awssdk.services.s3.model.PutBucketInventoryConfigurationRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketInventoryConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutBucketLifecycleConfigurationResponse putBucketLifecycleConfiguration(software.amazon.awssdk.services.s3.model.PutBucketLifecycleConfigurationRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketLifecycleConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutBucketLoggingResponse putBucketLogging(software.amazon.awssdk.services.s3.model.PutBucketLoggingRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketLogging(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutBucketMetricsConfigurationResponse putBucketMetricsConfiguration(software.amazon.awssdk.services.s3.model.PutBucketMetricsConfigurationRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketMetricsConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutBucketNotificationConfigurationResponse putBucketNotificationConfiguration(software.amazon.awssdk.services.s3.model.PutBucketNotificationConfigurationRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketNotificationConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutBucketOwnershipControlsResponse putBucketOwnershipControls(software.amazon.awssdk.services.s3.model.PutBucketOwnershipControlsRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketOwnershipControls(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutBucketPolicyResponse putBucketPolicy(software.amazon.awssdk.services.s3.model.PutBucketPolicyRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketPolicy(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutBucketReplicationResponse putBucketReplication(software.amazon.awssdk.services.s3.model.PutBucketReplicationRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketReplication(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutBucketRequestPaymentResponse putBucketRequestPayment(software.amazon.awssdk.services.s3.model.PutBucketRequestPaymentRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketRequestPayment(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutBucketTaggingResponse putBucketTagging(software.amazon.awssdk.services.s3.model.PutBucketTaggingRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketTagging(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutBucketVersioningResponse putBucketVersioning(software.amazon.awssdk.services.s3.model.PutBucketVersioningRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketVersioning(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutBucketWebsiteResponse putBucketWebsite(software.amazon.awssdk.services.s3.model.PutBucketWebsiteRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketWebsite(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutObjectResponse putObject(software.amazon.awssdk.services.s3.model.PutObjectRequest p0, java.nio.file.Path p1) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putObject(p0, p1)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutObjectResponse putObject(software.amazon.awssdk.services.s3.model.PutObjectRequest p0, software.amazon.awssdk.core.sync.RequestBody p1) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putObject(p0, p1)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutObjectAclResponse putObjectAcl(software.amazon.awssdk.services.s3.model.PutObjectAclRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putObjectAcl(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutObjectLegalHoldResponse putObjectLegalHold(software.amazon.awssdk.services.s3.model.PutObjectLegalHoldRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putObjectLegalHold(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutObjectLockConfigurationResponse putObjectLockConfiguration(software.amazon.awssdk.services.s3.model.PutObjectLockConfigurationRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putObjectLockConfiguration(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutObjectRetentionResponse putObjectRetention(software.amazon.awssdk.services.s3.model.PutObjectRetentionRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putObjectRetention(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutObjectTaggingResponse putObjectTagging(software.amazon.awssdk.services.s3.model.PutObjectTaggingRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putObjectTagging(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.PutPublicAccessBlockResponse putPublicAccessBlock(software.amazon.awssdk.services.s3.model.PutPublicAccessBlockRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putPublicAccessBlock(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.RestoreObjectResponse restoreObject(software.amazon.awssdk.services.s3.model.RestoreObjectRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.restoreObject(p0)); - } - - @Override - public software.amazon.awssdk.services.s3.model.UploadPartResponse uploadPart(software.amazon.awssdk.services.s3.model.UploadPartRequest p0, java.nio.file.Path p1) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.uploadPart(p0, p1)); - } - - @Override - public software.amazon.awssdk.services.s3.model.UploadPartResponse uploadPart(software.amazon.awssdk.services.s3.model.UploadPartRequest p0, software.amazon.awssdk.core.sync.RequestBody p1) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.uploadPart(p0, p1)); - } - - @Override - public software.amazon.awssdk.services.s3.model.UploadPartCopyResponse uploadPartCopy(software.amazon.awssdk.services.s3.model.UploadPartCopyRequest p0) throws AwsServiceException, SdkClientException { - return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.uploadPartCopy(p0)); - } + private static final Logger LOGGER = LoggerFactory.getLogger("io.awspring.cloud.s3.CrossRegionS3Client"); + + private static final int DEFAULT_BUCKET_CACHE_SIZE = 20; + + private final Map clientCache = new ConcurrentHashMap<>(Region.regions().size()); + + private final S3Client defaultS3Client; + + private final ConcurrentLruCache bucketCache; + + public CrossRegionS3Client(S3ClientBuilder clientBuilder) { + this(DEFAULT_BUCKET_CACHE_SIZE, clientBuilder); + } + + public CrossRegionS3Client(int bucketCacheSize, S3ClientBuilder clientBuilder) { + this.defaultS3Client = clientBuilder.build(); + this.bucketCache = new ConcurrentLruCache<>(bucketCacheSize, bucket -> { + Region region = resolveBucketRegion(bucket); + return clientCache.computeIfAbsent(region, r -> { + LOGGER.debug("Creating new S3 client for region: {}", r); + return clientBuilder.region(r).build(); + }); + }); + } + + @Override + public ListBucketsResponse listBuckets(ListBucketsRequest request) throws AwsServiceException, SdkClientException { + return defaultS3Client.listBuckets(request); + } + + @Override + public WriteGetObjectResponseResponse writeGetObjectResponse(WriteGetObjectResponseRequest request, + RequestBody requestBody) throws AwsServiceException, SdkClientException { + return defaultS3Client.writeGetObjectResponse(request, requestBody); + } + + // visible for testing + Map getClientCache() { + return clientCache; + } + + private Result executeInBucketRegion(String bucket, Function fn) { + try { + if (bucketCache.contains(bucket)) { + return fn.apply(bucketCache.get(bucket)); + } + else { + return fn.apply(defaultS3Client); + } + } + catch (S3Exception e) { + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Exception when requesting S3: {}", e.awsErrorDetails().errorCode(), e); + } + else { + LOGGER.debug("Exception when requesting S3 for bucket: {}: [{}] {}", bucket, + e.awsErrorDetails().errorCode(), e.awsErrorDetails().errorMessage()); + } + // "PermanentRedirect" means that the bucket is in different region than the + // defaultS3Client is configured for + if ("PermanentRedirect".equals(e.awsErrorDetails().errorCode())) { + return fn.apply(bucketCache.get(bucket)); + } + else { + throw e; + } + } + } + + private Region resolveBucketRegion(String bucket) { + LOGGER.debug("Resolving region for bucket {}", bucket); + String bucketLocation = defaultS3Client + .getBucketLocation(GetBucketLocationRequest.builder().bucket(bucket).build()) + .locationConstraintAsString(); + Region region = StringUtils.hasLength(bucketLocation) ? Region.of(bucketLocation) : Region.US_EAST_1; + LOGGER.debug("Region for bucket {} is {}", bucket, region); + return region; + } + + @Override + public String serviceName() { + return S3Client.SERVICE_NAME; + } + + @Override + public void close() { + this.clientCache.values().forEach(SdkAutoCloseable::close); + } + + @Override + public software.amazon.awssdk.services.s3.model.AbortMultipartUploadResponse abortMultipartUpload( + software.amazon.awssdk.services.s3.model.AbortMultipartUploadRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.abortMultipartUpload(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.CompleteMultipartUploadResponse completeMultipartUpload( + software.amazon.awssdk.services.s3.model.CompleteMultipartUploadRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.completeMultipartUpload(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.CopyObjectResponse copyObject( + software.amazon.awssdk.services.s3.model.CopyObjectRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.copyObject(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.CreateBucketResponse createBucket( + software.amazon.awssdk.services.s3.model.CreateBucketRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.createBucket(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.CreateMultipartUploadResponse createMultipartUpload( + software.amazon.awssdk.services.s3.model.CreateMultipartUploadRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.createMultipartUpload(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.DeleteBucketResponse deleteBucket( + software.amazon.awssdk.services.s3.model.DeleteBucketRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucket(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.DeleteBucketAnalyticsConfigurationResponse deleteBucketAnalyticsConfiguration( + software.amazon.awssdk.services.s3.model.DeleteBucketAnalyticsConfigurationRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketAnalyticsConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.DeleteBucketCorsResponse deleteBucketCors( + software.amazon.awssdk.services.s3.model.DeleteBucketCorsRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketCors(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.DeleteBucketEncryptionResponse deleteBucketEncryption( + software.amazon.awssdk.services.s3.model.DeleteBucketEncryptionRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketEncryption(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.DeleteBucketIntelligentTieringConfigurationResponse deleteBucketIntelligentTieringConfiguration( + software.amazon.awssdk.services.s3.model.DeleteBucketIntelligentTieringConfigurationRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketIntelligentTieringConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.DeleteBucketInventoryConfigurationResponse deleteBucketInventoryConfiguration( + software.amazon.awssdk.services.s3.model.DeleteBucketInventoryConfigurationRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketInventoryConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.DeleteBucketLifecycleResponse deleteBucketLifecycle( + software.amazon.awssdk.services.s3.model.DeleteBucketLifecycleRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketLifecycle(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.DeleteBucketMetricsConfigurationResponse deleteBucketMetricsConfiguration( + software.amazon.awssdk.services.s3.model.DeleteBucketMetricsConfigurationRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketMetricsConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.DeleteBucketOwnershipControlsResponse deleteBucketOwnershipControls( + software.amazon.awssdk.services.s3.model.DeleteBucketOwnershipControlsRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketOwnershipControls(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.DeleteBucketPolicyResponse deleteBucketPolicy( + software.amazon.awssdk.services.s3.model.DeleteBucketPolicyRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketPolicy(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.DeleteBucketReplicationResponse deleteBucketReplication( + software.amazon.awssdk.services.s3.model.DeleteBucketReplicationRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketReplication(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.DeleteBucketTaggingResponse deleteBucketTagging( + software.amazon.awssdk.services.s3.model.DeleteBucketTaggingRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketTagging(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.DeleteBucketWebsiteResponse deleteBucketWebsite( + software.amazon.awssdk.services.s3.model.DeleteBucketWebsiteRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteBucketWebsite(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.DeleteObjectResponse deleteObject( + software.amazon.awssdk.services.s3.model.DeleteObjectRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteObject(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.DeleteObjectTaggingResponse deleteObjectTagging( + software.amazon.awssdk.services.s3.model.DeleteObjectTaggingRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteObjectTagging(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.DeleteObjectsResponse deleteObjects( + software.amazon.awssdk.services.s3.model.DeleteObjectsRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deleteObjects(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.DeletePublicAccessBlockResponse deletePublicAccessBlock( + software.amazon.awssdk.services.s3.model.DeletePublicAccessBlockRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.deletePublicAccessBlock(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketAccelerateConfigurationResponse getBucketAccelerateConfiguration( + software.amazon.awssdk.services.s3.model.GetBucketAccelerateConfigurationRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketAccelerateConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketAclResponse getBucketAcl( + software.amazon.awssdk.services.s3.model.GetBucketAclRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketAcl(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketAnalyticsConfigurationResponse getBucketAnalyticsConfiguration( + software.amazon.awssdk.services.s3.model.GetBucketAnalyticsConfigurationRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketAnalyticsConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketCorsResponse getBucketCors( + software.amazon.awssdk.services.s3.model.GetBucketCorsRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketCors(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketEncryptionResponse getBucketEncryption( + software.amazon.awssdk.services.s3.model.GetBucketEncryptionRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketEncryption(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketIntelligentTieringConfigurationResponse getBucketIntelligentTieringConfiguration( + software.amazon.awssdk.services.s3.model.GetBucketIntelligentTieringConfigurationRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketIntelligentTieringConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketInventoryConfigurationResponse getBucketInventoryConfiguration( + software.amazon.awssdk.services.s3.model.GetBucketInventoryConfigurationRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketInventoryConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketLifecycleConfigurationResponse getBucketLifecycleConfiguration( + software.amazon.awssdk.services.s3.model.GetBucketLifecycleConfigurationRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketLifecycleConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketLocationResponse getBucketLocation( + software.amazon.awssdk.services.s3.model.GetBucketLocationRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketLocation(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketLoggingResponse getBucketLogging( + software.amazon.awssdk.services.s3.model.GetBucketLoggingRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketLogging(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketMetricsConfigurationResponse getBucketMetricsConfiguration( + software.amazon.awssdk.services.s3.model.GetBucketMetricsConfigurationRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketMetricsConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketNotificationConfigurationResponse getBucketNotificationConfiguration( + software.amazon.awssdk.services.s3.model.GetBucketNotificationConfigurationRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketNotificationConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketOwnershipControlsResponse getBucketOwnershipControls( + software.amazon.awssdk.services.s3.model.GetBucketOwnershipControlsRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketOwnershipControls(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketPolicyResponse getBucketPolicy( + software.amazon.awssdk.services.s3.model.GetBucketPolicyRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketPolicy(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketPolicyStatusResponse getBucketPolicyStatus( + software.amazon.awssdk.services.s3.model.GetBucketPolicyStatusRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketPolicyStatus(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketReplicationResponse getBucketReplication( + software.amazon.awssdk.services.s3.model.GetBucketReplicationRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketReplication(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketRequestPaymentResponse getBucketRequestPayment( + software.amazon.awssdk.services.s3.model.GetBucketRequestPaymentRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketRequestPayment(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketTaggingResponse getBucketTagging( + software.amazon.awssdk.services.s3.model.GetBucketTaggingRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketTagging(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketVersioningResponse getBucketVersioning( + software.amazon.awssdk.services.s3.model.GetBucketVersioningRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketVersioning(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetBucketWebsiteResponse getBucketWebsite( + software.amazon.awssdk.services.s3.model.GetBucketWebsiteRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getBucketWebsite(p0)); + } + + @Override + public software.amazon.awssdk.core.ResponseInputStream getObject( + software.amazon.awssdk.services.s3.model.GetObjectRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObject(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetObjectResponse getObject( + software.amazon.awssdk.services.s3.model.GetObjectRequest p0, java.nio.file.Path p1) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObject(p0, p1)); + } + + @Override + public ReturnT getObject(software.amazon.awssdk.services.s3.model.GetObjectRequest p0, + software.amazon.awssdk.core.sync.ResponseTransformer p1) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObject(p0, p1)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetObjectAclResponse getObjectAcl( + software.amazon.awssdk.services.s3.model.GetObjectAclRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectAcl(p0)); + } + + @Override + public software.amazon.awssdk.core.ResponseBytes getObjectAsBytes( + software.amazon.awssdk.services.s3.model.GetObjectRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectAsBytes(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetObjectAttributesResponse getObjectAttributes( + software.amazon.awssdk.services.s3.model.GetObjectAttributesRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectAttributes(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetObjectLegalHoldResponse getObjectLegalHold( + software.amazon.awssdk.services.s3.model.GetObjectLegalHoldRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectLegalHold(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetObjectLockConfigurationResponse getObjectLockConfiguration( + software.amazon.awssdk.services.s3.model.GetObjectLockConfigurationRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectLockConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetObjectRetentionResponse getObjectRetention( + software.amazon.awssdk.services.s3.model.GetObjectRetentionRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectRetention(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetObjectTaggingResponse getObjectTagging( + software.amazon.awssdk.services.s3.model.GetObjectTaggingRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectTagging(p0)); + } + + @Override + public software.amazon.awssdk.core.ResponseInputStream getObjectTorrent( + software.amazon.awssdk.services.s3.model.GetObjectTorrentRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectTorrent(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetObjectTorrentResponse getObjectTorrent( + software.amazon.awssdk.services.s3.model.GetObjectTorrentRequest p0, java.nio.file.Path p1) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectTorrent(p0, p1)); + } + + @Override + public ReturnT getObjectTorrent(software.amazon.awssdk.services.s3.model.GetObjectTorrentRequest p0, + software.amazon.awssdk.core.sync.ResponseTransformer p1) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectTorrent(p0, p1)); + } + + @Override + public software.amazon.awssdk.core.ResponseBytes getObjectTorrentAsBytes( + software.amazon.awssdk.services.s3.model.GetObjectTorrentRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getObjectTorrentAsBytes(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.GetPublicAccessBlockResponse getPublicAccessBlock( + software.amazon.awssdk.services.s3.model.GetPublicAccessBlockRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.getPublicAccessBlock(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.HeadBucketResponse headBucket( + software.amazon.awssdk.services.s3.model.HeadBucketRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.headBucket(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.HeadObjectResponse headObject( + software.amazon.awssdk.services.s3.model.HeadObjectRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.headObject(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.ListBucketAnalyticsConfigurationsResponse listBucketAnalyticsConfigurations( + software.amazon.awssdk.services.s3.model.ListBucketAnalyticsConfigurationsRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listBucketAnalyticsConfigurations(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.ListBucketIntelligentTieringConfigurationsResponse listBucketIntelligentTieringConfigurations( + software.amazon.awssdk.services.s3.model.ListBucketIntelligentTieringConfigurationsRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listBucketIntelligentTieringConfigurations(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.ListBucketInventoryConfigurationsResponse listBucketInventoryConfigurations( + software.amazon.awssdk.services.s3.model.ListBucketInventoryConfigurationsRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listBucketInventoryConfigurations(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.ListBucketMetricsConfigurationsResponse listBucketMetricsConfigurations( + software.amazon.awssdk.services.s3.model.ListBucketMetricsConfigurationsRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listBucketMetricsConfigurations(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.ListMultipartUploadsResponse listMultipartUploads( + software.amazon.awssdk.services.s3.model.ListMultipartUploadsRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listMultipartUploads(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.paginators.ListMultipartUploadsIterable listMultipartUploadsPaginator( + software.amazon.awssdk.services.s3.model.ListMultipartUploadsRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listMultipartUploadsPaginator(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.ListObjectVersionsResponse listObjectVersions( + software.amazon.awssdk.services.s3.model.ListObjectVersionsRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listObjectVersions(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.paginators.ListObjectVersionsIterable listObjectVersionsPaginator( + software.amazon.awssdk.services.s3.model.ListObjectVersionsRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listObjectVersionsPaginator(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.ListObjectsResponse listObjects( + software.amazon.awssdk.services.s3.model.ListObjectsRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listObjects(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.ListObjectsV2Response listObjectsV2( + software.amazon.awssdk.services.s3.model.ListObjectsV2Request p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listObjectsV2(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.paginators.ListObjectsV2Iterable listObjectsV2Paginator( + software.amazon.awssdk.services.s3.model.ListObjectsV2Request p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listObjectsV2Paginator(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.ListPartsResponse listParts( + software.amazon.awssdk.services.s3.model.ListPartsRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listParts(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.paginators.ListPartsIterable listPartsPaginator( + software.amazon.awssdk.services.s3.model.ListPartsRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.listPartsPaginator(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutBucketAccelerateConfigurationResponse putBucketAccelerateConfiguration( + software.amazon.awssdk.services.s3.model.PutBucketAccelerateConfigurationRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketAccelerateConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutBucketAclResponse putBucketAcl( + software.amazon.awssdk.services.s3.model.PutBucketAclRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketAcl(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutBucketAnalyticsConfigurationResponse putBucketAnalyticsConfiguration( + software.amazon.awssdk.services.s3.model.PutBucketAnalyticsConfigurationRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketAnalyticsConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutBucketCorsResponse putBucketCors( + software.amazon.awssdk.services.s3.model.PutBucketCorsRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketCors(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutBucketEncryptionResponse putBucketEncryption( + software.amazon.awssdk.services.s3.model.PutBucketEncryptionRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketEncryption(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutBucketIntelligentTieringConfigurationResponse putBucketIntelligentTieringConfiguration( + software.amazon.awssdk.services.s3.model.PutBucketIntelligentTieringConfigurationRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketIntelligentTieringConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutBucketInventoryConfigurationResponse putBucketInventoryConfiguration( + software.amazon.awssdk.services.s3.model.PutBucketInventoryConfigurationRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketInventoryConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutBucketLifecycleConfigurationResponse putBucketLifecycleConfiguration( + software.amazon.awssdk.services.s3.model.PutBucketLifecycleConfigurationRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketLifecycleConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutBucketLoggingResponse putBucketLogging( + software.amazon.awssdk.services.s3.model.PutBucketLoggingRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketLogging(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutBucketMetricsConfigurationResponse putBucketMetricsConfiguration( + software.amazon.awssdk.services.s3.model.PutBucketMetricsConfigurationRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketMetricsConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutBucketNotificationConfigurationResponse putBucketNotificationConfiguration( + software.amazon.awssdk.services.s3.model.PutBucketNotificationConfigurationRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketNotificationConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutBucketOwnershipControlsResponse putBucketOwnershipControls( + software.amazon.awssdk.services.s3.model.PutBucketOwnershipControlsRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketOwnershipControls(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutBucketPolicyResponse putBucketPolicy( + software.amazon.awssdk.services.s3.model.PutBucketPolicyRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketPolicy(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutBucketReplicationResponse putBucketReplication( + software.amazon.awssdk.services.s3.model.PutBucketReplicationRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketReplication(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutBucketRequestPaymentResponse putBucketRequestPayment( + software.amazon.awssdk.services.s3.model.PutBucketRequestPaymentRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketRequestPayment(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutBucketTaggingResponse putBucketTagging( + software.amazon.awssdk.services.s3.model.PutBucketTaggingRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketTagging(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutBucketVersioningResponse putBucketVersioning( + software.amazon.awssdk.services.s3.model.PutBucketVersioningRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketVersioning(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutBucketWebsiteResponse putBucketWebsite( + software.amazon.awssdk.services.s3.model.PutBucketWebsiteRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putBucketWebsite(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutObjectResponse putObject( + software.amazon.awssdk.services.s3.model.PutObjectRequest p0, java.nio.file.Path p1) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putObject(p0, p1)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutObjectResponse putObject( + software.amazon.awssdk.services.s3.model.PutObjectRequest p0, + software.amazon.awssdk.core.sync.RequestBody p1) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putObject(p0, p1)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutObjectAclResponse putObjectAcl( + software.amazon.awssdk.services.s3.model.PutObjectAclRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putObjectAcl(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutObjectLegalHoldResponse putObjectLegalHold( + software.amazon.awssdk.services.s3.model.PutObjectLegalHoldRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putObjectLegalHold(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutObjectLockConfigurationResponse putObjectLockConfiguration( + software.amazon.awssdk.services.s3.model.PutObjectLockConfigurationRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putObjectLockConfiguration(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutObjectRetentionResponse putObjectRetention( + software.amazon.awssdk.services.s3.model.PutObjectRetentionRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putObjectRetention(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutObjectTaggingResponse putObjectTagging( + software.amazon.awssdk.services.s3.model.PutObjectTaggingRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putObjectTagging(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.PutPublicAccessBlockResponse putPublicAccessBlock( + software.amazon.awssdk.services.s3.model.PutPublicAccessBlockRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.putPublicAccessBlock(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.RestoreObjectResponse restoreObject( + software.amazon.awssdk.services.s3.model.RestoreObjectRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.restoreObject(p0)); + } + + @Override + public software.amazon.awssdk.services.s3.model.UploadPartResponse uploadPart( + software.amazon.awssdk.services.s3.model.UploadPartRequest p0, java.nio.file.Path p1) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.uploadPart(p0, p1)); + } + + @Override + public software.amazon.awssdk.services.s3.model.UploadPartResponse uploadPart( + software.amazon.awssdk.services.s3.model.UploadPartRequest p0, + software.amazon.awssdk.core.sync.RequestBody p1) throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.uploadPart(p0, p1)); + } + + @Override + public software.amazon.awssdk.services.s3.model.UploadPartCopyResponse uploadPartCopy( + software.amazon.awssdk.services.s3.model.UploadPartCopyRequest p0) + throws AwsServiceException, SdkClientException { + return executeInBucketRegion(p0.bucket(), s3Client -> s3Client.uploadPartCopy(p0)); + } } - From 63884429711b689b0bb2de5a2eafc35ea939faa6 Mon Sep 17 00:00:00 2001 From: krimsz Date: Tue, 5 Jul 2022 09:53:08 +0200 Subject: [PATCH 08/10] Fix PR issues --- .../config/AbstractAwsConfigDataLocationResolver.java | 3 +-- .../autoconfigure/core/AwsClientBuilderConfigurer.java | 9 +++++---- .../core/CloudWatchMetricsPublisherProperties.java | 10 +++++----- .../cloud/autoconfigure/s3/S3AutoConfiguration.java | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/config/AbstractAwsConfigDataLocationResolver.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/config/AbstractAwsConfigDataLocationResolver.java index 7f7aebfd9..1a6d7f0ea 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/config/AbstractAwsConfigDataLocationResolver.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/config/AbstractAwsConfigDataLocationResolver.java @@ -157,8 +157,7 @@ else if (awsProperties.getEndpoint() != null) { MetricPublisher metricPublisher = getMetricPublisher(context); - if ((awsProperties.getMetrics() == null || awsProperties.getMetrics().getEnabled() == null - || (awsProperties.getMetrics().getEnabled() != null && awsProperties.getMetrics().getEnabled())) + if ((awsProperties.getMetrics() == null || awsProperties.getMetrics().getEnabled()) && metricPublisher != null) { ClientOverrideConfiguration.Builder clientOverrideConfigurationBuilder = new SpringCloudClientConfiguration() .clientOverrideConfiguration().toBuilder(); diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsClientBuilderConfigurer.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsClientBuilderConfigurer.java index 6311547ff..93f82b7d3 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsClientBuilderConfigurer.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsClientBuilderConfigurer.java @@ -42,6 +42,8 @@ * @since 3.0 */ public class AwsClientBuilderConfigurer { + public static final boolean IS_CLOUDWATCH_METRIC_PUBLISHER_PRESENT = ClassUtils + .isPresent("software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher", null); private final AwsCredentialsProvider credentialsProvider; private final AwsRegionProvider regionProvider; private final AwsProperties awsProperties; @@ -93,9 +95,8 @@ public Region resolveRegion(@Nullable AwsClientProperties clientProperties) { public static @Nullable MetricPublisher createSpecificMetricPublisher(MetricPublisher metricPublisher, AwsClientProperties properties, AwsClientBuilderConfigurer awsClientBuilderConfigurer) { - if (ClassUtils.isPresent("software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher", null) - && properties.getMetrics() != null) { - if (properties.getMetrics().getEnabled() == null || properties.getMetrics().getEnabled()) { + if (IS_CLOUDWATCH_METRIC_PUBLISHER_PRESENT && properties.getMetrics() != null) { + if (properties.getMetrics().getEnabled()) { PropertyMapper propertyMapper = PropertyMapper.get(); CloudWatchAsyncClientBuilder cloudWatchAsyncClientBuilder = CloudWatchAsyncClient.builder(); @@ -113,7 +114,7 @@ public Region resolveRegion(@Nullable AwsClientProperties clientProperties) { .to(v -> builder.uploadFrequency(Duration.ofSeconds(v))); return builder.build(); } - if (properties.getMetrics().getEnabled() != null && !properties.getMetrics().getEnabled()) { + else { return null; } diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/CloudWatchMetricsPublisherProperties.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/CloudWatchMetricsPublisherProperties.java index 828db06dd..9e48a4e1b 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/CloudWatchMetricsPublisherProperties.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/CloudWatchMetricsPublisherProperties.java @@ -19,18 +19,18 @@ public class CloudWatchMetricsPublisherProperties { @Nullable - Boolean enabled; + private boolean enabled; @Nullable - String namespace; + private String namespace; @Nullable - Long uploadFrequencyInSeconds; + private Long uploadFrequencyInSeconds; @Nullable - public Boolean getEnabled() { + public boolean getEnabled() { return enabled; } - public void setEnabled(@Nullable Boolean enabled) { + public void setEnabled(@Nullable boolean enabled) { this.enabled = enabled; } diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/S3AutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/S3AutoConfiguration.java index 1900cd33d..4f8c847c3 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/S3AutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/s3/S3AutoConfiguration.java @@ -62,7 +62,7 @@ @ConditionalOnProperty(name = "spring.cloud.aws.s3.enabled", havingValue = "true", matchIfMissing = true) public class S3AutoConfiguration { - private static S3Properties properties; + private final S3Properties properties; public S3AutoConfiguration(S3Properties properties) { this.properties = properties; From ce4af9f342a34e825f29cd7fe4d47204b83b87e0 Mon Sep 17 00:00:00 2001 From: krimsz Date: Mon, 11 Jul 2022 22:14:33 +0200 Subject: [PATCH 09/10] Fix origin of properties for mapper --- .../autoconfigure/core/AwsClientBuilderConfigurer.java | 5 ++--- .../core/CloudWatchMetricsPublisherAutoConfiguration.java | 6 ++++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsClientBuilderConfigurer.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsClientBuilderConfigurer.java index 93f82b7d3..e0f2c75a5 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsClientBuilderConfigurer.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/AwsClientBuilderConfigurer.java @@ -101,9 +101,8 @@ public Region resolveRegion(@Nullable AwsClientProperties clientProperties) { CloudWatchAsyncClientBuilder cloudWatchAsyncClientBuilder = CloudWatchAsyncClient.builder(); CloudWatchProperties cloudWatchProperties = new CloudWatchProperties(); - propertyMapper.from(cloudWatchProperties.getEndpoint()).whenNonNull() - .to(cloudWatchProperties::setEndpoint); - propertyMapper.from(cloudWatchProperties.getRegion()).whenNonNull().to(cloudWatchProperties::setRegion); + propertyMapper.from(properties.getEndpoint()).whenNonNull().to(cloudWatchProperties::setEndpoint); + propertyMapper.from(properties.getRegion()).whenNonNull().to(cloudWatchProperties::setRegion); CloudWatchAsyncClient cloudWatchAsyncClient = awsClientBuilderConfigurer .configure(cloudWatchAsyncClientBuilder, cloudWatchProperties, null, null).build(); diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/CloudWatchMetricsPublisherAutoConfiguration.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/CloudWatchMetricsPublisherAutoConfiguration.java index 1f4444f86..6729cec4b 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/CloudWatchMetricsPublisherAutoConfiguration.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/core/CloudWatchMetricsPublisherAutoConfiguration.java @@ -28,6 +28,7 @@ import org.springframework.context.annotation.Configuration; import software.amazon.awssdk.metrics.MetricPublisher; import software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher; +import software.amazon.awssdk.regions.providers.AwsRegionProvider; import software.amazon.awssdk.services.cloudwatch.CloudWatchAsyncClient; import software.amazon.awssdk.services.cloudwatch.CloudWatchAsyncClientBuilder; @@ -47,13 +48,14 @@ public CloudWatchMetricsPublisherAutoConfiguration(AwsProperties awsProperties) @ConditionalOnMissingBean @ConditionalOnProperty(name = "spring.cloud.aws.metrics.enabled", havingValue = "true", matchIfMissing = true) MetricPublisher cloudWatchMetricPublisher(AwsClientBuilderConfigurer awsClientBuilderConfigurer, + AwsRegionProvider awsRegionProvider, ObjectProvider> configurer) { PropertyMapper propertyMapper = PropertyMapper.get(); CloudWatchAsyncClientBuilder cloudWatchAsyncClientBuilder = CloudWatchAsyncClient.builder(); CloudWatchProperties cloudWatchProperties = new CloudWatchProperties(); - propertyMapper.from(cloudWatchProperties.getEndpoint()).whenNonNull().to(cloudWatchProperties::setEndpoint); - propertyMapper.from(cloudWatchProperties.getRegion()).whenNonNull().to(cloudWatchProperties::setRegion); + propertyMapper.from(awsProperties.getEndpoint()).whenNonNull().to(cloudWatchProperties::setEndpoint); + propertyMapper.from(awsRegionProvider.getRegion().id()).whenNonNull().to(cloudWatchProperties::setRegion); CloudWatchAsyncClient cloudWatchAsyncClient = awsClientBuilderConfigurer .configure(cloudWatchAsyncClientBuilder, cloudWatchProperties, configurer.getIfAvailable(), null) .build(); From ede466aa2cfeb8e3961f4727a3067a4940824a6c Mon Sep 17 00:00:00 2001 From: krimsz Date: Mon, 11 Jul 2022 22:14:57 +0200 Subject: [PATCH 10/10] WIP possible way of moving forward for parameterstore and secretsmanager --- ...AbstractAwsConfigDataLocationResolver.java | 65 ++++++++++++------- ...ameterStoreConfigDataLocationResolver.java | 11 ++-- ...retsManagerConfigDataLocationResolver.java | 1 - ...StoreConfigDataLoaderIntegrationTests.java | 34 ++++++++++ 4 files changed, 84 insertions(+), 27 deletions(-) diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/config/AbstractAwsConfigDataLocationResolver.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/config/AbstractAwsConfigDataLocationResolver.java index 1a6d7f0ea..0c000c9a4 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/config/AbstractAwsConfigDataLocationResolver.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/config/AbstractAwsConfigDataLocationResolver.java @@ -22,7 +22,8 @@ import io.awspring.cloud.autoconfigure.core.RegionProperties; import io.awspring.cloud.autoconfigure.core.RegionProviderAutoConfiguration; import io.awspring.cloud.core.SpringCloudClientConfiguration; -import io.micrometer.core.lang.Nullable; +import java.net.URI; +import java.time.Duration; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -35,16 +36,19 @@ import org.springframework.boot.context.config.ConfigDataLocationResolverContext; import org.springframework.boot.context.config.ConfigDataResource; import org.springframework.boot.context.config.ConfigDataResourceNotFoundException; +import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.boot.context.properties.bind.Bindable; import org.springframework.boot.context.properties.bind.Binder; import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; import software.amazon.awssdk.awscore.client.builder.AwsClientBuilder; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; -import software.amazon.awssdk.metrics.MetricPublisher; +import software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.regions.providers.AwsRegionProvider; +import software.amazon.awssdk.services.cloudwatch.CloudWatchAsyncClient; /** * Base class for AWS specific {@link ConfigDataLocationResolver}s. @@ -58,6 +62,10 @@ public abstract class AbstractAwsConfigDataLocationResolver> CloudWatchMetricPublisher createMetricPublisher( + AwsProperties awsProperties, AwsClientProperties awsClientProperties, AwsRegionProvider regionProvider, + T clientBuilder, AwsCredentialsProvider credentialsProvider) { + CloudWatchMetricPublisher.Builder builder = CloudWatchMetricPublisher.builder(); + PropertyMapper map = PropertyMapper.get(); + if ((awsClientProperties.getMetrics() != null && awsClientProperties.getMetrics().getEnabled())) { + CloudWatchAsyncClient cloudwatchAsyncClient = createCloudwatchAsyncClient(awsClientProperties.getRegion(), + awsClientProperties.getEndpoint(), credentialsProvider); + + map.from(awsClientProperties.getMetrics()::getNamespace).whenNonNull().to(builder::namespace); + map.from(awsClientProperties.getMetrics()::getUploadFrequencyInSeconds).whenNonNull() + .to(v -> builder.uploadFrequency(Duration.ofSeconds(v))); + builder.cloudWatchClient(cloudwatchAsyncClient); } - catch (IllegalStateException | ClassNotFoundException e) { - return null; + else if (awsProperties.getMetrics() == null + || (awsProperties.getMetrics() != null && awsProperties.getMetrics().getEnabled())) { + CloudWatchAsyncClient cloudwatchAsyncClient = createCloudwatchAsyncClient(regionProvider.getRegion().id(), + awsProperties.getEndpoint(), credentialsProvider); + if (awsProperties.getMetrics() != null) { + map.from(awsProperties.getMetrics()::getNamespace).whenNonNull().to(builder::namespace); + map.from(awsProperties.getMetrics()::getUploadFrequencyInSeconds).whenNonNull() + .to(v -> builder.uploadFrequency(Duration.ofSeconds(v))); + } + builder.cloudWatchClient(cloudwatchAsyncClient); } + return builder.build(); } - protected void createMetricPublisher(ConfigDataLocationResolverContext resolverContext) { - try { - Class.forName("software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher"); - } - catch (IllegalStateException | ClassNotFoundException ignored) { - // ignored, means that the optional dependency is not in the classpath - return; - } - + private > CloudWatchAsyncClient createCloudwatchAsyncClient(String region, + URI endpoint, AwsCredentialsProvider credentialsProvider) { + return CloudWatchAsyncClient.builder().region(Region.of(region)).endpointOverride(endpoint) + .credentialsProvider(credentialsProvider).build(); } - } diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/config/parameterstore/ParameterStoreConfigDataLocationResolver.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/config/parameterstore/ParameterStoreConfigDataLocationResolver.java index 5548b5b46..311c7872c 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/config/parameterstore/ParameterStoreConfigDataLocationResolver.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/config/parameterstore/ParameterStoreConfigDataLocationResolver.java @@ -60,12 +60,15 @@ protected String getPrefix() { public List resolveProfileSpecific( ConfigDataLocationResolverContext resolverContext, ConfigDataLocation location, Profiles profiles) throws ConfigDataLocationNotFoundException { - registerBean(resolverContext, AwsProperties.class, loadAwsProperties(resolverContext.getBinder())); - registerBean(resolverContext, ParameterStoreProperties.class, loadProperties(resolverContext.getBinder())); + AwsProperties awsProperties = loadAwsProperties(resolverContext.getBinder()); + ParameterStoreProperties parameterStoreProperties = loadProperties(resolverContext.getBinder()); + RegionProperties regionProperties = loadRegionProperties(resolverContext.getBinder()); + + registerBean(resolverContext, AwsProperties.class, awsProperties); + registerBean(resolverContext, ParameterStoreProperties.class, parameterStoreProperties); registerBean(resolverContext, CredentialsProperties.class, loadCredentialsProperties(resolverContext.getBinder())); - registerBean(resolverContext, RegionProperties.class, loadRegionProperties(resolverContext.getBinder())); - createMetricPublisher(resolverContext); + registerBean(resolverContext, RegionProperties.class, regionProperties); registerAndPromoteBean(resolverContext, SsmClient.class, this::createSimpleSystemManagementClient); ParameterStorePropertySources sources = new ParameterStorePropertySources(); diff --git a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/config/secretsmanager/SecretsManagerConfigDataLocationResolver.java b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/config/secretsmanager/SecretsManagerConfigDataLocationResolver.java index 32c779ec4..76fe08a00 100644 --- a/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/config/secretsmanager/SecretsManagerConfigDataLocationResolver.java +++ b/spring-cloud-aws-autoconfigure/src/main/java/io/awspring/cloud/autoconfigure/config/secretsmanager/SecretsManagerConfigDataLocationResolver.java @@ -69,7 +69,6 @@ public List resolveProfileSpecific( registerBean(resolverContext, CredentialsProperties.class, loadCredentialsProperties(resolverContext.getBinder())); registerBean(resolverContext, RegionProperties.class, loadRegionProperties(resolverContext.getBinder())); - createMetricPublisher(resolverContext); registerAndPromoteBean(resolverContext, SecretsManagerClient.class, this::createAwsSecretsManagerClient); SecretsManagerPropertySources propertySources = new SecretsManagerPropertySources(); diff --git a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/config/parameterstore/ParameterStoreConfigDataLoaderIntegrationTests.java b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/config/parameterstore/ParameterStoreConfigDataLoaderIntegrationTests.java index 16c0e79b4..d2a7bb56a 100644 --- a/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/config/parameterstore/ParameterStoreConfigDataLoaderIntegrationTests.java +++ b/spring-cloud-aws-autoconfigure/src/test/java/io/awspring/cloud/autoconfigure/config/parameterstore/ParameterStoreConfigDataLoaderIntegrationTests.java @@ -37,6 +37,7 @@ import org.springframework.boot.test.system.CapturedOutput; import org.springframework.boot.test.system.OutputCaptureExtension; import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.test.util.ReflectionTestUtils; import org.testcontainers.containers.localstack.LocalStackContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; @@ -46,6 +47,8 @@ import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.http.SdkHttpClient; import software.amazon.awssdk.http.apache.ApacheHttpClient; +import software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher; +import software.amazon.awssdk.metrics.publishers.cloudwatch.internal.transform.MetricCollectionAggregator; import software.amazon.awssdk.services.ssm.SsmClient; import software.amazon.awssdk.services.ssm.model.GetParametersByPathRequest; import software.amazon.awssdk.services.ssm.model.GetParametersByPathResponse; @@ -210,6 +213,37 @@ void parameterStoreClientUsesGlobalRegion() { } } + @Test + void clientIsConfiguredWithConfigurerProvidedToBootstrapRegistry2() { + SpringApplication application = new SpringApplication(App.class); + application.setWebApplicationType(WebApplicationType.NONE); + application.addBootstrapRegistryInitializer(new AwsConfigurerClientConfiguration()); + + try (ConfigurableApplicationContext context = application.run( + "--spring.cloud.aws.parameterstore.metrics.namespace=custom", + "--spring.config.import=aws-parameterstore:/config/spring/", + "--spring.cloud.aws.parameterstore.region=" + REGION, + "--spring.cloud.aws.endpoint=http://non-existing-host/", + "--spring.cloud.aws.parameterstore.endpoint=" + localstack.getEndpointOverride(SSM).toString(), + "--spring.cloud.aws.credentials.access-key=noop", "--spring.cloud.aws.credentials.secret-key=noop", + "--spring.cloud.aws.region.static=eu-west-1", + "--logging.level.io.awspring.cloud.parameterstore=debug")) { + + CloudWatchMetricPublisher metricPublisher = (CloudWatchMetricPublisher) context.getBean(SsmClient.class) + .overrideConfiguration().metricPublishers().get(0); + MetricCollectionAggregator metricAggregator = (MetricCollectionAggregator) ReflectionTestUtils + .getField(metricPublisher, "metricAggregator"); + + String namespace = (String) ReflectionTestUtils.getField(metricAggregator, "namespace"); + assertThat(namespace).isEqualTo("custom"); + } + } + + @Test + void parameterStoreUsesCustomEndpointForMetricsIfDefined() { + + } + private ConfigurableApplicationContext runApplication(SpringApplication application, String springConfigImport, String endpointProperty) { return application.run("--spring.config.import=" + springConfigImport,