Unverified Commit df62f5c6 authored by ysaito1001's avatar ysaito1001 Committed by GitHub
Browse files

Make service config builder contain `CloneableLayer` (#2795)



## Motivation and Context
This PR will reduce fields in service config builders to contain only
`CloneableLayer` (except for `interceptors` and `identity_resolvers`).

## Description
This is the third PR in a series of config refactoring in the
orchestrator mode. Just like #2762, this PR reduces fields in service
config builders to contain `CloneableLayer`.

The code changes follow a straightforward pattern where builders'
setters are implemented via a config layer.

## Testing
Relies on the existing tests in CI

----

_By submitting this pull request, I confirm that you can use, modify,
copy, and redistribute this contribution, under the terms of your
choice._

---------

Co-authored-by: default avatarYuki Saito <awsaito@amazon.com>
Co-authored-by: default avatarZelda Hessler <zhessler@amazon.com>
parent 47718f9d
Loading
Loading
Loading
Loading
+17 −5
Original line number Diff line number Diff line
@@ -103,13 +103,25 @@ class AwsFluentClientDecorator : ClientCodegenDecorator {
        baseGenerator.protocolSupport,
        baseGenerator.operationShape,
        renderClientCreation = { params ->
            rustTemplate(
            rust("let mut ${params.configBuilderName} = ${params.configBuilderName};")
            if (codegenContext.smithyRuntimeMode.defaultToOrchestrator) {
                // TODO(enableNewSmithyRuntimeLaunch): A builder field could not be accessed directly in the orchestrator
                //  mode when this code change was made. smithy-rs#2792 will enable us to use getters in builders.
                //  Make this `set_region` conditional by checking if `config_builder.region().is_none()` once the PR
                //  has been merged to main.
                rust("""${params.configBuilderName}.set_region(Some(crate::config::Region::new("us-east-1")));""")
            } else {
                rust(
                    """
                    // If the test case was missing endpoint parameters, default a region so it doesn't fail
                let mut ${params.configBuilderName} = ${params.configBuilderName};
                    if ${params.configBuilderName}.region.is_none() {
                        ${params.configBuilderName}.set_region(Some(crate::config::Region::new("us-east-1")));
                    }
                    """,
                )
            }
            rustTemplate(
                """
                let config = ${params.configBuilderName}.http_connector(${params.connectorName}).build();
                let ${params.clientName} = #{Client}::from_conf(config);
                """,
+38 −12
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@ import software.amazon.smithy.rust.codegen.core.rustlang.rust
import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate
import software.amazon.smithy.rust.codegen.core.rustlang.writable
import software.amazon.smithy.rust.codegen.core.smithy.RuntimeConfig
import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType
import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.preludeScope
import software.amazon.smithy.rust.codegen.core.smithy.customize.AdHocCustomization
import software.amazon.smithy.rust.codegen.core.smithy.customize.adhocCustomization

@@ -53,8 +55,10 @@ class CredentialCacheConfig(codegenContext: ClientCodegenContext) : ConfigCustom
    private val runtimeConfig = codegenContext.runtimeConfig
    private val runtimeMode = codegenContext.smithyRuntimeMode
    private val codegenScope = arrayOf(
        *preludeScope,
        "CredentialsCache" to AwsRuntimeType.awsCredentialTypes(runtimeConfig).resolve("cache::CredentialsCache"),
        "DefaultProvider" to defaultProvider(),
        "SharedAsyncSleep" to RuntimeType.smithyAsync(runtimeConfig).resolve("rt::sleep::SharedAsyncSleep"),
        "SharedCredentialsCache" to AwsRuntimeType.awsCredentialTypes(runtimeConfig).resolve("cache::SharedCredentialsCache"),
        "SharedCredentialsProvider" to AwsRuntimeType.awsCredentialTypes(runtimeConfig).resolve("provider::SharedCredentialsProvider"),
    )
@@ -95,17 +99,37 @@ class CredentialCacheConfig(codegenContext: ClientCodegenContext) : ConfigCustom
            }

            ServiceConfig.BuilderStruct ->
                rustTemplate("credentials_cache: Option<#{CredentialsCache}>,", *codegenScope)
                if (runtimeMode.defaultToMiddleware) {
                    rustTemplate("credentials_cache: #{Option}<#{CredentialsCache}>,", *codegenScope)
                }

            ServiceConfig.BuilderImpl -> {
                rustTemplate(
                    """
                    /// Sets the credentials cache for this service
                    pub fn credentials_cache(mut self, credentials_cache: #{CredentialsCache}) -> Self {
                        self.set_credentials_cache(Some(credentials_cache));
                        self.set_credentials_cache(#{Some}(credentials_cache));
                        self
                    }

                    """,
                    *codegenScope,
                )

                if (runtimeMode.defaultToOrchestrator) {
                    rustTemplate(
                        """
                        /// Sets the credentials cache for this service
                        pub fn set_credentials_cache(&mut self, credentials_cache: #{Option}<#{CredentialsCache}>) -> &mut Self {
                            self.inner.store_or_unset(credentials_cache);
                            self
                        }
                        """,
                        *codegenScope,
                    )
                } else {
                    rustTemplate(
                        """
                        /// Sets the credentials cache for this service
                        pub fn set_credentials_cache(&mut self, credentials_cache: Option<#{CredentialsCache}>) -> &mut Self {
                            self.credentials_cache = credentials_cache;
@@ -115,15 +139,17 @@ class CredentialCacheConfig(codegenContext: ClientCodegenContext) : ConfigCustom
                        *codegenScope,
                    )
                }
            }

            ServiceConfig.BuilderBuild -> {
                if (runtimeMode.defaultToOrchestrator) {
                    rustTemplate(
                        """
                        layer.store_put(
                            self.credentials_cache
                        self.inner.store_put(
                            self.inner.load::<#{CredentialsCache}>()
                                .cloned()
                                .unwrap_or_else({
                                    let sleep = self.sleep_impl.clone();
                                    let sleep = self.inner.load::<#{SharedAsyncSleep}>().cloned();
                                    || match sleep {
                                        Some(sleep) => {
                                            #{CredentialsCache}::lazy_builder()
@@ -133,9 +159,9 @@ class CredentialCacheConfig(codegenContext: ClientCodegenContext) : ConfigCustom
                                        None => #{CredentialsCache}::lazy(),
                                    }
                                })
                                .create_cache(self.credentials_provider.unwrap_or_else(|| {
                                .create_cache(self.inner.load::<#{SharedCredentialsProvider}>().cloned().unwrap_or_else(|| {
                                    #{SharedCredentialsProvider}::new(#{DefaultProvider})
                                })),
                                }))
                        );
                        """,
                        *codegenScope,
+40 −15
Original line number Diff line number Diff line
@@ -17,8 +17,8 @@ import software.amazon.smithy.rust.codegen.core.rustlang.Writable
import software.amazon.smithy.rust.codegen.core.rustlang.rust
import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate
import software.amazon.smithy.rust.codegen.core.rustlang.writable
import software.amazon.smithy.rust.codegen.core.smithy.RuntimeConfig
import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType
import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.preludeScope
import software.amazon.smithy.rust.codegen.core.smithy.RustCrate
import software.amazon.smithy.rust.codegen.core.smithy.customize.AdHocCustomization
import software.amazon.smithy.rust.codegen.core.smithy.customize.adhocCustomization
@@ -40,7 +40,7 @@ class CredentialsProviderDecorator : ClientCodegenDecorator {
        codegenContext: ClientCodegenContext,
        baseCustomizations: List<ConfigCustomization>,
    ): List<ConfigCustomization> {
        return baseCustomizations + CredentialProviderConfig(codegenContext.runtimeConfig)
        return baseCustomizations + CredentialProviderConfig(codegenContext)
    }

    override fun extraSections(codegenContext: ClientCodegenContext): List<AdHocCustomization> =
@@ -65,28 +65,52 @@ class CredentialsProviderDecorator : ClientCodegenDecorator {
/**
 * Add a `.credentials_provider` field and builder to the `Config` for a given service
 */
class CredentialProviderConfig(runtimeConfig: RuntimeConfig) : ConfigCustomization() {
class CredentialProviderConfig(codegenContext: ClientCodegenContext) : ConfigCustomization() {
    private val smithyRuntimeMode = codegenContext.smithyRuntimeMode
    private val runtimeConfig = codegenContext.runtimeConfig
    private val codegenScope = arrayOf(
        "provider" to AwsRuntimeType.awsCredentialTypes(runtimeConfig).resolve("provider"),
        *preludeScope,
        "Credentials" to AwsRuntimeType.awsCredentialTypes(runtimeConfig).resolve("Credentials"),
        "ProvideCredentials" to AwsRuntimeType.awsCredentialTypes(runtimeConfig).resolve("provider::ProvideCredentials"),
        "SharedCredentialsProvider" to AwsRuntimeType.awsCredentialTypes(runtimeConfig).resolve("provider::SharedCredentialsProvider"),
        "TestCredentials" to AwsRuntimeType.awsCredentialTypesTestUtil(runtimeConfig).resolve("Credentials"),
    )

    override fun section(section: ServiceConfig) = writable {
        when (section) {
            ServiceConfig.BuilderStruct ->
                rustTemplate("credentials_provider: Option<#{provider}::SharedCredentialsProvider>,", *codegenScope)
            ServiceConfig.BuilderStruct -> {
                if (smithyRuntimeMode.defaultToMiddleware) {
                    rustTemplate("credentials_provider: #{Option}<#{SharedCredentialsProvider}>,", *codegenScope)
                }
            }
            ServiceConfig.BuilderImpl -> {
                rustTemplate(
                    """
                    /// Sets the credentials provider for this service
                    pub fn credentials_provider(mut self, credentials_provider: impl #{provider}::ProvideCredentials + 'static) -> Self {
                        self.set_credentials_provider(Some(#{provider}::SharedCredentialsProvider::new(credentials_provider)));
                    pub fn credentials_provider(mut self, credentials_provider: impl #{ProvideCredentials} + 'static) -> Self {
                        self.set_credentials_provider(#{Some}(#{SharedCredentialsProvider}::new(credentials_provider)));
                        self
                    }
                    """,
                    *codegenScope,
                )

                if (smithyRuntimeMode.defaultToOrchestrator) {
                    rustTemplate(
                        """
                        /// Sets the credentials provider for this service
                    pub fn set_credentials_provider(&mut self, credentials_provider: Option<#{provider}::SharedCredentialsProvider>) -> &mut Self {
                        pub fn set_credentials_provider(&mut self, credentials_provider: #{Option}<#{SharedCredentialsProvider}>) -> &mut Self {
                            self.inner.store_or_unset(credentials_provider);
                            self
                        }
                        """,
                        *codegenScope,
                    )
                } else {
                    rustTemplate(
                        """
                        /// Sets the credentials provider for this service
                        pub fn set_credentials_provider(&mut self, credentials_provider: #{Option}<#{SharedCredentialsProvider}>) -> &mut Self {
                            self.credentials_provider = credentials_provider;
                            self
                        }
@@ -94,9 +118,10 @@ class CredentialProviderConfig(runtimeConfig: RuntimeConfig) : ConfigCustomizati
                        *codegenScope,
                    )
                }
            }

            is ServiceConfig.DefaultForTests -> rustTemplate(
                "${section.configBuilderRef}.set_credentials_provider(Some(#{provider}::SharedCredentialsProvider::new(#{TestCredentials}::for_tests())));",
                "${section.configBuilderRef}.set_credentials_provider(Some(#{SharedCredentialsProvider}::new(#{TestCredentials}::for_tests())));",
                *codegenScope,
            )

+28 −9
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.rust
import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate
import software.amazon.smithy.rust.codegen.core.rustlang.writable
import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType
import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.preludeScope
import software.amazon.smithy.rust.codegen.core.util.letIf

// TODO(enableNewSmithyRuntimeCleanup): Delete this decorator since it's now in `codegen-client`
@@ -37,6 +38,7 @@ class HttpConnectorConfigCustomization(
    private val runtimeMode = codegenContext.smithyRuntimeMode
    private val moduleUseName = codegenContext.moduleUseName()
    private val codegenScope = arrayOf(
        *preludeScope,
        "HttpConnector" to RuntimeType.smithyClient(runtimeConfig).resolve("http_connector::HttpConnector"),
    )

@@ -71,8 +73,10 @@ class HttpConnectorConfigCustomization(
                }
            }
            is ServiceConfig.BuilderStruct -> writable {
                if (runtimeMode.defaultToMiddleware) {
                    rustTemplate("http_connector: Option<#{HttpConnector}>,", *codegenScope)
                }
            }
            ServiceConfig.BuilderImpl -> writable {
                rustTemplate(
                    """
@@ -108,7 +112,7 @@ class HttpConnectorConfigCustomization(
                    /// ## }
                    /// ```
                    pub fn http_connector(mut self, http_connector: impl Into<#{HttpConnector}>) -> Self {
                        self.http_connector = Some(http_connector.into());
                        self.set_http_connector(#{Some}(http_connector));
                        self
                    }

@@ -150,7 +154,23 @@ class HttpConnectorConfigCustomization(
                    /// ## }
                    /// ## }
                    /// ```
                    pub fn set_http_connector(&mut self, http_connector: Option<impl Into<#{HttpConnector}>>) -> &mut Self {
                    """,
                    *codegenScope,
                )
                if (runtimeMode.defaultToOrchestrator) {
                    rustTemplate(
                        """
                        pub fn set_http_connector(&mut self, http_connector: #{Option}<impl #{Into}<#{HttpConnector}>>) -> &mut Self {
                            http_connector.map(|c| self.inner.store_put(c.into()));
                            self
                        }
                        """,
                        *codegenScope,
                    )
                } else {
                    rustTemplate(
                        """
                        pub fn set_http_connector(&mut self, http_connector: #{Option}<impl #{Into}<#{HttpConnector}>>) -> &mut Self {
                            self.http_connector = http_connector.map(|inner| inner.into());
                            self
                        }
@@ -158,10 +178,9 @@ class HttpConnectorConfigCustomization(
                        *codegenScope,
                    )
                }
            }
            is ServiceConfig.BuilderBuild -> writable {
                if (runtimeMode.defaultToOrchestrator) {
                    rust("layer.store_or_unset(self.http_connector);")
                } else {
                if (runtimeMode.defaultToMiddleware) {
                    rust("http_connector: self.http_connector,")
                }
            }
+41 −17
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.rust
import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate
import software.amazon.smithy.rust.codegen.core.rustlang.writable
import software.amazon.smithy.rust.codegen.core.smithy.RuntimeConfig
import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.preludeScope
import software.amazon.smithy.rust.codegen.core.smithy.RustCrate
import software.amazon.smithy.rust.codegen.core.smithy.customize.AdHocCustomization
import software.amazon.smithy.rust.codegen.core.smithy.customize.adhocCustomization
@@ -160,12 +161,15 @@ class RegionProviderConfig(codegenContext: ClientCodegenContext) : ConfigCustomi
    private val region = region(codegenContext.runtimeConfig)
    private val moduleUseName = codegenContext.moduleUseName()
    private val runtimeMode = codegenContext.smithyRuntimeMode
    private val codegenScope = arrayOf("Region" to region.resolve("Region"))
    private val codegenScope = arrayOf(
        *preludeScope,
        "Region" to region.resolve("Region"),
    )
    override fun section(section: ServiceConfig) = writable {
        when (section) {
            ServiceConfig.ConfigStruct -> {
                if (runtimeMode.defaultToMiddleware) {
                    rustTemplate("pub(crate) region: Option<#{Region}>,", *codegenScope)
                    rustTemplate("pub(crate) region: #{Option}<#{Region}>,", *codegenScope)
                }
            }
            ServiceConfig.ConfigImpl -> {
@@ -173,7 +177,7 @@ class RegionProviderConfig(codegenContext: ClientCodegenContext) : ConfigCustomi
                    rustTemplate(
                        """
                        /// Returns the AWS region, if it was provided.
                        pub fn region(&self) -> Option<&#{Region}> {
                        pub fn region(&self) -> #{Option}<&#{Region}> {
                            self.inner.load::<#{Region}>()
                        }
                        """,
@@ -183,7 +187,7 @@ class RegionProviderConfig(codegenContext: ClientCodegenContext) : ConfigCustomi
                    rustTemplate(
                        """
                        /// Returns the AWS region, if it was provided.
                        pub fn region(&self) -> Option<&#{Region}> {
                        pub fn region(&self) -> #{Option}<&#{Region}> {
                            self.region.as_ref()
                        }
                        """,
@@ -192,10 +196,13 @@ class RegionProviderConfig(codegenContext: ClientCodegenContext) : ConfigCustomi
                }
            }

            ServiceConfig.BuilderStruct ->
                rustTemplate("pub(crate) region: Option<#{Region}>,", *codegenScope)
            ServiceConfig.BuilderStruct -> {
                if (runtimeMode.defaultToMiddleware) {
                    rustTemplate("pub(crate) region: #{Option}<#{Region}>,", *codegenScope)
                }
            }

            ServiceConfig.BuilderImpl ->
            ServiceConfig.BuilderImpl -> {
                rustTemplate(
                    """
                    /// Sets the AWS region to use when making requests.
@@ -209,24 +216,41 @@ class RegionProviderConfig(codegenContext: ClientCodegenContext) : ConfigCustomi
                    ///     .region(Region::new("us-east-1"))
                    ///     .build();
                    /// ```
                    pub fn region(mut self, region: impl Into<Option<#{Region}>>) -> Self {
                        self.region = region.into();
                    pub fn region(mut self, region: impl #{Into}<#{Option}<#{Region}>>) -> Self {
                        self.set_region(region.into());
                        self
                    }
                    """,
                    *codegenScope,
                )

                if (runtimeMode.defaultToOrchestrator) {
                    rustTemplate(
                        """
                        /// Sets the AWS region to use when making requests.
                    pub fn set_region(&mut self, region: Option<#{Region}>) -> &mut Self {
                        pub fn set_region(&mut self, region: #{Option}<#{Region}>) -> &mut Self {
                            self.inner.store_or_unset(region);
                            self
                        }
                        """,
                        *codegenScope,
                    )
                } else {
                    rustTemplate(
                        """
                        /// Sets the AWS region to use when making requests.
                        pub fn set_region(&mut self, region: #{Option}<#{Region}>) -> &mut Self {
                            self.region = region;
                            self
                        }
                        """,
                        *codegenScope,
                    )
                }
            }

            ServiceConfig.BuilderBuild -> {
                if (runtimeMode.defaultToOrchestrator) {
                    rust("layer.store_or_unset(self.region);")
                } else {
                if (runtimeMode.defaultToMiddleware) {
                    rust("region: self.region,")
                }
            }
Loading