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

Remove HACK that used to put `Handle` in config bag (#2806)



## Motivation and Context
Removes `HACK` that used to put `Handle` in config bag.

## Description
The `HACK` was previously placed in `ServiceRuntimePlugin::config`
because later in the orchestrator execution, we needed to access service
config fields (through `Handle`) to build endpoint `Params` within
`EndpointParamsInterceptor`. Now that service config fields are baked
into a frozen layer, `EndpointParamsInterceptor` can load those fields
directly from the config bag (to which the frozen layer has been added)
when constructing endpoint `Params`. We can therefore remove `HACK` at
this point.

## Testing
- [x] Passed 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>
parent 177965cd
Loading
Loading
Loading
Loading
+23 −15
Original line number Diff line number Diff line
@@ -20,18 +20,23 @@ import software.amazon.smithy.rust.codegen.client.smithy.customize.ClientCodegen
import software.amazon.smithy.rust.codegen.client.smithy.endpoint.EndpointCustomization
import software.amazon.smithy.rust.codegen.client.smithy.endpoint.EndpointRulesetIndex
import software.amazon.smithy.rust.codegen.client.smithy.endpoint.rustName
import software.amazon.smithy.rust.codegen.client.smithy.endpoint.symbol
import software.amazon.smithy.rust.codegen.client.smithy.generators.config.ConfigCustomization
import software.amazon.smithy.rust.codegen.client.smithy.generators.config.ConfigParam
import software.amazon.smithy.rust.codegen.client.smithy.generators.config.configParamNewtype
import software.amazon.smithy.rust.codegen.client.smithy.generators.config.loadFromConfigBag
import software.amazon.smithy.rust.codegen.client.smithy.generators.config.standardConfigParam
import software.amazon.smithy.rust.codegen.core.rustlang.RustType
import software.amazon.smithy.rust.codegen.core.rustlang.Writable
import software.amazon.smithy.rust.codegen.core.rustlang.docs
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.stripOuter
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.customize.AdHocCustomization
import software.amazon.smithy.rust.codegen.core.smithy.mapRustType
import software.amazon.smithy.rust.codegen.core.util.PANIC
import software.amazon.smithy.rust.codegen.core.util.dq
import software.amazon.smithy.rust.codegen.core.util.extendIf
@@ -54,22 +59,20 @@ fun ClientCodegenContext.getBuiltIn(builtIn: String): Parameter? {
private fun promotedBuiltins(parameter: Parameter) =
    parameter == Builtins.FIPS || parameter == Builtins.DUALSTACK || parameter == Builtins.SDK_ENDPOINT

private fun ConfigParam.Builder.toConfigParam(parameter: Parameter, runtimeConfig: RuntimeConfig): ConfigParam =
    this.name(this.name ?: parameter.name.rustName())
        .type(
            when (parameter.type!!) {
                ParameterType.STRING -> RuntimeType.String.toSymbol()
                ParameterType.BOOLEAN -> RuntimeType.Bool.toSymbol()
            },
        )
        .newtype(
            when (promotedBuiltins(parameter)) {
private fun configParamNewtype(parameter: Parameter, name: String, runtimeConfig: RuntimeConfig): RuntimeType {
    val type = parameter.symbol().mapRustType { t -> t.stripOuter<RustType.Option>() }
    return when (promotedBuiltins(parameter)) {
        true -> AwsRuntimeType.awsTypes(runtimeConfig)
                    .resolve("endpoint_config::${this.name!!.toPascalCase()}")
            .resolve("endpoint_config::${name.toPascalCase()}")

                false -> configParamNewtype(this.name!!.toPascalCase(), this.type!!, runtimeConfig)
            },
        )
        false -> configParamNewtype(name.toPascalCase(), type, runtimeConfig)
    }
}

private fun ConfigParam.Builder.toConfigParam(parameter: Parameter, runtimeConfig: RuntimeConfig): ConfigParam =
    this.name(this.name ?: parameter.name.rustName())
        .type(parameter.symbol().mapRustType { t -> t.stripOuter<RustType.Option>() })
        .newtype(configParamNewtype(parameter, this.name!!, runtimeConfig))
        .setterDocs(this.setterDocs ?: parameter.documentation.orNull()?.let { writable { docs(it) } })
        .build()

@@ -139,7 +142,12 @@ fun decoratorForBuiltIn(
                    when (parameter.builtIn) {
                        builtIn.builtIn -> writable {
                            if (codegenContext.smithyRuntimeMode.defaultToOrchestrator) {
                                rust("$configRef.$name()")
                                val newtype = configParamNewtype(parameter, name, codegenContext.runtimeConfig)
                                val symbol = parameter.symbol().mapRustType { t -> t.stripOuter<RustType.Option>() }
                                rustTemplate(
                                    """$configRef.#{load_from_service_config_layer}""",
                                    "load_from_service_config_layer" to loadFromConfigBag(symbol.name, newtype),
                                )
                            } else {
                                rust("$configRef.$name")
                            }
+4 −1
Original line number Diff line number Diff line
@@ -132,7 +132,10 @@ class RegionDecorator : ClientCodegenDecorator {
                    return when (parameter.builtIn) {
                        Builtins.REGION.builtIn -> writable {
                            if (codegenContext.smithyRuntimeMode.defaultToOrchestrator) {
                                rust("$configRef.region().as_ref().map(|r|r.as_ref().to_owned())")
                                rustTemplate(
                                    "$configRef.load::<#{Region}>().map(|r|r.as_ref().to_owned())",
                                    "Region" to region(codegenContext.runtimeConfig).resolve("Region"),
                                )
                            } else {
                                rust("$configRef.region.as_ref().map(|r|r.as_ref().to_owned())")
                            }
+15 −8
Original line number Diff line number Diff line
@@ -13,9 +13,12 @@ import software.amazon.smithy.model.traits.EndpointTrait
import software.amazon.smithy.rulesengine.language.syntax.parameters.Parameters
import software.amazon.smithy.rulesengine.traits.ContextIndex
import software.amazon.smithy.rust.codegen.client.smithy.ClientCodegenContext
import software.amazon.smithy.rust.codegen.client.smithy.endpoint.ClientContextConfigCustomization
import software.amazon.smithy.rust.codegen.client.smithy.endpoint.EndpointTypesGenerator
import software.amazon.smithy.rust.codegen.client.smithy.endpoint.rustName
import software.amazon.smithy.rust.codegen.client.smithy.generators.EndpointTraitBindings
import software.amazon.smithy.rust.codegen.client.smithy.generators.config.configParamNewtype
import software.amazon.smithy.rust.codegen.client.smithy.generators.config.loadFromConfigBag
import software.amazon.smithy.rust.codegen.core.rustlang.CargoDependency
import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter
import software.amazon.smithy.rust.codegen.core.rustlang.Writable
@@ -83,11 +86,6 @@ class EndpointParamsInterceptorGenerator(

                    #{endpoint_prefix:W}

                    // HACK: pull the handle out of the config bag until config is implemented right
                    let handle = cfg.get::<std::sync::Arc<crate::client::Handle>>()
                        .expect("the handle is hacked into the config bag");
                    let _config = &handle.conf;

                    let params = #{Params}::builder()
                        #{param_setters}
                        .build()
@@ -109,15 +107,24 @@ class EndpointParamsInterceptorGenerator(
        val builtInParams = params.toList().filter { it.isBuiltIn }
        // first load builtins and their defaults
        builtInParams.forEach { param ->
            endpointTypesGenerator.builtInFor(param, "_config")?.also { defaultValue ->
            val config = if (codegenContext.smithyRuntimeMode.defaultToOrchestrator) {
                "cfg"
            } else {
                "_config"
            }
            endpointTypesGenerator.builtInFor(param, config)?.also { defaultValue ->
                rust(".set_${param.name.rustName()}(#W)", defaultValue)
            }
        }

        idx.getClientContextParams(codegenContext.serviceShape).orNull()?.parameters?.forEach { (name, param) ->
            val paramName = EndpointParamsGenerator.memberName(name)
            val setterName = EndpointParamsGenerator.setterName(name)
            rust(".$setterName(_config.$paramName())")
            val inner = ClientContextConfigCustomization.toSymbol(param.type, symbolProvider)
            val newtype = configParamNewtype(name, inner, codegenContext.runtimeConfig)
            rustTemplate(
                ".$setterName(cfg.#{load_from_service_config_layer})",
                "load_from_service_config_layer" to loadFromConfigBag(inner.name, newtype),
            )
        }

        idx.getStaticContextParams(operationShape).orNull()?.parameters?.forEach { (name, param) ->
+3 −3
Original line number Diff line number Diff line
@@ -111,6 +111,9 @@ class ServiceRuntimePluginGenerator(
    fun render(writer: RustWriter, customizations: List<ServiceRuntimePluginCustomization>) {
        writer.rustTemplate(
            """
            // TODO(enableNewSmithyRuntimeLaunch) Remove `allow(dead_code)` as well as a field `handle` when
            //  the field is no longer used.
            ##[allow(dead_code)]
            ##[derive(Debug)]
            pub(crate) struct ServiceRuntimePlugin {
                handle: #{Arc}<crate::client::Handle>,
@@ -127,9 +130,6 @@ class ServiceRuntimePluginGenerator(
                    use #{ConfigBagAccessors};
                    let mut cfg = #{Layer}::new(${codegenContext.serviceShape.id.name.dq()});

                    // HACK: Put the handle into the config bag to work around config not being fully implemented yet
                    cfg.put(self.handle.clone());

                    let http_auth_schemes = #{HttpAuthSchemes}::builder()
                        #{http_auth_scheme_customizations}
                        .build();
+31 −29
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@ import software.amazon.smithy.model.shapes.ServiceShape
import software.amazon.smithy.model.traits.IdempotencyTokenTrait
import software.amazon.smithy.rust.codegen.client.smithy.ClientCodegenContext
import software.amazon.smithy.rust.codegen.client.smithy.ClientRustModule
import software.amazon.smithy.rust.codegen.client.smithy.customizations.codegenScope
import software.amazon.smithy.rust.codegen.client.smithy.customize.TestUtilFeature
import software.amazon.smithy.rust.codegen.core.rustlang.Attribute
import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter
@@ -159,15 +160,37 @@ fun configParamNewtype(newtypeName: String, inner: Symbol, runtimeConfig: Runtim
        rustTemplate(
            """
            ##[derive(Debug, Clone)]
            pub(crate) struct $newtypeName($inner);
            pub(crate) struct $newtypeName(pub(crate) $inner);
            impl #{Storable} for $newtypeName {
                type Storer = #{StoreReplace}<$newtypeName>;
                type Storer = #{StoreReplace}<Self>;
            }
            """,
            *codegenScope,
        )
    }

/**
 * Render an expression that loads a value from a config bag.
 *
 * The expression to be rendered handles a case where a newtype is stored in the config bag, but the user expects
 * the underlying raw type after the newtype has been loaded from the bag.
 */
fun loadFromConfigBag(innerTypeName: String, newtype: RuntimeType): Writable = writable {
    rustTemplate(
        """
        load::<#{newtype}>().map(#{f})
        """,
        "newtype" to newtype,
        "f" to writable {
            if (innerTypeName == "bool") {
                rust("|ty| ty.0")
            } else {
                rust("|ty| ty.0.clone()")
            }
        },
    )
}

/**
 * Config customization for a config param with no special behavior:
 * 1. `pub(crate)` field
@@ -190,31 +213,6 @@ fun standardConfigParam(param: ConfigParam, codegenContext: ClientCodegenContext
                }
            }

            ServiceConfig.ConfigImpl -> writable {
                if (runtimeMode.defaultToOrchestrator) {
                    rustTemplate(
                        """
                        pub(crate) fn ${param.name}(&self) -> #{output} {
                            self.inner.load::<#{newtype}>().map(#{f})
                        }
                        """,
                        "f" to writable {
                            if (param.type.name == "bool") {
                                rust("|ty| ty.0")
                            } else {
                                rust("|ty| ty.0.clone()")
                            }
                        },
                        "newtype" to param.newtype!!,
                        "output" to if (param.optional) {
                            param.type.makeOptional()
                        } else {
                            param.type
                        },
                    )
                }
            }

            ServiceConfig.BuilderStruct -> writable {
                if (runtimeMode.defaultToMiddleware) {
                    rust("${param.name}: #T,", param.type.makeOptional())
@@ -430,6 +428,7 @@ class ServiceConfigGenerator(
                rustBlock("pub fn build(mut self) -> Config") {
                    rustTemplate(
                        """
                        ##[allow(unused_imports)]
                        use #{ConfigBagAccessors};
                        // The builder is being turned into a service config. While doing so, we'd like to avoid
                        // requiring that items created and stored _during_ the build method be `Clone`, since they
@@ -472,14 +471,17 @@ class ServiceConfigGenerator(
                    #{Some}(self.inner.clone())
                }

                fn interceptors(&self, interceptors: &mut #{InterceptorRegistrar}) {
                    interceptors.extend(self.interceptors.iter().cloned());
                fn interceptors(&self, _interceptors: &mut #{InterceptorRegistrar}) {
                    #{interceptors}
                }
            }

            """,
            *codegenScope,
            "config" to writable { writeCustomizations(customizations, ServiceConfig.RuntimePluginConfig("cfg")) },
            "interceptors" to writable {
                writeCustomizations(customizations, ServiceConfig.RuntimePluginInterceptors("_interceptors"))
            },
        )
    }

Loading