From 189f2b5fb537c76fc9781e5ea6f36007b0ef6ea6 Mon Sep 17 00:00:00 2001 From: Yuki Saito Date: Fri, 9 Jun 2023 22:54:23 -0500 Subject: [PATCH 01/15] Make types storable in config layer --- .../aws-credential-types/external-types.toml | 3 ++ .../aws-credential-types/src/cache.rs | 9 ++++++ .../aws-credential-types/src/provider.rs | 5 +++ .../aws-types/external-types.toml | 5 ++- aws/rust-runtime/aws-types/src/app_name.rs | 5 +++ .../aws-types/src/endpoint_config.rs | 31 +++++++++++++++++++ aws/rust-runtime/aws-types/src/lib.rs | 1 + aws/rust-runtime/aws-types/src/region.rs | 5 +++ rust-runtime/aws-smithy-async/Cargo.toml | 1 + .../aws-smithy-async/external-types.toml | 4 +++ rust-runtime/aws-smithy-async/src/rt/sleep.rs | 5 +++ .../aws-smithy-async/src/test_util.rs | 2 +- rust-runtime/aws-smithy-async/src/time.rs | 5 +++ .../aws-smithy-client/src/http_connector.rs | 5 +++ rust-runtime/aws-smithy-http/src/endpoint.rs | 5 +++ .../src/client/identity.rs | 6 +++- .../src/client/interceptors.rs | 6 +++- rust-runtime/aws-smithy-types/src/retry.rs | 5 +++ rust-runtime/aws-smithy-types/src/timeout.rs | 5 +++ .../inlineable/src/idempotency_token.rs | 5 +++ 20 files changed, 114 insertions(+), 4 deletions(-) create mode 100644 aws/rust-runtime/aws-types/src/endpoint_config.rs diff --git a/aws/rust-runtime/aws-credential-types/external-types.toml b/aws/rust-runtime/aws-credential-types/external-types.toml index 20337b394d..e5650b346c 100644 --- a/aws/rust-runtime/aws-credential-types/external-types.toml +++ b/aws/rust-runtime/aws-credential-types/external-types.toml @@ -1,3 +1,6 @@ allowed_external_types = [ "aws_smithy_async::rt::sleep::SharedAsyncSleep", + "aws_smithy_types::config_bag::Storable", + "aws_smithy_types::config_bag::StoreReplace", + "aws_smithy_types::config_bag::Storer", ] diff --git a/aws/rust-runtime/aws-credential-types/src/cache.rs b/aws/rust-runtime/aws-credential-types/src/cache.rs index 4d4810efab..a1351d0f9c 100644 --- a/aws/rust-runtime/aws-credential-types/src/cache.rs +++ b/aws/rust-runtime/aws-credential-types/src/cache.rs @@ -14,6 +14,7 @@ pub use lazy_caching::Builder as LazyBuilder; use no_caching::NoCredentialsCache; use crate::provider::{future, SharedCredentialsProvider}; +use aws_smithy_types::config_bag::{Storable, StoreReplace}; use std::sync::Arc; /// Asynchronous Cached Credentials Provider @@ -62,6 +63,10 @@ impl ProvideCachedCredentials for SharedCredentialsCache { } } +impl Storable for SharedCredentialsCache { + type Storer = StoreReplace; +} + #[derive(Clone, Debug)] pub(crate) enum Inner { Lazy(lazy_caching::Builder), @@ -122,3 +127,7 @@ impl CredentialsCache { } } } + +impl Storable for CredentialsCache { + type Storer = StoreReplace; +} diff --git a/aws/rust-runtime/aws-credential-types/src/provider.rs b/aws/rust-runtime/aws-credential-types/src/provider.rs index d9a43ab36d..9be88b590f 100644 --- a/aws/rust-runtime/aws-credential-types/src/provider.rs +++ b/aws/rust-runtime/aws-credential-types/src/provider.rs @@ -72,6 +72,7 @@ construct credentials from hardcoded values. //! ``` use crate::Credentials; +use aws_smithy_types::config_bag::{Storable, StoreReplace}; use std::sync::Arc; /// Credentials provider errors @@ -350,3 +351,7 @@ impl ProvideCredentials for SharedCredentialsProvider { self.0.provide_credentials() } } + +impl Storable for SharedCredentialsProvider { + type Storer = StoreReplace; +} diff --git a/aws/rust-runtime/aws-types/external-types.toml b/aws/rust-runtime/aws-types/external-types.toml index 830795ad27..c14e24ee25 100644 --- a/aws/rust-runtime/aws-types/external-types.toml +++ b/aws/rust-runtime/aws-types/external-types.toml @@ -2,13 +2,16 @@ allowed_external_types = [ "aws_credential_types::cache::CredentialsCache", "aws_credential_types::provider::SharedCredentialsProvider", "aws_smithy_async::rt::sleep::SharedAsyncSleep", - "aws_smithy_async::time::TimeSource", "aws_smithy_async::time::SharedTimeSource", + "aws_smithy_async::time::TimeSource", "aws_smithy_client::http_connector", "aws_smithy_client::http_connector::HttpConnector", "aws_smithy_http::endpoint::Endpoint", "aws_smithy_http::endpoint::EndpointPrefix", "aws_smithy_http::endpoint::error::InvalidEndpointError", + "aws_smithy_types::config_bag::Storable", + "aws_smithy_types::config_bag::StoreReplace", + "aws_smithy_types::config_bag::Storer", "aws_smithy_types::retry::RetryConfig", "aws_smithy_types::timeout::TimeoutConfig", "http::uri::Uri", diff --git a/aws/rust-runtime/aws-types/src/app_name.rs b/aws/rust-runtime/aws-types/src/app_name.rs index 70843e19bd..25555eab64 100644 --- a/aws/rust-runtime/aws-types/src/app_name.rs +++ b/aws/rust-runtime/aws-types/src/app_name.rs @@ -5,6 +5,7 @@ //! New-type for a configurable app name. +use aws_smithy_types::config_bag::{Storable, StoreReplace}; use std::borrow::Cow; use std::error::Error; use std::fmt; @@ -38,6 +39,10 @@ impl fmt::Display for AppName { } } +impl Storable for AppName { + type Storer = StoreReplace; +} + impl AppName { /// Creates a new app name. /// diff --git a/aws/rust-runtime/aws-types/src/endpoint_config.rs b/aws/rust-runtime/aws-types/src/endpoint_config.rs new file mode 100644 index 0000000000..562051f530 --- /dev/null +++ b/aws/rust-runtime/aws-types/src/endpoint_config.rs @@ -0,0 +1,31 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +//! Newtypes for endpoint-related parameters +//! +//! Parameters require newtypes so they have distinct types when stored in layers in config bag. + +use aws_smithy_types::config_bag::{Storable, StoreReplace}; + +/// Newtype for `use_fips` +#[derive(Clone, Debug)] +pub struct UseFips(pub bool); +impl Storable for UseFips { + type Storer = StoreReplace; +} + +/// Newtype for `use_dual_stack` +#[derive(Clone, Debug)] +pub struct UseDualStack(pub bool); +impl Storable for UseDualStack { + type Storer = StoreReplace; +} + +/// Newtype for `endpoint_url` +#[derive(Clone, Debug)] +pub struct EndpointUrl(pub String); +impl Storable for EndpointUrl { + type Storer = StoreReplace; +} diff --git a/aws/rust-runtime/aws-types/src/lib.rs b/aws/rust-runtime/aws-types/src/lib.rs index 27860df1be..de5bfa269e 100644 --- a/aws/rust-runtime/aws-types/src/lib.rs +++ b/aws/rust-runtime/aws-types/src/lib.rs @@ -16,6 +16,7 @@ pub mod app_name; pub mod build_metadata; +pub mod endpoint_config; #[doc(hidden)] pub mod os_shim_internal; pub mod region; diff --git a/aws/rust-runtime/aws-types/src/region.rs b/aws/rust-runtime/aws-types/src/region.rs index 3f053d0acb..be09aac6da 100644 --- a/aws/rust-runtime/aws-types/src/region.rs +++ b/aws/rust-runtime/aws-types/src/region.rs @@ -5,6 +5,7 @@ //! Region type for determining the endpoint to send requests to. +use aws_smithy_types::config_bag::{Storable, StoreReplace}; use std::borrow::Cow; use std::fmt::{Display, Formatter}; @@ -35,6 +36,10 @@ impl Display for Region { } } +impl Storable for Region { + type Storer = StoreReplace; +} + impl Region { /// Creates a new `Region` from the given string. pub fn new(region: impl Into>) -> Self { diff --git a/rust-runtime/aws-smithy-async/Cargo.toml b/rust-runtime/aws-smithy-async/Cargo.toml index c95862d9ff..ca703aaf65 100644 --- a/rust-runtime/aws-smithy-async/Cargo.toml +++ b/rust-runtime/aws-smithy-async/Cargo.toml @@ -12,6 +12,7 @@ rt-tokio = ["tokio/time"] test-util = [] [dependencies] +aws-smithy-types = { path = "../aws-smithy-types" } pin-project-lite = "0.2" tokio = { version = "1.23.1", features = ["sync"] } tokio-stream = { version = "0.1.5", default-features = false } diff --git a/rust-runtime/aws-smithy-async/external-types.toml b/rust-runtime/aws-smithy-async/external-types.toml index 613ae21ffb..67a89e03da 100644 --- a/rust-runtime/aws-smithy-async/external-types.toml +++ b/rust-runtime/aws-smithy-async/external-types.toml @@ -1,4 +1,8 @@ allowed_external_types = [ + "aws_smithy_types::config_bag::Storable", + "aws_smithy_types::config_bag::StoreReplace", + "aws_smithy_types::config_bag::Storer", + # TODO(https://github.com/awslabs/smithy-rs/issues/1193): Switch to AsyncIterator once standardized "futures_core::stream::Stream", diff --git a/rust-runtime/aws-smithy-async/src/rt/sleep.rs b/rust-runtime/aws-smithy-async/src/rt/sleep.rs index 076db95c97..6776790ee0 100644 --- a/rust-runtime/aws-smithy-async/src/rt/sleep.rs +++ b/rust-runtime/aws-smithy-async/src/rt/sleep.rs @@ -6,6 +6,7 @@ //! Provides an [`AsyncSleep`] trait that returns a future that sleeps for a given duration, //! and implementations of `AsyncSleep` for different async runtimes. +use aws_smithy_types::config_bag::{Storable, StoreReplace}; use std::fmt::{Debug, Formatter}; use std::future::Future; use std::pin::Pin; @@ -68,6 +69,10 @@ impl AsyncSleep for SharedAsyncSleep { } } +impl Storable for SharedAsyncSleep { + type Storer = StoreReplace; +} + #[cfg(feature = "rt-tokio")] /// Returns a default sleep implementation based on the features enabled pub fn default_async_sleep() -> Option { diff --git a/rust-runtime/aws-smithy-async/src/test_util.rs b/rust-runtime/aws-smithy-async/src/test_util.rs index 365db3b504..0aec83070d 100644 --- a/rust-runtime/aws-smithy-async/src/test_util.rs +++ b/rust-runtime/aws-smithy-async/src/test_util.rs @@ -24,7 +24,7 @@ pub struct ManualTimeSource { impl TimeSource for ManualTimeSource { fn now(&self) -> SystemTime { - self.start_time + self.log.lock().unwrap().iter().sum() + self.start_time + self.log.lock().unwrap().iter().sum::() } } diff --git a/rust-runtime/aws-smithy-async/src/time.rs b/rust-runtime/aws-smithy-async/src/time.rs index 2abe332c88..0b43a0af74 100644 --- a/rust-runtime/aws-smithy-async/src/time.rs +++ b/rust-runtime/aws-smithy-async/src/time.rs @@ -4,6 +4,7 @@ */ //! Time source abstraction to support WASM and testing +use aws_smithy_types::config_bag::{Storable, StoreReplace}; use std::fmt::Debug; use std::sync::Arc; use std::time::SystemTime; @@ -86,3 +87,7 @@ impl TimeSource for SharedTimeSource { self.0.now() } } + +impl Storable for SharedTimeSource { + type Storer = StoreReplace; +} diff --git a/rust-runtime/aws-smithy-client/src/http_connector.rs b/rust-runtime/aws-smithy-client/src/http_connector.rs index 37366604ee..eaac5805c6 100644 --- a/rust-runtime/aws-smithy-client/src/http_connector.rs +++ b/rust-runtime/aws-smithy-client/src/http_connector.rs @@ -8,6 +8,7 @@ use crate::erase::DynConnector; use aws_smithy_async::rt::sleep::SharedAsyncSleep; +use aws_smithy_types::config_bag::{Storable, StoreReplace}; use aws_smithy_types::timeout::TimeoutConfig; use std::time::Duration; use std::{fmt::Debug, sync::Arc}; @@ -41,6 +42,10 @@ impl Debug for HttpConnector { } } +impl Storable for HttpConnector { + type Storer = StoreReplace; +} + impl HttpConnector { /// If `HttpConnector` is `Prebuilt`, return a clone of that connector. /// If `HttpConnector` is `ConnectorFn`, generate a new connector from settings and return it. diff --git a/rust-runtime/aws-smithy-http/src/endpoint.rs b/rust-runtime/aws-smithy-http/src/endpoint.rs index dcc1db18d7..47c1e1af00 100644 --- a/rust-runtime/aws-smithy-http/src/endpoint.rs +++ b/rust-runtime/aws-smithy-http/src/endpoint.rs @@ -7,6 +7,7 @@ use crate::endpoint::error::InvalidEndpointError; use crate::operation::error::BuildError; +use aws_smithy_types::config_bag::{Storable, StoreReplace}; use http::uri::{Authority, Uri}; use std::borrow::Cow; use std::fmt::{Debug, Formatter}; @@ -66,6 +67,10 @@ impl From>> for SharedEndpointResolver { } } +impl Storable for SharedEndpointResolver { + type Storer = StoreReplace>; +} + impl ResolveEndpoint for SharedEndpointResolver { fn resolve_endpoint(&self, params: &T) -> Result { self.0.resolve_endpoint(params) diff --git a/rust-runtime/aws-smithy-runtime-api/src/client/identity.rs b/rust-runtime/aws-smithy-runtime-api/src/client/identity.rs index 341567d191..ad8188342d 100644 --- a/rust-runtime/aws-smithy-runtime-api/src/client/identity.rs +++ b/rust-runtime/aws-smithy-runtime-api/src/client/identity.rs @@ -5,7 +5,7 @@ use crate::client::auth::AuthSchemeId; use crate::client::orchestrator::Future; -use aws_smithy_types::config_bag::ConfigBag; +use aws_smithy_types::config_bag::{ConfigBag, Storable, StoreReplace}; use std::any::Any; use std::fmt::Debug; use std::sync::Arc; @@ -23,6 +23,10 @@ pub struct IdentityResolvers { identity_resolvers: Vec<(AuthSchemeId, Arc)>, } +impl Storable for IdentityResolvers { + type Storer = StoreReplace; +} + impl IdentityResolvers { pub fn builder() -> builders::IdentityResolversBuilder { builders::IdentityResolversBuilder::new() diff --git a/rust-runtime/aws-smithy-runtime-api/src/client/interceptors.rs b/rust-runtime/aws-smithy-runtime-api/src/client/interceptors.rs index fe1f7e535d..47e1ef194b 100644 --- a/rust-runtime/aws-smithy-runtime-api/src/client/interceptors.rs +++ b/rust-runtime/aws-smithy-runtime-api/src/client/interceptors.rs @@ -9,7 +9,7 @@ pub mod error; use crate::client::interceptors::context::wrappers::{ FinalizerInterceptorContextMut, FinalizerInterceptorContextRef, }; -use aws_smithy_types::config_bag::ConfigBag; +use aws_smithy_types::config_bag::{ConfigBag, Storable, StoreAppend}; use aws_smithy_types::error::display::DisplayErrorContext; pub use context::{ wrappers::{ @@ -635,6 +635,10 @@ impl Deref for SharedInterceptor { } } +impl Storable for SharedInterceptor { + type Storer = StoreAppend; +} + /// Collection of [`SharedInterceptor`] that allows for only registration #[derive(Debug, Clone, Default)] pub struct InterceptorRegistrar { diff --git a/rust-runtime/aws-smithy-types/src/retry.rs b/rust-runtime/aws-smithy-types/src/retry.rs index b96ababf06..18053a0bb8 100644 --- a/rust-runtime/aws-smithy-types/src/retry.rs +++ b/rust-runtime/aws-smithy-types/src/retry.rs @@ -5,6 +5,7 @@ //! This module defines types that describe when to retry given a response. +use crate::config_bag::{Storable, StoreReplace}; use std::fmt; use std::str::FromStr; use std::time::Duration; @@ -262,6 +263,10 @@ pub struct RetryConfig { reconnect_mode: ReconnectMode, } +impl Storable for RetryConfig { + type Storer = StoreReplace; +} + /// Mode for connection re-establishment /// /// By default, when a transient error is encountered, the connection in use will be poisoned. This diff --git a/rust-runtime/aws-smithy-types/src/timeout.rs b/rust-runtime/aws-smithy-types/src/timeout.rs index 04e92650a9..160895ceb1 100644 --- a/rust-runtime/aws-smithy-types/src/timeout.rs +++ b/rust-runtime/aws-smithy-types/src/timeout.rs @@ -6,6 +6,7 @@ //! This module defines types that describe timeouts that can be applied to various stages of the //! Smithy networking stack. +use crate::config_bag::{Storable, StoreReplace}; use std::time::Duration; /// Builder for [`TimeoutConfig`]. @@ -208,6 +209,10 @@ pub struct TimeoutConfig { operation_attempt_timeout: Option, } +impl Storable for TimeoutConfig { + type Storer = StoreReplace; +} + impl TimeoutConfig { /// Returns a builder to create a `TimeoutConfig`. pub fn builder() -> TimeoutConfigBuilder { diff --git a/rust-runtime/inlineable/src/idempotency_token.rs b/rust-runtime/inlineable/src/idempotency_token.rs index ac71874bc1..12921f02af 100644 --- a/rust-runtime/inlineable/src/idempotency_token.rs +++ b/rust-runtime/inlineable/src/idempotency_token.rs @@ -3,6 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +use aws_smithy_types::config_bag::{Storable, StoreReplace}; use std::sync::Mutex; pub(crate) fn uuid_v4(input: u128) -> String { @@ -58,6 +59,10 @@ impl From<&'static str> for IdempotencyTokenProvider { } } +impl Storable for IdempotencyTokenProvider { + type Storer = StoreReplace; +} + impl IdempotencyTokenProvider { pub fn make_idempotency_token(&self) -> String { match &self.inner { From 9867d4886acc82bc41d204e9961ff421a63c324a Mon Sep 17 00:00:00 2001 From: Yuki Saito Date: Mon, 12 Jun 2023 10:41:01 -0500 Subject: [PATCH 02/15] Make service config contain just `FrozenLayer` This commit updates service configs to contain only a single field `FrozenLayer` and remove individual fields. Note that their builders still contain individual fields instead of just containing a `Layer` because `Layer` is currently not `Clone`able. --- .../amazon/smithy/rustsdk/CredentialCaches.kt | 134 +++++++++++----- .../rustsdk/EndpointBuiltInsDecorator.kt | 55 +++++-- .../HttpConnectorConfigCustomization.kt | 44 +++-- .../amazon/smithy/rustsdk/RegionDecorator.kt | 57 +++++-- .../smithy/rustsdk/UserAgentDecorator.kt | 62 ++++--- .../timestream/TimestreamDecorator.kt | 15 +- .../customizations/HttpAuthDecorator.kt | 41 +++-- .../HttpConnectorConfigDecorator.kt | 44 +++-- .../InterceptorConfigCustomization.kt | 15 +- .../ResiliencyConfigCustomization.kt | 125 ++++++++++----- .../customizations/TimeSourceCustomization.kt | 127 +++++++++++++++ .../customize/RequiredCustomizations.kt | 8 +- .../ClientContextConfigCustomization.kt | 17 +- .../endpoint/EndpointConfigCustomization.kt | 100 ++++++++---- .../EndpointParamsInterceptorGenerator.kt | 4 +- .../ServiceRuntimePluginGenerator.kt | 2 +- .../IdempotencyTokenProviderCustomization.kt | 56 +++++-- .../config/ServiceConfigGenerator.kt | 151 +++++++++++++++--- .../generators/config/TimeSourceConfig.kt | 40 ----- 19 files changed, 790 insertions(+), 307 deletions(-) create mode 100644 codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/TimeSourceCustomization.kt delete mode 100644 codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/TimeSourceConfig.kt diff --git a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/CredentialCaches.kt b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/CredentialCaches.kt index ae3cde9cc0..8bf443d8f9 100644 --- a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/CredentialCaches.kt +++ b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/CredentialCaches.kt @@ -27,7 +27,7 @@ class CredentialsCacheDecorator : ClientCodegenDecorator { codegenContext: ClientCodegenContext, baseCustomizations: List, ): List { - return baseCustomizations + CredentialCacheConfig(codegenContext.runtimeConfig) + return baseCustomizations + CredentialCacheConfig(codegenContext) } override fun operationCustomizations( @@ -49,44 +49,65 @@ class CredentialsCacheDecorator : ClientCodegenDecorator { /** * Add a `.credentials_cache` field and builder to the `Config` for a given service */ -class CredentialCacheConfig(runtimeConfig: RuntimeConfig) : ConfigCustomization() { +class CredentialCacheConfig(codegenContext: ClientCodegenContext) : ConfigCustomization() { + private val runtimeConfig = codegenContext.runtimeConfig + private val runtimeMode = codegenContext.smithyRuntimeMode private val codegenScope = arrayOf( - "cache" to AwsRuntimeType.awsCredentialTypes(runtimeConfig).resolve("cache"), - "provider" to AwsRuntimeType.awsCredentialTypes(runtimeConfig).resolve("provider"), + "CredentialsCache" to AwsRuntimeType.awsCredentialTypes(runtimeConfig).resolve("cache::CredentialsCache"), "DefaultProvider" to defaultProvider(), + "SharedCredentialsCache" to AwsRuntimeType.awsCredentialTypes(runtimeConfig).resolve("cache::SharedCredentialsCache"), + "SharedCredentialsProvider" to AwsRuntimeType.awsCredentialTypes(runtimeConfig).resolve("provider::SharedCredentialsProvider"), ) override fun section(section: ServiceConfig) = writable { when (section) { - ServiceConfig.ConfigStruct -> rustTemplate( - """pub(crate) credentials_cache: #{cache}::SharedCredentialsCache,""", - *codegenScope, - ) - - ServiceConfig.ConfigImpl -> rustTemplate( - """ - /// Returns the credentials cache. - pub fn credentials_cache(&self) -> #{cache}::SharedCredentialsCache { - self.credentials_cache.clone() + ServiceConfig.ConfigStruct -> { + if (runtimeMode.defaultToMiddleware) { + rustTemplate( + """pub(crate) credentials_cache: #{SharedCredentialsCache},""", + *codegenScope, + ) } - """, - *codegenScope, - ) + } + + ServiceConfig.ConfigImpl -> { + if (runtimeMode.defaultToOrchestrator) { + rustTemplate( + """ + /// Returns the credentials cache. + pub fn credentials_cache(&self) -> #{SharedCredentialsCache} { + self.inner.load::<#{SharedCredentialsCache}>().expect("credentials cache should be set").clone() + } + """, + *codegenScope, + ) + } else { + rustTemplate( + """ + /// Returns the credentials cache. + pub fn credentials_cache(&self) -> #{SharedCredentialsCache} { + self.credentials_cache.clone() + } + """, + *codegenScope, + ) + } + } ServiceConfig.BuilderStruct -> - rustTemplate("credentials_cache: Option<#{cache}::CredentialsCache>,", *codegenScope) + rustTemplate("credentials_cache: Option<#{CredentialsCache}>,", *codegenScope) ServiceConfig.BuilderImpl -> { rustTemplate( """ /// Sets the credentials cache for this service - pub fn credentials_cache(mut self, credentials_cache: #{cache}::CredentialsCache) -> Self { + pub fn credentials_cache(mut self, credentials_cache: #{CredentialsCache}) -> Self { self.set_credentials_cache(Some(credentials_cache)); self } /// Sets the credentials cache for this service - pub fn set_credentials_cache(&mut self, credentials_cache: Option<#{cache}::CredentialsCache>) -> &mut Self { + pub fn set_credentials_cache(&mut self, credentials_cache: Option<#{CredentialsCache}>) -> &mut Self { self.credentials_cache = credentials_cache; self } @@ -95,29 +116,56 @@ class CredentialCacheConfig(runtimeConfig: RuntimeConfig) : ConfigCustomization( ) } - ServiceConfig.BuilderBuild -> rustTemplate( - """ - credentials_cache: self - .credentials_cache - .unwrap_or_else({ - let sleep = self.sleep_impl.clone(); - || match sleep { - Some(sleep) => { - #{cache}::CredentialsCache::lazy_builder() - .sleep(sleep) - .into_credentials_cache() - } - None => #{cache}::CredentialsCache::lazy(), - } - }) - .create_cache( - self.credentials_provider.unwrap_or_else(|| { - #{provider}::SharedCredentialsProvider::new(#{DefaultProvider}) - }) - ), - """, - *codegenScope, - ) + ServiceConfig.BuilderBuild -> { + if (runtimeMode.defaultToOrchestrator) { + rustTemplate( + """ + layer.store_put( + self.credentials_cache + .unwrap_or_else({ + let sleep = self.sleep_impl.clone(); + || match sleep { + Some(sleep) => { + #{CredentialsCache}::lazy_builder() + .sleep(sleep) + .into_credentials_cache() + } + None => #{CredentialsCache}::lazy(), + } + }) + .create_cache(self.credentials_provider.unwrap_or_else(|| { + #{SharedCredentialsProvider}::new(#{DefaultProvider}) + })), + ); + """, + *codegenScope, + ) + } else { + rustTemplate( + """ + credentials_cache: self + .credentials_cache + .unwrap_or_else({ + let sleep = self.sleep_impl.clone(); + || match sleep { + Some(sleep) => { + #{CredentialsCache}::lazy_builder() + .sleep(sleep) + .into_credentials_cache() + } + None => #{CredentialsCache}::lazy(), + } + }) + .create_cache( + self.credentials_provider.unwrap_or_else(|| { + #{SharedCredentialsProvider}::new(#{DefaultProvider}) + }) + ), + """, + *codegenScope, + ) + } + } else -> emptySection } diff --git a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/EndpointBuiltInsDecorator.kt b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/EndpointBuiltInsDecorator.kt index 1ac83c10ca..9eec481e0c 100644 --- a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/EndpointBuiltInsDecorator.kt +++ b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/EndpointBuiltInsDecorator.kt @@ -22,18 +22,21 @@ import software.amazon.smithy.rust.codegen.client.smithy.endpoint.EndpointRulese import software.amazon.smithy.rust.codegen.client.smithy.endpoint.rustName 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.standardConfigParam 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.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.util.PANIC import software.amazon.smithy.rust.codegen.core.util.dq import software.amazon.smithy.rust.codegen.core.util.extendIf import software.amazon.smithy.rust.codegen.core.util.orNull +import software.amazon.smithy.rust.codegen.core.util.toPascalCase import java.util.Optional /** load a builtIn parameter from a ruleset by name */ @@ -48,14 +51,27 @@ fun ClientCodegenContext.getBuiltIn(builtIn: String): Parameter? { return rules.getBuiltIn(builtIn) } -private fun toConfigParam(parameter: Parameter): ConfigParam = ConfigParam( - parameter.name.rustName(), - when (parameter.type!!) { - ParameterType.STRING -> RuntimeType.String.toSymbol() - ParameterType.BOOLEAN -> RuntimeType.Bool.toSymbol() - }, - parameter.documentation.orNull()?.let { writable { docs(it) } }, -) +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)) { + true -> AwsRuntimeType.awsTypes(runtimeConfig) + .resolve("endpoint_config::${this.name!!.toPascalCase()}") + + false -> configParamNewtype(this.name!!.toPascalCase(), this.type!!, runtimeConfig) + }, + ) + .setterDocs(this.setterDocs ?: parameter.documentation.orNull()?.let { writable { docs(it) } }) + .build() fun Model.loadBuiltIn(serviceId: ShapeId, builtInSrc: Parameter): Parameter? { val model = this @@ -82,14 +98,14 @@ fun Model.sdkConfigSetter( } /** - * Create a client codegen decorator that creates bindings for a builtIn parameter. Optionally, you can provide [clientParam] - * which allows control over the config parameter that will be generated. + * Create a client codegen decorator that creates bindings for a builtIn parameter. Optionally, you can provide + * [clientParam.Builder] which allows control over the config parameter that will be generated. */ fun decoratorForBuiltIn( builtIn: Parameter, - clientParam: ConfigParam? = null, + clientParamBuilder: ConfigParam.Builder? = null, ): ClientCodegenDecorator { - val nameOverride = clientParam?.name + val nameOverride = clientParamBuilder?.name val name = nameOverride ?: builtIn.name.rustName() return object : ClientCodegenDecorator { override val name: String = "Auto${builtIn.builtIn.get()}" @@ -100,7 +116,7 @@ fun decoratorForBuiltIn( override fun extraSections(codegenContext: ClientCodegenContext): List { return listOfNotNull( - codegenContext.model.sdkConfigSetter(codegenContext.serviceShape.id, builtIn, clientParam?.name), + codegenContext.model.sdkConfigSetter(codegenContext.serviceShape.id, builtIn, clientParamBuilder?.name), ) } @@ -110,7 +126,9 @@ fun decoratorForBuiltIn( ): List { return baseCustomizations.extendIf(rulesetContainsBuiltIn(codegenContext)) { standardConfigParam( - clientParam ?: toConfigParam(builtIn), + clientParamBuilder?.toConfigParam(builtIn, codegenContext.runtimeConfig) ?: ConfigParam.Builder() + .toConfigParam(builtIn, codegenContext.runtimeConfig), + codegenContext, ) } } @@ -120,11 +138,16 @@ fun decoratorForBuiltIn( override fun loadBuiltInFromServiceConfig(parameter: Parameter, configRef: String): Writable? = when (parameter.builtIn) { builtIn.builtIn -> writable { - rust("$configRef.$name") + if (codegenContext.smithyRuntimeMode.defaultToOrchestrator) { + rust("$configRef.$name()") + } else { + rust("$configRef.$name") + } if (parameter.type == ParameterType.STRING) { rust(".clone()") } } + else -> null } @@ -173,6 +196,6 @@ val PromotedBuiltInsDecorators = decoratorForBuiltIn(Builtins.DUALSTACK), decoratorForBuiltIn( Builtins.SDK_ENDPOINT, - ConfigParam("endpoint_url", RuntimeType.String.toSymbol(), endpointUrlDocs), + ConfigParam.Builder().name("endpoint_url").type(RuntimeType.String.toSymbol()).setterDocs(endpointUrlDocs), ), ).toTypedArray() diff --git a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/HttpConnectorConfigCustomization.kt b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/HttpConnectorConfigCustomization.kt index d64ddea9b3..1190ee7ea5 100644 --- a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/HttpConnectorConfigCustomization.kt +++ b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/HttpConnectorConfigCustomization.kt @@ -13,7 +13,6 @@ 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.CodegenContext import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.util.letIf @@ -32,9 +31,10 @@ class HttpConnectorDecorator : ClientCodegenDecorator { } class HttpConnectorConfigCustomization( - codegenContext: CodegenContext, + codegenContext: ClientCodegenContext, ) : ConfigCustomization() { private val runtimeConfig = codegenContext.runtimeConfig + private val runtimeMode = codegenContext.smithyRuntimeMode private val moduleUseName = codegenContext.moduleUseName() private val codegenScope = arrayOf( "HttpConnector" to RuntimeType.smithyClient(runtimeConfig).resolve("http_connector::HttpConnector"), @@ -43,18 +43,32 @@ class HttpConnectorConfigCustomization( override fun section(section: ServiceConfig): Writable { return when (section) { is ServiceConfig.ConfigStruct -> writable { - rustTemplate("http_connector: Option<#{HttpConnector}>,", *codegenScope) + if (runtimeMode.defaultToMiddleware) { + rustTemplate("http_connector: Option<#{HttpConnector}>,", *codegenScope) + } } is ServiceConfig.ConfigImpl -> writable { - rustTemplate( - """ - /// Return an [`HttpConnector`](#{HttpConnector}) to use when making requests, if any. - pub fn http_connector(&self) -> Option<&#{HttpConnector}> { - self.http_connector.as_ref() - } - """, - *codegenScope, - ) + if (runtimeMode.defaultToOrchestrator) { + rustTemplate( + """ + /// Return an [`HttpConnector`](#{HttpConnector}) to use when making requests, if any. + pub fn http_connector(&self) -> Option<&#{HttpConnector}> { + self.inner.load::<#{HttpConnector}>() + } + """, + *codegenScope, + ) + } else { + rustTemplate( + """ + /// Return an [`HttpConnector`](#{HttpConnector}) to use when making requests, if any. + pub fn http_connector(&self) -> Option<&#{HttpConnector}> { + self.http_connector.as_ref() + } + """, + *codegenScope, + ) + } } is ServiceConfig.BuilderStruct -> writable { rustTemplate("http_connector: Option<#{HttpConnector}>,", *codegenScope) @@ -145,7 +159,11 @@ class HttpConnectorConfigCustomization( ) } is ServiceConfig.BuilderBuild -> writable { - rust("http_connector: self.http_connector,") + if (runtimeMode.defaultToOrchestrator) { + rust("layer.store_or_unset(self.http_connector);") + } else { + rust("http_connector: self.http_connector,") + } } else -> emptySection } diff --git a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/RegionDecorator.kt b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/RegionDecorator.kt index 61373f5d24..ae3f8b248e 100644 --- a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/RegionDecorator.kt +++ b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/RegionDecorator.kt @@ -21,7 +21,6 @@ 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.CodegenContext import software.amazon.smithy.rust.codegen.core.smithy.RuntimeConfig import software.amazon.smithy.rust.codegen.core.smithy.RustCrate import software.amazon.smithy.rust.codegen.core.smithy.customize.AdHocCustomization @@ -131,7 +130,11 @@ class RegionDecorator : ClientCodegenDecorator { override fun loadBuiltInFromServiceConfig(parameter: Parameter, configRef: String): Writable? { return when (parameter.builtIn) { Builtins.REGION.builtIn -> writable { - rust("$configRef.region.as_ref().map(|r|r.as_ref().to_owned())") + if (codegenContext.smithyRuntimeMode.defaultToOrchestrator) { + rust("$configRef.region().as_ref().map(|r|r.as_ref().to_owned())") + } else { + rust("$configRef.region.as_ref().map(|r|r.as_ref().to_owned())") + } } else -> null } @@ -153,22 +156,41 @@ class RegionDecorator : ClientCodegenDecorator { } } -class RegionProviderConfig(codegenContext: CodegenContext) : ConfigCustomization() { +class RegionProviderConfig(codegenContext: ClientCodegenContext) : ConfigCustomization() { 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")) override fun section(section: ServiceConfig) = writable { when (section) { - ServiceConfig.ConfigStruct -> rustTemplate("pub(crate) region: Option<#{Region}>,", *codegenScope) - ServiceConfig.ConfigImpl -> rustTemplate( - """ - /// Returns the AWS region, if it was provided. - pub fn region(&self) -> Option<&#{Region}> { - self.region.as_ref() + ServiceConfig.ConfigStruct -> { + if (runtimeMode.defaultToMiddleware) { + rustTemplate("pub(crate) region: Option<#{Region}>,", *codegenScope) } - """, - *codegenScope, - ) + } + ServiceConfig.ConfigImpl -> { + if (runtimeMode.defaultToOrchestrator) { + rustTemplate( + """ + /// Returns the AWS region, if it was provided. + pub fn region(&self) -> Option<&#{Region}> { + self.inner.load::<#{Region}>() + } + """, + *codegenScope, + ) + } else { + rustTemplate( + """ + /// Returns the AWS region, if it was provided. + pub fn region(&self) -> Option<&#{Region}> { + self.region.as_ref() + } + """, + *codegenScope, + ) + } + } ServiceConfig.BuilderStruct -> rustTemplate("pub(crate) region: Option<#{Region}>,", *codegenScope) @@ -201,10 +223,13 @@ class RegionProviderConfig(codegenContext: CodegenContext) : ConfigCustomization *codegenScope, ) - ServiceConfig.BuilderBuild -> rustTemplate( - """region: self.region,""", - *codegenScope, - ) + ServiceConfig.BuilderBuild -> { + if (runtimeMode.defaultToOrchestrator) { + rust("layer.store_or_unset(self.region);") + } else { + rust("region: self.region,") + } + } else -> emptySection } diff --git a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/UserAgentDecorator.kt b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/UserAgentDecorator.kt index 7ead51d18b..46ced0c5fc 100644 --- a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/UserAgentDecorator.kt +++ b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/UserAgentDecorator.kt @@ -20,7 +20,7 @@ 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.Companion.preludeScope import software.amazon.smithy.rust.codegen.core.smithy.RustCrate import software.amazon.smithy.rust.codegen.core.smithy.customizations.CrateVersionCustomization import software.amazon.smithy.rust.codegen.core.smithy.customize.AdHocCustomization @@ -40,7 +40,7 @@ class UserAgentDecorator : ClientCodegenDecorator { codegenContext: ClientCodegenContext, baseCustomizations: List, ): List { - return baseCustomizations + AppNameCustomization(codegenContext.runtimeConfig) + return baseCustomizations + AppNameCustomization(codegenContext) } override fun operationCustomizations( @@ -143,15 +143,18 @@ class UserAgentDecorator : ClientCodegenDecorator { } } - private class AppNameCustomization(runtimeConfig: RuntimeConfig) : ConfigCustomization() { + private class AppNameCustomization(codegenContext: ClientCodegenContext) : ConfigCustomization() { + private val runtimeConfig = codegenContext.runtimeConfig + private val runtimeMode = codegenContext.smithyRuntimeMode private val codegenScope = arrayOf( + *preludeScope, "AppName" to AwsRuntimeType.awsTypes(runtimeConfig).resolve("app_name::AppName"), ) override fun section(section: ServiceConfig): Writable = when (section) { is ServiceConfig.BuilderStruct -> writable { - rustTemplate("app_name: Option<#{AppName}>,", *codegenScope) + rustTemplate("app_name: #{Option}<#{AppName}>,", *codegenScope) } is ServiceConfig.BuilderImpl -> writable { @@ -170,7 +173,7 @@ class UserAgentDecorator : ClientCodegenDecorator { /// /// This _optional_ name is used to identify the application in the user agent that /// gets sent along with requests. - pub fn set_app_name(&mut self, app_name: Option<#{AppName}>) -> &mut Self { + pub fn set_app_name(&mut self, app_name: #{Option}<#{AppName}>) -> &mut Self { self.app_name = app_name; self } @@ -180,26 +183,47 @@ class UserAgentDecorator : ClientCodegenDecorator { } is ServiceConfig.BuilderBuild -> writable { - rust("app_name: self.app_name,") + if (runtimeMode.defaultToOrchestrator) { + rust("layer.store_or_unset(self.app_name);") + } else { + rust("app_name: self.app_name,") + } } is ServiceConfig.ConfigStruct -> writable { - rustTemplate("app_name: Option<#{AppName}>,", *codegenScope) + if (runtimeMode.defaultToMiddleware) { + rustTemplate("app_name: #{Option}<#{AppName}>,", *codegenScope) + } } is ServiceConfig.ConfigImpl -> writable { - rustTemplate( - """ - /// Returns the name of the app that is using the client, if it was provided. - /// - /// This _optional_ name is used to identify the application in the user agent that - /// gets sent along with requests. - pub fn app_name(&self) -> Option<&#{AppName}> { - self.app_name.as_ref() - } - """, - *codegenScope, - ) + if (runtimeMode.defaultToOrchestrator) { + rustTemplate( + """ + /// Returns the name of the app that is using the client, if it was provided. + /// + /// This _optional_ name is used to identify the application in the user agent that + /// gets sent along with requests. + pub fn app_name(&self) -> #{Option}<&#{AppName}> { + self.inner.load::<#{AppName}>() + } + """, + *codegenScope, + ) + } else { + rustTemplate( + """ + /// Returns the name of the app that is using the client, if it was provided. + /// + /// This _optional_ name is used to identify the application in the user agent that + /// gets sent along with requests. + pub fn app_name(&self) -> #{Option}<&#{AppName}> { + self.app_name.as_ref() + } + """, + *codegenScope, + ) + } } else -> emptySection diff --git a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/timestream/TimestreamDecorator.kt b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/timestream/TimestreamDecorator.kt index 695110e590..4b4c22e387 100644 --- a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/timestream/TimestreamDecorator.kt +++ b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/timestream/TimestreamDecorator.kt @@ -11,8 +11,10 @@ import software.amazon.smithy.rust.codegen.client.smithy.endpoint.Types import software.amazon.smithy.rust.codegen.core.rustlang.CargoDependency import software.amazon.smithy.rust.codegen.core.rustlang.DependencyScope import software.amazon.smithy.rust.codegen.core.rustlang.Visibility +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.toType +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.smithy.RustCrate @@ -52,6 +54,7 @@ class TimestreamDecorator : ClientCodegenDecorator { Visibility.PUBLIC, CargoDependency.Tokio.copy(scope = DependencyScope.Compile, features = setOf("sync")), ) + val runtimeMode = codegenContext.smithyRuntimeMode rustCrate.lib { // helper function to resolve an endpoint given a base client rustTemplate( @@ -62,7 +65,7 @@ class TimestreamDecorator : ClientCodegenDecorator { #{ResolveEndpointError}::from_source("failed to call describe_endpoints", e) })?; let endpoint = describe_endpoints.endpoints().unwrap().get(0).unwrap(); - let expiry = client.conf().time_source.now() + #{Duration}::from_secs(endpoint.cache_period_in_minutes() as u64 * 60); + let expiry = client.conf().#{time_source}.now() + #{Duration}::from_secs(endpoint.cache_period_in_minutes() as u64 * 60); Ok(( #{Endpoint}::builder() .url(format!("https://{}", endpoint.address().unwrap())) @@ -78,7 +81,7 @@ class TimestreamDecorator : ClientCodegenDecorator { pub async fn enable_endpoint_discovery(self) -> #{Result}<(Self, #{endpoint_discovery}::ReloadEndpoint), #{ResolveEndpointError}> { let mut new_conf = self.conf().clone(); let sleep = self.conf().sleep_impl().expect("sleep impl must be provided"); - let time = self.conf().time_source.clone(); + let time = self.conf().#{time_source}.clone(); let (resolver, reloader) = #{endpoint_discovery}::create_cache( move || { let client = self.clone(); @@ -92,9 +95,15 @@ class TimestreamDecorator : ClientCodegenDecorator { Ok((Self::from_conf(new_conf), reloader)) } } - """, "endpoint_discovery" to endpointDiscovery.toType(), + "time_source" to writable { + if (runtimeMode.defaultToOrchestrator) { + rust("time_source()") + } else { + rust("time_source") + } + }, "SystemTime" to RuntimeType.std.resolve("time::SystemTime"), "Duration" to RuntimeType.std.resolve("time::Duration"), "SharedEndpointResolver" to RuntimeType.smithyHttp(codegenContext.runtimeConfig) diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/HttpAuthDecorator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/HttpAuthDecorator.kt index dd19433315..aed42c62c6 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/HttpAuthDecorator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/HttpAuthDecorator.kt @@ -237,6 +237,7 @@ private class HttpAuthConfigCustomization( private val authSchemes: HttpAuthSchemes, ) : ConfigCustomization() { private val codegenScope = codegenScope(codegenContext.runtimeConfig) + private val runtimeMode = codegenContext.smithyRuntimeMode override fun section(section: ServiceConfig): Writable = writable { when (section) { @@ -324,23 +325,41 @@ private class HttpAuthConfigCustomization( } is ServiceConfig.BuilderBuild -> { - rust("identity_resolvers: self.identity_resolvers,") + if (runtimeMode.defaultToOrchestrator) { + rust(" layer.store_put(self.identity_resolvers);") + } else { + rust("identity_resolvers: self.identity_resolvers,") + } } is ServiceConfig.ConfigStruct -> { - rustTemplate("identity_resolvers: #{IdentityResolvers},", *codegenScope) + if (runtimeMode.defaultToMiddleware) { + rustTemplate("identity_resolvers: #{IdentityResolvers},", *codegenScope) + } } is ServiceConfig.ConfigImpl -> { - rustTemplate( - """ - /// Returns the identity resolvers. - pub fn identity_resolvers(&self) -> &#{IdentityResolvers} { - &self.identity_resolvers - } - """, - *codegenScope, - ) + if (runtimeMode.defaultToOrchestrator) { + rustTemplate( + """ + /// Returns the identity resolvers. + pub fn identity_resolvers(&self) -> &#{IdentityResolvers} { + self.inner.load::<#{IdentityResolvers}>().expect("Identity resolvers should be set") + } + """, + *codegenScope, + ) + } else { + rustTemplate( + """ + /// Returns the identity resolvers. + pub fn identity_resolvers(&self) -> &#{IdentityResolvers} { + &self.identity_resolvers + } + """, + *codegenScope, + ) + } } else -> {} diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/HttpConnectorConfigDecorator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/HttpConnectorConfigDecorator.kt index ba9c68f5f7..8d1cb133ae 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/HttpConnectorConfigDecorator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/HttpConnectorConfigDecorator.kt @@ -13,7 +13,6 @@ 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.CodegenContext import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.util.letIf @@ -31,9 +30,10 @@ class HttpConnectorConfigDecorator : ClientCodegenDecorator { } private class HttpConnectorConfigCustomization( - codegenContext: CodegenContext, + codegenContext: ClientCodegenContext, ) : ConfigCustomization() { private val runtimeConfig = codegenContext.runtimeConfig + private val runtimeMode = codegenContext.smithyRuntimeMode private val moduleUseName = codegenContext.moduleUseName() private val codegenScope = arrayOf( "HttpConnector" to RuntimeType.smithyClient(runtimeConfig).resolve("http_connector::HttpConnector"), @@ -42,19 +42,33 @@ private class HttpConnectorConfigCustomization( override fun section(section: ServiceConfig): Writable { return when (section) { is ServiceConfig.ConfigStruct -> writable { - rustTemplate("http_connector: Option<#{HttpConnector}>,", *codegenScope) + if (runtimeMode.defaultToMiddleware) { + rustTemplate("http_connector: Option<#{HttpConnector}>,", *codegenScope) + } } is ServiceConfig.ConfigImpl -> writable { - rustTemplate( - """ - /// Return an [`HttpConnector`](#{HttpConnector}) to use when making requests, if any. - pub fn http_connector(&self) -> Option<&#{HttpConnector}> { - self.http_connector.as_ref() - } - """, - *codegenScope, - ) + if (runtimeMode.defaultToOrchestrator) { + rustTemplate( + """ + /// Return an [`HttpConnector`](#{HttpConnector}) to use when making requests, if any. + pub fn http_connector(&self) -> Option<&#{HttpConnector}> { + self.inner.load::<#{HttpConnector}>() + } + """, + *codegenScope, + ) + } else { + rustTemplate( + """ + /// Return an [`HttpConnector`](#{HttpConnector}) to use when making requests, if any. + pub fn http_connector(&self) -> Option<&#{HttpConnector}> { + self.http_connector.as_ref() + } + """, + *codegenScope, + ) + } } is ServiceConfig.BuilderStruct -> writable { @@ -147,7 +161,11 @@ private class HttpConnectorConfigCustomization( } is ServiceConfig.BuilderBuild -> writable { - rust("http_connector: self.http_connector,") + if (runtimeMode.defaultToOrchestrator) { + rust("layer.store_or_unset(self.http_connector);") + } else { + rust("http_connector: self.http_connector,") + } } else -> emptySection diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/InterceptorConfigCustomization.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/InterceptorConfigCustomization.kt index 967bea65ac..8419d5ce69 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/InterceptorConfigCustomization.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/InterceptorConfigCustomization.kt @@ -25,13 +25,6 @@ class InterceptorConfigCustomization(codegenContext: CodegenContext) : ConfigCus override fun section(section: ServiceConfig) = writable { when (section) { - ServiceConfig.ConfigStruct -> rustTemplate( - """ - pub(crate) interceptors: Vec<#{SharedInterceptor}>, - """, - *codegenScope, - ) - ServiceConfig.BuilderStruct -> rustTemplate( """ @@ -46,7 +39,7 @@ class InterceptorConfigCustomization(codegenContext: CodegenContext) : ConfigCus ##[doc(hidden)] /// Returns interceptors currently registered by the user. pub fn interceptors(&self) -> impl Iterator + '_ { - self.interceptors.iter() + self.inner.load::<#{SharedInterceptor}>() } """, *codegenScope, @@ -171,11 +164,7 @@ class InterceptorConfigCustomization(codegenContext: CodegenContext) : ConfigCus *codegenScope, ) - ServiceConfig.BuilderBuild -> rust( - """ - interceptors: self.interceptors, - """, - ) + ServiceConfig.BuilderBuild -> rust("self.interceptors.into_iter().for_each(|i| { layer.store_append(i); });") ServiceConfig.ToRuntimePlugin -> rust( """ diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/ResiliencyConfigCustomization.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/ResiliencyConfigCustomization.kt index 90a03bd348..8c6a74dd99 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/ResiliencyConfigCustomization.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/ResiliencyConfigCustomization.kt @@ -5,6 +5,7 @@ package software.amazon.smithy.rust.codegen.client.smithy.customizations +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.generators.ServiceRuntimePluginCustomization import software.amazon.smithy.rust.codegen.client.smithy.generators.ServiceRuntimePluginSection @@ -14,13 +15,13 @@ 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.CodegenContext 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.RustCrate -class ResiliencyConfigCustomization(codegenContext: CodegenContext) : ConfigCustomization() { +class ResiliencyConfigCustomization(codegenContext: ClientCodegenContext) : ConfigCustomization() { private val runtimeConfig = codegenContext.runtimeConfig + private val runtimeMode = codegenContext.smithyRuntimeMode private val retryConfig = RuntimeType.smithyTypes(runtimeConfig).resolve("retry") private val sleepModule = RuntimeType.smithyAsync(runtimeConfig).resolve("rt::sleep") private val timeoutModule = RuntimeType.smithyTypes(runtimeConfig).resolve("timeout") @@ -35,38 +36,64 @@ class ResiliencyConfigCustomization(codegenContext: CodegenContext) : ConfigCust override fun section(section: ServiceConfig) = writable { when (section) { - is ServiceConfig.ConfigStruct -> rustTemplate( - """ - retry_config: Option<#{RetryConfig}>, - sleep_impl: Option<#{SharedAsyncSleep}>, - timeout_config: Option<#{TimeoutConfig}>, - """, - *codegenScope, - ) + is ServiceConfig.ConfigStruct -> { + if (runtimeMode.defaultToMiddleware) { + rustTemplate( + """ + retry_config: Option<#{RetryConfig}>, + sleep_impl: Option<#{SharedAsyncSleep}>, + timeout_config: Option<#{TimeoutConfig}>, + """, + *codegenScope, + ) + } + } is ServiceConfig.ConfigImpl -> { - rustTemplate( - """ - /// Return a reference to the retry configuration contained in this config, if any. - pub fn retry_config(&self) -> Option<&#{RetryConfig}> { - self.retry_config.as_ref() - } + if (runtimeMode.defaultToOrchestrator) { + rustTemplate( + """ + /// Return a reference to the retry configuration contained in this config, if any. + pub fn retry_config(&self) -> Option<&#{RetryConfig}> { + self.inner.load::<#{RetryConfig}>() + } - /// Return a cloned shared async sleep implementation from this config, if any. - pub fn sleep_impl(&self) -> Option<#{SharedAsyncSleep}> { - self.sleep_impl.clone() - } + /// Return a cloned shared async sleep implementation from this config, if any. + pub fn sleep_impl(&self) -> Option<#{SharedAsyncSleep}> { + self.inner.load::<#{SharedAsyncSleep}>().cloned() + } - /// Return a reference to the timeout configuration contained in this config, if any. - pub fn timeout_config(&self) -> Option<&#{TimeoutConfig}> { - self.timeout_config.as_ref() - } - """, - *codegenScope, - ) + /// Return a reference to the timeout configuration contained in this config, if any. + pub fn timeout_config(&self) -> Option<&#{TimeoutConfig}> { + self.inner.load::<#{TimeoutConfig}>() + } + """, + *codegenScope, + ) + } else { + rustTemplate( + """ + /// Return a reference to the retry configuration contained in this config, if any. + pub fn retry_config(&self) -> Option<&#{RetryConfig}> { + self.retry_config.as_ref() + } + + /// Return a cloned shared async sleep implementation from this config, if any. + pub fn sleep_impl(&self) -> Option<#{SharedAsyncSleep}> { + self.sleep_impl.clone() + } + + /// Return a reference to the timeout configuration contained in this config, if any. + pub fn timeout_config(&self) -> Option<&#{TimeoutConfig}> { + self.timeout_config.as_ref() + } + """, + *codegenScope, + ) + } } - is ServiceConfig.BuilderStruct -> + is ServiceConfig.BuilderStruct -> { rustTemplate( """ retry_config: Option<#{RetryConfig}>, @@ -75,6 +102,7 @@ class ResiliencyConfigCustomization(codegenContext: CodegenContext) : ConfigCust """, *codegenScope, ) + } ServiceConfig.BuilderImpl -> rustTemplate( @@ -216,21 +244,30 @@ class ResiliencyConfigCustomization(codegenContext: CodegenContext) : ConfigCust *codegenScope, ) - ServiceConfig.BuilderBuild -> rustTemplate( - // We call clone on sleep_impl because the field is used by - // initializing the credentials_cache field later in the build - // method of a Config builder. - // We could rearrange the order of decorators so that AwsCodegenDecorator - // runs before RequiredCustomizations, which in turns renders - // CredentialsCacheDecorator before this class, but that is a bigger - // change than adding a call to the clone method on sleep_impl. - """ - retry_config: self.retry_config, - sleep_impl: self.sleep_impl.clone(), - timeout_config: self.timeout_config, - """, - *codegenScope, - ) + ServiceConfig.BuilderBuild -> { + if (runtimeMode.defaultToOrchestrator) { + rustTemplate( + """ + layer.store_or_unset(self.retry_config); + layer.store_or_unset(self.sleep_impl.clone()); + layer.store_or_unset(self.timeout_config); + """, + *codegenScope, + ) + } else { + rustTemplate( + // We call clone on sleep_impl because the field is used by + // initializing the credentials_cache field later in the build + // method of a Config builder. + """ + retry_config: self.retry_config, + sleep_impl: self.sleep_impl.clone(), + timeout_config: self.timeout_config, + """, + *codegenScope, + ) + } + } else -> emptySection } @@ -276,7 +313,7 @@ class ResiliencyServiceRuntimePluginCustomization : ServiceRuntimePluginCustomiz if let Some(timeout_config) = self.handle.conf.timeout_config() { ${section.configBagName}.put(timeout_config.clone()); } - ${section.configBagName}.put(self.handle.conf.time_source.clone()); + ${section.configBagName}.put(self.handle.conf.time_source()); """, ) } diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/TimeSourceCustomization.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/TimeSourceCustomization.kt new file mode 100644 index 0000000000..e27531814e --- /dev/null +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/TimeSourceCustomization.kt @@ -0,0 +1,127 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package software.amazon.smithy.rust.codegen.client.smithy.customizations + +import software.amazon.smithy.rust.codegen.client.smithy.ClientCodegenContext +import software.amazon.smithy.rust.codegen.client.smithy.generators.OperationCustomization +import software.amazon.smithy.rust.codegen.client.smithy.generators.OperationSection +import software.amazon.smithy.rust.codegen.client.smithy.generators.config.ConfigCustomization +import software.amazon.smithy.rust.codegen.client.smithy.generators.config.ServiceConfig +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.rustBlockTemplate +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 + +class TimeSourceCustomization(codegenContext: ClientCodegenContext) : ConfigCustomization() { + private val runtimeMode = codegenContext.smithyRuntimeMode + private val codegenScope = arrayOf( + *preludeScope, + "SharedTimeSource" to RuntimeType.smithyAsync(codegenContext.runtimeConfig).resolve("time::SharedTimeSource"), + ) + + override fun section(section: ServiceConfig) = + writable { + when (section) { + is ServiceConfig.ConfigStruct -> { + if (runtimeMode.defaultToMiddleware) { + rustTemplate( + """ + pub(crate) time_source: #{SharedTimeSource}, + """, + *codegenScope, + ) + } + } + + is ServiceConfig.ConfigImpl -> { + rust("/// Return time source used for this service.") + rustBlockTemplate( + "pub fn time_source(&self) -> #{SharedTimeSource}", + *codegenScope, + ) { + if (runtimeMode.defaultToOrchestrator) { + rustTemplate( + """self.inner.load::<#{SharedTimeSource}>().expect("time source should be set").clone()""", + *codegenScope, + ) + } else { + rust("self.time_source.clone()") + } + } + } + + is ServiceConfig.BuilderStruct -> + rustTemplate( + """ + time_source: #{Option}<#{SharedTimeSource}>, + """, + *codegenScope, + ) + + ServiceConfig.BuilderImpl -> + rustTemplate( + """ + /// Sets the time source used for this service + pub fn time_source( + mut self, + time_source: impl #{Into}<#{SharedTimeSource}>, + ) -> Self { + self.time_source = Some(time_source.into()); + self + } + /// Sets the time source used for this service + pub fn set_time_source( + &mut self, + time_source: #{Option}<#{SharedTimeSource}>, + ) -> &mut Self { + self.time_source = time_source; + self + } + """, + *codegenScope, + ) + + ServiceConfig.BuilderBuild -> { + if (runtimeMode.defaultToOrchestrator) { + rustTemplate( + """ + layer.store_put(self.time_source.unwrap_or_default()); + """, + *codegenScope, + ) + } else { + rustTemplate( + """ + time_source: self.time_source.unwrap_or_default(), + """, + *codegenScope, + ) + } + } + + else -> emptySection + } + } +} + +class TimeSourceOperationCustomization : OperationCustomization() { + override fun section(section: OperationSection): Writable { + return when (section) { + is OperationSection.MutateRequest -> writable { + rust( + """ + ${section.request}.properties_mut().insert(${section.config}.time_source.clone()); + """, + ) + } + + else -> emptySection + } + } +} diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customize/RequiredCustomizations.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customize/RequiredCustomizations.kt index 307866bfac..ee415bfcf4 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customize/RequiredCustomizations.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customize/RequiredCustomizations.kt @@ -16,11 +16,11 @@ import software.amazon.smithy.rust.codegen.client.smithy.customizations.Intercep import software.amazon.smithy.rust.codegen.client.smithy.customizations.ResiliencyConfigCustomization import software.amazon.smithy.rust.codegen.client.smithy.customizations.ResiliencyReExportCustomization import software.amazon.smithy.rust.codegen.client.smithy.customizations.ResiliencyServiceRuntimePluginCustomization +import software.amazon.smithy.rust.codegen.client.smithy.customizations.TimeSourceCustomization +import software.amazon.smithy.rust.codegen.client.smithy.customizations.TimeSourceOperationCustomization import software.amazon.smithy.rust.codegen.client.smithy.generators.OperationCustomization import software.amazon.smithy.rust.codegen.client.smithy.generators.ServiceRuntimePluginCustomization import software.amazon.smithy.rust.codegen.client.smithy.generators.config.ConfigCustomization -import software.amazon.smithy.rust.codegen.client.smithy.generators.config.TimeSourceOperationCustomization -import software.amazon.smithy.rust.codegen.client.smithy.generators.config.timeSourceCustomization import software.amazon.smithy.rust.codegen.core.rustlang.Feature import software.amazon.smithy.rust.codegen.core.smithy.RustCrate import software.amazon.smithy.rust.codegen.core.smithy.customizations.AllowLintsCustomization @@ -60,9 +60,9 @@ class RequiredCustomizations : ClientCodegenDecorator { if (codegenContext.smithyRuntimeMode.generateOrchestrator) { baseCustomizations + ResiliencyConfigCustomization(codegenContext) + InterceptorConfigCustomization( codegenContext, - ) + timeSourceCustomization(codegenContext) + ) + TimeSourceCustomization(codegenContext) } else { - baseCustomizations + ResiliencyConfigCustomization(codegenContext) + timeSourceCustomization(codegenContext) + baseCustomizations + ResiliencyConfigCustomization(codegenContext) + TimeSourceCustomization(codegenContext) } override fun libRsCustomizations( diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/endpoint/ClientContextConfigCustomization.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/endpoint/ClientContextConfigCustomization.kt index 05be47f0f5..db842def8d 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/endpoint/ClientContextConfigCustomization.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/endpoint/ClientContextConfigCustomization.kt @@ -11,19 +11,22 @@ import software.amazon.smithy.model.shapes.ShapeType import software.amazon.smithy.model.shapes.StringShape import software.amazon.smithy.rulesengine.traits.ClientContextParamDefinition import software.amazon.smithy.rulesengine.traits.ClientContextParamsTrait +import software.amazon.smithy.rust.codegen.client.smithy.ClientCodegenContext 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.ServiceConfig +import software.amazon.smithy.rust.codegen.client.smithy.generators.config.configParamNewtype import software.amazon.smithy.rust.codegen.client.smithy.generators.config.standardConfigParam import software.amazon.smithy.rust.codegen.core.rustlang.RustReservedWords 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.join import software.amazon.smithy.rust.codegen.core.rustlang.writable -import software.amazon.smithy.rust.codegen.core.smithy.CodegenContext +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeConfig import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider import software.amazon.smithy.rust.codegen.core.util.getTrait import software.amazon.smithy.rust.codegen.core.util.orNull +import software.amazon.smithy.rust.codegen.core.util.toPascalCase import software.amazon.smithy.rust.codegen.core.util.toSnakeCase /** @@ -32,10 +35,11 @@ import software.amazon.smithy.rust.codegen.core.util.toSnakeCase * This handles injecting parameters like `s3::Accelerate` or `s3::ForcePathStyle`. The resulting parameters become * setters on the config builder object. */ -class ClientContextConfigCustomization(ctx: CodegenContext) : ConfigCustomization() { +class ClientContextConfigCustomization(ctx: ClientCodegenContext) : ConfigCustomization() { + private val runtimeConfig = ctx.runtimeConfig private val configParams = ctx.serviceShape.getTrait()?.parameters.orEmpty().toList() - .map { (key, value) -> fromClientParam(key, value, ctx.symbolProvider) } - private val decorators = configParams.map { standardConfigParam(it) } + .map { (key, value) -> fromClientParam(key, value, ctx.symbolProvider, runtimeConfig) } + private val decorators = configParams.map { standardConfigParam(it, ctx) } companion object { fun toSymbol(shapeType: ShapeType, symbolProvider: RustSymbolProvider): Symbol = @@ -51,10 +55,13 @@ class ClientContextConfigCustomization(ctx: CodegenContext) : ConfigCustomizatio name: String, definition: ClientContextParamDefinition, symbolProvider: RustSymbolProvider, + runtimeConfig: RuntimeConfig, ): ConfigParam { + val inner = toSymbol(definition.type, symbolProvider) return ConfigParam( RustReservedWords.escapeIfNeeded(name.toSnakeCase()), - toSymbol(definition.type, symbolProvider), + inner, + configParamNewtype(RustReservedWords.escapeIfNeeded(name.toPascalCase()), inner, runtimeConfig), definition.documentation.orNull()?.let { writable { docs(it) } }, ) } diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/endpoint/EndpointConfigCustomization.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/endpoint/EndpointConfigCustomization.kt index 6d74f1a7dc..a3308ce4da 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/endpoint/EndpointConfigCustomization.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/endpoint/EndpointConfigCustomization.kt @@ -25,6 +25,7 @@ internal class EndpointConfigCustomization( ConfigCustomization() { private val runtimeConfig = codegenContext.runtimeConfig private val moduleUseName = codegenContext.moduleUseName() + private val runtimeMode = codegenContext.smithyRuntimeMode private val types = Types(runtimeConfig) override fun section(section: ServiceConfig): Writable { @@ -38,21 +39,38 @@ internal class EndpointConfigCustomization( "Params" to typesGenerator.paramsStruct(), ) when (section) { - is ServiceConfig.ConfigStruct -> rustTemplate( - "pub (crate) endpoint_resolver: $sharedEndpointResolver,", - *codegenScope, - ) + is ServiceConfig.ConfigStruct -> { + if (runtimeMode.defaultToMiddleware) { + rustTemplate( + "pub (crate) endpoint_resolver: $sharedEndpointResolver,", + *codegenScope, + ) + } + } - is ServiceConfig.ConfigImpl -> - rustTemplate( - """ - /// Returns the endpoint resolver. - pub fn endpoint_resolver(&self) -> $sharedEndpointResolver { - self.endpoint_resolver.clone() - } - """, - *codegenScope, - ) + is ServiceConfig.ConfigImpl -> { + if (runtimeMode.defaultToOrchestrator) { + rustTemplate( + """ + /// Returns the endpoint resolver. + pub fn endpoint_resolver(&self) -> $sharedEndpointResolver { + self.inner.load::<$sharedEndpointResolver>().expect("endpoint resolver should be set").clone() + } + """, + *codegenScope, + ) + } else { + rustTemplate( + """ + /// Returns the endpoint resolver. + pub fn endpoint_resolver(&self) -> $sharedEndpointResolver { + self.endpoint_resolver.clone() + } + """, + *codegenScope, + ) + } + } is ServiceConfig.BuilderStruct -> rustTemplate( @@ -123,15 +141,27 @@ internal class EndpointConfigCustomization( ServiceConfig.BuilderBuild -> { val defaultResolver = typesGenerator.defaultResolver() if (defaultResolver != null) { - rustTemplate( - """ - endpoint_resolver: self.endpoint_resolver.unwrap_or_else(|| - #{SharedEndpointResolver}::new(#{DefaultResolver}::new()) - ), - """, - *codegenScope, - "DefaultResolver" to defaultResolver, - ) + if (runtimeMode.defaultToOrchestrator) { + rustTemplate( + """ + layer.store_put(self.endpoint_resolver.unwrap_or_else(|| + #{SharedEndpointResolver}::new(#{DefaultResolver}::new()) + )); + """, + *codegenScope, + "DefaultResolver" to defaultResolver, + ) + } else { + rustTemplate( + """ + endpoint_resolver: self.endpoint_resolver.unwrap_or_else(|| + #{SharedEndpointResolver}::new(#{DefaultResolver}::new()) + ), + """, + *codegenScope, + "DefaultResolver" to defaultResolver, + ) + } } else { val alwaysFailsResolver = RuntimeType.forInlineFun("MissingResolver", ClientRustModule.Endpoint) { @@ -152,13 +182,23 @@ internal class EndpointConfigCustomization( } // To keep this diff under control, rather than `.expect` here, insert a resolver that will // always fail. In the future, this will be changed to an `expect()` - rustTemplate( - """ - endpoint_resolver: self.endpoint_resolver.unwrap_or_else(||#{SharedEndpointResolver}::new(#{FailingResolver})), - """, - *codegenScope, - "FailingResolver" to alwaysFailsResolver, - ) + if (runtimeMode.defaultToOrchestrator) { + rustTemplate( + """ + layer.store_put(self.endpoint_resolver.unwrap_or_else(||#{SharedEndpointResolver}::new(#{FailingResolver}))); + """, + *codegenScope, + "FailingResolver" to alwaysFailsResolver, + ) + } else { + rustTemplate( + """ + endpoint_resolver: self.endpoint_resolver.unwrap_or_else(||#{SharedEndpointResolver}::new(#{FailingResolver})), + """, + *codegenScope, + "FailingResolver" to alwaysFailsResolver, + ) + } } } diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/endpoint/generators/EndpointParamsInterceptorGenerator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/endpoint/generators/EndpointParamsInterceptorGenerator.kt index 1dc2bb16dd..d525e0d31e 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/endpoint/generators/EndpointParamsInterceptorGenerator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/endpoint/generators/EndpointParamsInterceptorGenerator.kt @@ -115,9 +115,9 @@ class EndpointParamsInterceptorGenerator( val paramName = EndpointParamsGenerator.memberName(name) val setterName = EndpointParamsGenerator.setterName(name) if (param.type == ShapeType.BOOLEAN) { - rust(".$setterName(_config.$paramName)") + rust(".$setterName(_config.$paramName())") } else { - rust(".$setterName(_config.$paramName.clone())") + rust(".$setterName(_config.$paramName().clone())") } } diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/ServiceRuntimePluginGenerator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/ServiceRuntimePluginGenerator.kt index 0d6b924584..265d333ad8 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/ServiceRuntimePluginGenerator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/ServiceRuntimePluginGenerator.kt @@ -165,7 +165,7 @@ class ServiceRuntimePluginGenerator( #{additional_config} // Client-level Interceptors are registered after default Interceptors. - _interceptors.extend(self.handle.conf.interceptors.iter().cloned()); + _interceptors.extend(self.handle.conf.interceptors().cloned()); Ok(()) } diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/IdempotencyTokenProviderCustomization.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/IdempotencyTokenProviderCustomization.kt index 75b075dc4d..e29b5f7331 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/IdempotencyTokenProviderCustomization.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/IdempotencyTokenProviderCustomization.kt @@ -5,6 +5,7 @@ package software.amazon.smithy.rust.codegen.client.smithy.generators.config +import software.amazon.smithy.rust.codegen.client.smithy.SmithyRuntimeMode 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 @@ -15,25 +16,42 @@ import software.amazon.smithy.rust.codegen.core.smithy.customize.NamedCustomizat /** * Add a `make_token` field to Service config. See below for the resulting generated code. */ -class IdempotencyTokenProviderCustomization : NamedCustomization() { +class IdempotencyTokenProviderCustomization(private val runtimeMode: SmithyRuntimeMode) : NamedCustomization() { + override fun section(section: ServiceConfig): Writable { return when (section) { is ServiceConfig.ConfigStruct -> writable { - rust("pub (crate) make_token: #T::IdempotencyTokenProvider,", RuntimeType.IdempotencyToken) + if (runtimeMode.defaultToMiddleware) { + rust("pub (crate) make_token: #T::IdempotencyTokenProvider,", RuntimeType.IdempotencyToken) + } } ServiceConfig.ConfigImpl -> writable { - rust( - """ - /// Returns a copy of the idempotency token provider. - /// If a random token provider was configured, - /// a newly-randomized token provider will be returned. - pub fn make_token(&self) -> #T::IdempotencyTokenProvider { - self.make_token.clone() - } - """, - RuntimeType.IdempotencyToken, - ) + if (runtimeMode.defaultToOrchestrator) { + rustTemplate( + """ + /// Returns a copy of the idempotency token provider. + /// If a random token provider was configured, + /// a newly-randomized token provider will be returned. + pub fn make_token(&self) -> #{IdempotencyTokenProvider} { + self.inner.load::<#{IdempotencyTokenProvider}>().expect("the idempotency provider should be set").clone() + } + """, + "IdempotencyTokenProvider" to RuntimeType.IdempotencyToken.resolve("IdempotencyTokenProvider"), + ) + } else { + rust( + """ + /// Returns a copy of the idempotency token provider. + /// If a random token provider was configured, + /// a newly-randomized token provider will be returned. + pub fn make_token(&self) -> #T::IdempotencyTokenProvider { + self.make_token.clone() + } + """, + RuntimeType.IdempotencyToken, + ) + } } ServiceConfig.BuilderStruct -> writable { @@ -60,7 +78,17 @@ class IdempotencyTokenProviderCustomization : NamedCustomization( } ServiceConfig.BuilderBuild -> writable { - rust("make_token: self.make_token.unwrap_or_else(#T::default_provider),", RuntimeType.IdempotencyToken) + if (runtimeMode.defaultToOrchestrator) { + rust( + "layer.store_put(self.make_token.unwrap_or_else(#T::default_provider));", + RuntimeType.IdempotencyToken, + ) + } else { + rust( + "make_token: self.make_token.unwrap_or_else(#T::default_provider),", + RuntimeType.IdempotencyToken, + ) + } } is ServiceConfig.DefaultForTests -> writable { diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/ServiceConfigGenerator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/ServiceConfigGenerator.kt index a43d4f9e10..9a05eeeb13 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/ServiceConfigGenerator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/ServiceConfigGenerator.kt @@ -11,6 +11,9 @@ import software.amazon.smithy.model.knowledge.OperationIndex import software.amazon.smithy.model.knowledge.TopDownIndex 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 @@ -24,6 +27,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.rustBlockTemplate 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.CodegenContext +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.NamedCustomization import software.amazon.smithy.rust.codegen.core.smithy.customize.Section @@ -107,10 +111,53 @@ sealed class ServiceConfig(name: String) : Section(name) { data class ConfigParam( val name: String, val type: Symbol, + val newtype: RuntimeType?, val setterDocs: Writable?, val getterDocs: Writable? = null, val optional: Boolean = true, -) +) { + + data class Builder( + var name: String? = null, + var type: Symbol? = null, + var newtype: RuntimeType? = null, + var setterDocs: Writable? = null, + var getterDocs: Writable? = null, + var optional: Boolean = true, + ) { + fun name(name: String) = apply { this.name = name } + fun type(type: Symbol) = apply { this.type = type } + fun newtype(newtype: RuntimeType) = apply { this.newtype = newtype } + fun setterDocs(setterDocs: Writable?) = apply { this.setterDocs = setterDocs } + fun getterDocs(getterDocs: Writable?) = apply { this.getterDocs = getterDocs } + fun optional(optional: Boolean) = apply { this.optional = optional } + fun build() = ConfigParam(name!!, type!!, newtype, setterDocs, getterDocs, optional) + } +} + +/** + * Generate a [RuntimeType] for a newtype whose name is [newtypeName] that wraps [inner]. + * + * When config parameters are stored in a config map in Rust, stored parameters are keyed by type. + * Therefore, primitive types, such as bool and String, need to be wrapped in newtypes to make them distinct. + */ +fun configParamNewtype(newtypeName: String, inner: Symbol, runtimeConfig: RuntimeConfig) = + RuntimeType.forInlineFun(newtypeName, ClientRustModule.Config) { + val codegenScope = arrayOf( + "Storable" to RuntimeType.smithyTypes(runtimeConfig).resolve("config_bag::Storable"), + "StoreReplace" to RuntimeType.smithyTypes(runtimeConfig).resolve("config_bag::StoreReplace"), + ) + rustTemplate( + """ + ##[derive(Debug, Clone)] + pub(crate) struct $newtypeName($inner); + impl #{Storable} for $newtypeName { + type Storer = #{StoreReplace}<$newtypeName>; + } + """, + *codegenScope, + ) + } /** * Config customization for a config param with no special behavior: @@ -118,19 +165,47 @@ data class ConfigParam( * 2. convenience setter (non-optional) * 3. standard setter (&mut self) */ -fun standardConfigParam(param: ConfigParam): ConfigCustomization = object : ConfigCustomization() { +fun standardConfigParam(param: ConfigParam, codegenContext: ClientCodegenContext): ConfigCustomization = object : ConfigCustomization() { + private val runtimeMode = codegenContext.smithyRuntimeMode + override fun section(section: ServiceConfig): Writable { return when (section) { - is ServiceConfig.ConfigStruct -> writable { - docsOrFallback(param.getterDocs) - val t = when (param.optional) { - true -> param.type.makeOptional() - false -> param.type + ServiceConfig.ConfigStruct -> writable { + if (runtimeMode.defaultToMiddleware) { + docsOrFallback(param.getterDocs) + val t = when (param.optional) { + true -> param.type.makeOptional() + false -> param.type + } + rust("pub (crate) ${param.name}: #T,", t) + } + } + + 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 + }, + ) } - rust("pub (crate) ${param.name}: #T,", t) } - ServiceConfig.ConfigImpl -> emptySection ServiceConfig.BuilderStruct -> writable { rust("${param.name}: #T,", param.type.makeOptional()) } @@ -159,8 +234,15 @@ fun standardConfigParam(param: ConfigParam): ConfigCustomization = object : Conf } ServiceConfig.BuilderBuild -> writable { - val default = "".letIf(!param.optional) { ".unwrap_or_default() " } - rust("${param.name}: self.${param.name}$default,") + if (runtimeMode.defaultToOrchestrator) { + rustTemplate( + "layer.store_or_unset(self.${param.name}.map(#{newtype}));", + "newtype" to param.newtype!!, + ) + } else { + val default = "".letIf(!param.optional) { ".unwrap_or_default() " } + rust("${param.name}: self.${param.name}$default,") + } } ServiceConfig.ToRuntimePlugin -> emptySection @@ -196,18 +278,24 @@ typealias ConfigCustomization = NamedCustomization * // builder implementation * } */ -class ServiceConfigGenerator(private val customizations: List = listOf()) { +class ServiceConfigGenerator(private val codegenContext: ClientCodegenContext, private val customizations: List = listOf()) { + private val moduleUseName = codegenContext.moduleUseName() + private val runtimeMode = codegenContext.smithyRuntimeMode + private val codegenScope = arrayOf( + "FrozenLayer" to RuntimeType.smithyTypes(codegenContext.runtimeConfig).resolve("config_bag::FrozenLayer"), + "Layer" to RuntimeType.smithyTypes(codegenContext.runtimeConfig).resolve("config_bag::Layer"), + ) companion object { fun withBaseBehavior( - codegenContext: CodegenContext, + codegenContext: ClientCodegenContext, extraCustomizations: List, ): ServiceConfigGenerator { val baseFeatures = mutableListOf() if (codegenContext.serviceShape.needsIdempotencyToken(codegenContext.model)) { - baseFeatures.add(IdempotencyTokenProviderCustomization()) + baseFeatures.add(IdempotencyTokenProviderCustomization(codegenContext.smithyRuntimeMode)) } - return ServiceConfigGenerator(baseFeatures + extraCustomizations) + return ServiceConfigGenerator(codegenContext, baseFeatures + extraCustomizations) } } @@ -218,6 +306,12 @@ class ServiceConfigGenerator(private val customizations: List Self { Self::default() }") + writer.rust("pub fn new() -> Self { Self::default() }") customizations.forEach { it.section(ServiceConfig.BuilderImpl)(this) } @@ -294,15 +388,32 @@ class ServiceConfigGenerator(private val customizations: List Config") { - rustBlock("Config") { + if (runtimeMode.defaultToOrchestrator) { + rustTemplate( + """let mut layer = #{Layer}::new("$moduleUseName::Config");""", + *codegenScope, + ) customizations.forEach { it.section(ServiceConfig.BuilderBuild)(this) } + rustTemplate( + """ + Config { + inner: layer.freeze(), + } + """, + ) + } else { + rustBlock("Config") { + customizations.forEach { + it.section(ServiceConfig.BuilderBuild)(this) + } + } } } - } - customizations.forEach { - it.section(ServiceConfig.Extras)(writer) + customizations.forEach { + it.section(ServiceConfig.Extras)(writer) + } } } diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/TimeSourceConfig.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/TimeSourceConfig.kt deleted file mode 100644 index ea5285aa70..0000000000 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/TimeSourceConfig.kt +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0 - */ - -package software.amazon.smithy.rust.codegen.client.smithy.generators.config - -import software.amazon.smithy.rust.codegen.client.smithy.ClientCodegenContext -import software.amazon.smithy.rust.codegen.client.smithy.generators.OperationCustomization -import software.amazon.smithy.rust.codegen.client.smithy.generators.OperationSection -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.writable -import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType - -fun timeSourceCustomization(codegenContext: ClientCodegenContext) = standardConfigParam( - ConfigParam( - "time_source", - RuntimeType.smithyAsync(codegenContext.runtimeConfig).resolve("time::SharedTimeSource").toSymbol(), - setterDocs = writable { docs("""Sets the time source used for this service""") }, - optional = false, - ), -) - -class TimeSourceOperationCustomization : OperationCustomization() { - override fun section(section: OperationSection): Writable { - return when (section) { - is OperationSection.MutateRequest -> writable { - rust( - """ - ${section.request}.properties_mut().insert(${section.config}.time_source.clone()); - """, - ) - } - - else -> emptySection - } - } -} From 3b1b71a1858dce4f387651a72679abb1097463ba Mon Sep 17 00:00:00 2001 From: Yuki Saito Date: Mon, 12 Jun 2023 10:42:09 -0500 Subject: [PATCH 03/15] Update tests to work with layer-backed service config --- .../rustsdk/CredentialProviderConfigTest.kt | 14 ++- .../HttpConnectorConfigCustomizationTest.kt | 15 ++- .../rustsdk/RegionProviderConfigTest.kt | 15 ++- .../rustsdk/SigV4SigningDecoratorTest.kt | 20 +++- .../testutil/TestConfigCustomization.kt | 77 +++++++++--- .../codegen/client/testutil/TestHelpers.kt | 4 + .../ResiliencyConfigCustomizationTest.kt | 2 +- .../ClientContextConfigCustomizationTest.kt | 62 +++++++--- ...empotencyTokenProviderCustomizationTest.kt | 47 +++++++- .../config/ServiceConfigGeneratorTest.kt | 110 ++++++++++++++---- .../rust/codegen/core/smithy/RuntimeType.kt | 1 + 11 files changed, 285 insertions(+), 82 deletions(-) diff --git a/aws/sdk-codegen/src/test/kotlin/software/amazon/smithy/rustsdk/CredentialProviderConfigTest.kt b/aws/sdk-codegen/src/test/kotlin/software/amazon/smithy/rustsdk/CredentialProviderConfigTest.kt index df26efdfec..df19f6f16b 100644 --- a/aws/sdk-codegen/src/test/kotlin/software/amazon/smithy/rustsdk/CredentialProviderConfigTest.kt +++ b/aws/sdk-codegen/src/test/kotlin/software/amazon/smithy/rustsdk/CredentialProviderConfigTest.kt @@ -5,12 +5,18 @@ package software.amazon.smithy.rustsdk -import org.junit.jupiter.api.Test +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.ValueSource +import software.amazon.smithy.rust.codegen.client.smithy.SmithyRuntimeMode import software.amazon.smithy.rust.codegen.client.testutil.validateConfigCustomizations +import software.amazon.smithy.rust.codegen.client.testutil.withSmithyRuntimeMode internal class CredentialProviderConfigTest { - @Test - fun `generates a valid config`() { - validateConfigCustomizations(CredentialProviderConfig(AwsTestRuntimeConfig)) + @ParameterizedTest + @ValueSource(strings = ["middleware", "orchestrator"]) + fun `generates a valid config`(smithyRuntimeModeStr: String) { + val smithyRuntimeMode = SmithyRuntimeMode.fromString(smithyRuntimeModeStr) + val codegenContext = awsTestCodegenContext().withSmithyRuntimeMode(smithyRuntimeMode) + validateConfigCustomizations(codegenContext, CredentialProviderConfig(codegenContext.runtimeConfig)) } } diff --git a/aws/sdk-codegen/src/test/kotlin/software/amazon/smithy/rustsdk/HttpConnectorConfigCustomizationTest.kt b/aws/sdk-codegen/src/test/kotlin/software/amazon/smithy/rustsdk/HttpConnectorConfigCustomizationTest.kt index b97952e002..ca5e087b96 100644 --- a/aws/sdk-codegen/src/test/kotlin/software/amazon/smithy/rustsdk/HttpConnectorConfigCustomizationTest.kt +++ b/aws/sdk-codegen/src/test/kotlin/software/amazon/smithy/rustsdk/HttpConnectorConfigCustomizationTest.kt @@ -5,15 +5,20 @@ package software.amazon.smithy.rustsdk -import org.junit.jupiter.api.Test +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.ValueSource +import software.amazon.smithy.rust.codegen.client.smithy.SmithyRuntimeMode import software.amazon.smithy.rust.codegen.client.testutil.validateConfigCustomizations +import software.amazon.smithy.rust.codegen.client.testutil.withSmithyRuntimeMode import software.amazon.smithy.rust.codegen.core.testutil.TestWorkspace class HttpConnectorConfigCustomizationTest { - @Test - fun `generates a valid config`() { + @ParameterizedTest + @ValueSource(strings = ["middleware", "orchestrator"]) + fun `generates a valid config`(smithyRuntimeModeStr: String) { val project = TestWorkspace.testProject() - val codegenContext = awsTestCodegenContext() - validateConfigCustomizations(HttpConnectorConfigCustomization(codegenContext), project) + val smithyRuntimeMode = SmithyRuntimeMode.fromString(smithyRuntimeModeStr) + val codegenContext = awsTestCodegenContext().withSmithyRuntimeMode(smithyRuntimeMode) + validateConfigCustomizations(codegenContext, HttpConnectorConfigCustomization(codegenContext), project) } } diff --git a/aws/sdk-codegen/src/test/kotlin/software/amazon/smithy/rustsdk/RegionProviderConfigTest.kt b/aws/sdk-codegen/src/test/kotlin/software/amazon/smithy/rustsdk/RegionProviderConfigTest.kt index 9d2e865a64..1160f322ef 100644 --- a/aws/sdk-codegen/src/test/kotlin/software/amazon/smithy/rustsdk/RegionProviderConfigTest.kt +++ b/aws/sdk-codegen/src/test/kotlin/software/amazon/smithy/rustsdk/RegionProviderConfigTest.kt @@ -5,22 +5,27 @@ package software.amazon.smithy.rustsdk -import org.junit.jupiter.api.Test +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.ValueSource +import software.amazon.smithy.rust.codegen.client.smithy.SmithyRuntimeMode import software.amazon.smithy.rust.codegen.client.testutil.testClientRustSettings import software.amazon.smithy.rust.codegen.client.testutil.validateConfigCustomizations +import software.amazon.smithy.rust.codegen.client.testutil.withSmithyRuntimeMode import software.amazon.smithy.rust.codegen.core.testutil.TestWorkspace import software.amazon.smithy.rust.codegen.core.testutil.rustSettings internal class RegionProviderConfigTest { - @Test - fun `generates a valid config`() { + @ParameterizedTest + @ValueSource(strings = ["middleware", "orchestrator"]) + fun `generates a valid config`(smithyRuntimeModeStr: String) { val project = TestWorkspace.testProject() + val smithyRuntimeMode = SmithyRuntimeMode.fromString(smithyRuntimeModeStr) val codegenContext = awsTestCodegenContext( settings = testClientRustSettings( moduleName = project.rustSettings().moduleName, runtimeConfig = AwsTestRuntimeConfig, ), - ) - validateConfigCustomizations(RegionProviderConfig(codegenContext), project) + ).withSmithyRuntimeMode(smithyRuntimeMode) + validateConfigCustomizations(codegenContext, RegionProviderConfig(codegenContext), project) } } diff --git a/aws/sdk-codegen/src/test/kotlin/software/amazon/smithy/rustsdk/SigV4SigningDecoratorTest.kt b/aws/sdk-codegen/src/test/kotlin/software/amazon/smithy/rustsdk/SigV4SigningDecoratorTest.kt index 71bd5eaf6c..68a6610180 100644 --- a/aws/sdk-codegen/src/test/kotlin/software/amazon/smithy/rustsdk/SigV4SigningDecoratorTest.kt +++ b/aws/sdk-codegen/src/test/kotlin/software/amazon/smithy/rustsdk/SigV4SigningDecoratorTest.kt @@ -5,19 +5,31 @@ package software.amazon.smithy.rustsdk -import org.junit.jupiter.api.Test +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.ValueSource import software.amazon.smithy.aws.traits.auth.SigV4Trait +import software.amazon.smithy.rust.codegen.client.smithy.SmithyRuntimeMode import software.amazon.smithy.rust.codegen.client.testutil.stubConfigProject +import software.amazon.smithy.rust.codegen.client.testutil.testClientRustSettings +import software.amazon.smithy.rust.codegen.client.testutil.withSmithyRuntimeMode import software.amazon.smithy.rust.codegen.core.testutil.TestWorkspace import software.amazon.smithy.rust.codegen.core.testutil.compileAndTest import software.amazon.smithy.rust.codegen.core.testutil.unitTest internal class SigV4SigningDecoratorTest { - @Test - fun `generates a valid config`() { + @ParameterizedTest + @ValueSource(strings = ["middleware", "orchestrator"]) + fun `generates a valid config`(smithyRuntimeModeStr: String) { + val smithyRuntimeMode = SmithyRuntimeMode.fromString(smithyRuntimeModeStr) + val codegenContext = awsTestCodegenContext( + settings = testClientRustSettings( + runtimeConfig = AwsTestRuntimeConfig, + ), + ).withSmithyRuntimeMode(smithyRuntimeMode) val project = stubConfigProject( + codegenContext, SigV4SigningConfig( - AwsTestRuntimeConfig, + codegenContext.runtimeConfig, true, SigV4Trait.builder().name("test-service").build(), ), diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/testutil/TestConfigCustomization.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/testutil/TestConfigCustomization.kt index cb06688225..d45a2300ee 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/testutil/TestConfigCustomization.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/testutil/TestConfigCustomization.kt @@ -5,35 +5,61 @@ package software.amazon.smithy.rust.codegen.client.testutil +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.generators.config.ConfigCustomization import software.amazon.smithy.rust.codegen.client.smithy.generators.config.ServiceConfig import software.amazon.smithy.rust.codegen.client.smithy.generators.config.ServiceConfigGenerator +import software.amazon.smithy.rust.codegen.client.smithy.generators.config.configParamNewtype 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.RuntimeType import software.amazon.smithy.rust.codegen.core.testutil.TestWorkspace import software.amazon.smithy.rust.codegen.core.testutil.TestWriterDelegator import software.amazon.smithy.rust.codegen.core.testutil.compileAndTest import software.amazon.smithy.rust.codegen.core.testutil.unitTest +import software.amazon.smithy.rust.codegen.core.util.toPascalCase /** * Test helper to produce a valid config customization to test that a [ConfigCustomization] can be used in conjunction * with other [ConfigCustomization]s. */ -fun stubConfigCustomization(name: String): ConfigCustomization { +fun stubConfigCustomization(name: String, codegenContext: ClientCodegenContext): ConfigCustomization { return object : ConfigCustomization() { override fun section(section: ServiceConfig): Writable = writable { when (section) { - ServiceConfig.ConfigStruct -> rust("_$name: u64,") - ServiceConfig.ConfigImpl -> rust( - """ - ##[allow(missing_docs)] - pub fn $name(&self) -> u64 { - self._$name + ServiceConfig.ConfigStruct -> { + if (codegenContext.smithyRuntimeMode.defaultToMiddleware) { + rust("_$name: u64,") } - """, - ) + } + ServiceConfig.ConfigImpl -> { + if (codegenContext.smithyRuntimeMode.defaultToOrchestrator) { + rustTemplate( + """ + ##[allow(missing_docs)] + pub fn $name(&self) -> u64 { + self.inner.load::<#{T}>().map(|u| u.0).unwrap() + } + """, + "T" to configParamNewtype( + "_$name".toPascalCase(), RuntimeType.U64.toSymbol(), + codegenContext.runtimeConfig, + ), + ) + } else { + rust( + """ + ##[allow(missing_docs)] + pub fn $name(&self) -> u64 { + self._$name + } + """, + ) + } + } ServiceConfig.BuilderStruct -> rust("_$name: Option,") ServiceConfig.BuilderImpl -> rust( """ @@ -44,11 +70,25 @@ fun stubConfigCustomization(name: String): ConfigCustomization { } """, ) - ServiceConfig.BuilderBuild -> rust( - """ - _$name: self._$name.unwrap_or(123), - """, - ) + ServiceConfig.BuilderBuild -> { + if (codegenContext.smithyRuntimeMode.defaultToOrchestrator) { + rustTemplate( + """ + layer.store_or_unset(self._$name.map(#{T})); + """, + "T" to configParamNewtype( + "_$name".toPascalCase(), RuntimeType.U64.toSymbol(), + codegenContext.runtimeConfig, + ), + ) + } else { + rust( + """ + _$name: self._$name.unwrap_or(123), + """, + ) + } + } else -> emptySection } } @@ -62,18 +102,19 @@ fun stubConfigCustomization(name: String): ConfigCustomization { * */ @Suppress("NAME_SHADOWING") fun validateConfigCustomizations( + codegenContext: ClientCodegenContext, customization: ConfigCustomization, project: TestWriterDelegator? = null, ): TestWriterDelegator { val project = project ?: TestWorkspace.testProject() - stubConfigProject(customization, project) + stubConfigProject(codegenContext, customization, project) project.compileAndTest() return project } -fun stubConfigProject(customization: ConfigCustomization, project: TestWriterDelegator): TestWriterDelegator { - val customizations = listOf(stubConfigCustomization("a")) + customization + stubConfigCustomization("b") - val generator = ServiceConfigGenerator(customizations = customizations.toList()) +fun stubConfigProject(codegenContext: ClientCodegenContext, customization: ConfigCustomization, project: TestWriterDelegator): TestWriterDelegator { + val customizations = listOf(stubConfigCustomization("a", codegenContext)) + customization + stubConfigCustomization("b", codegenContext) + val generator = ServiceConfigGenerator(codegenContext, customizations = customizations.toList()) project.withModule(ClientRustModule.Config) { generator.render(this) unitTest( diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/testutil/TestHelpers.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/testutil/TestHelpers.kt index 1d2384b4a0..2e8dff72bc 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/testutil/TestHelpers.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/testutil/TestHelpers.kt @@ -15,6 +15,7 @@ import software.amazon.smithy.rust.codegen.client.smithy.ClientCodegenContext import software.amazon.smithy.rust.codegen.client.smithy.ClientModuleProvider import software.amazon.smithy.rust.codegen.client.smithy.ClientRustSettings import software.amazon.smithy.rust.codegen.client.smithy.RustClientCodegenPlugin +import software.amazon.smithy.rust.codegen.client.smithy.SmithyRuntimeMode import software.amazon.smithy.rust.codegen.client.smithy.customize.ClientCodegenDecorator import software.amazon.smithy.rust.codegen.client.smithy.customize.CombinedClientCodegenDecorator import software.amazon.smithy.rust.codegen.core.smithy.RuntimeConfig @@ -89,6 +90,9 @@ fun testClientCodegenContext( rootDecorator ?: CombinedClientCodegenDecorator(emptyList()), ) +fun ClientCodegenContext.withSmithyRuntimeMode(smithyRuntimeMode: SmithyRuntimeMode): ClientCodegenContext = + copy(settings = settings.copy(codegenConfig = settings.codegenConfig.copy(enableNewSmithyRuntime = smithyRuntimeMode))) + fun TestWriterDelegator.clientRustSettings() = testClientRustSettings( service = ShapeId.from("fake#Fake"), diff --git a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/ResiliencyConfigCustomizationTest.kt b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/ResiliencyConfigCustomizationTest.kt index 6ebc6ad759..4f9c1e23e3 100644 --- a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/ResiliencyConfigCustomizationTest.kt +++ b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/ResiliencyConfigCustomizationTest.kt @@ -39,7 +39,7 @@ internal class ResiliencyConfigCustomizationTest { val project = TestWorkspace.testProject(model, ClientCodegenConfig()) val codegenContext = testClientCodegenContext(model, settings = project.clientRustSettings()) - stubConfigProject(ResiliencyConfigCustomization(codegenContext), project) + stubConfigProject(codegenContext, ResiliencyConfigCustomization(codegenContext), project) ResiliencyReExportCustomization(codegenContext.runtimeConfig).extras(project) project.compileAndTest() } diff --git a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/endpoint/ClientContextConfigCustomizationTest.kt b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/endpoint/ClientContextConfigCustomizationTest.kt index 32cbbddeb4..509a86e845 100644 --- a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/endpoint/ClientContextConfigCustomizationTest.kt +++ b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/endpoint/ClientContextConfigCustomizationTest.kt @@ -5,9 +5,12 @@ package software.amazon.smithy.rust.codegen.client.smithy.endpoint -import org.junit.jupiter.api.Test +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.ValueSource +import software.amazon.smithy.rust.codegen.client.smithy.SmithyRuntimeMode import software.amazon.smithy.rust.codegen.client.testutil.testClientCodegenContext import software.amazon.smithy.rust.codegen.client.testutil.validateConfigCustomizations +import software.amazon.smithy.rust.codegen.client.testutil.withSmithyRuntimeMode import software.amazon.smithy.rust.codegen.core.rustlang.rust import software.amazon.smithy.rust.codegen.core.testutil.TestWorkspace import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel @@ -29,28 +32,51 @@ class ClientContextConfigCustomizationTest { service TestService { operations: [] } """.asSmithyModel() - @Test - fun `client params generate a valid customization`() { + @ParameterizedTest + @ValueSource(strings = ["middleware", "orchestrator"]) + fun `client params generate a valid customization`(smithyRuntimeModeStr: String) { val project = TestWorkspace.testProject() + val smithyRuntimeMode = SmithyRuntimeMode.fromString(smithyRuntimeModeStr) project.unitTest { - rust( - """ - let conf = crate::Config::builder().a_string_param("hello!").a_bool_param(true).build(); - assert_eq!(conf.a_string_param.unwrap(), "hello!"); - assert_eq!(conf.a_bool_param, Some(true)); - """, - ) + if (smithyRuntimeMode.defaultToOrchestrator) { + rust( + """ + let conf = crate::Config::builder().a_string_param("hello!").a_bool_param(true).build(); + assert_eq!(conf.a_string_param().unwrap(), "hello!"); + assert_eq!(conf.a_bool_param(), Some(true)); + """, + ) + } else { + rust( + """ + let conf = crate::Config::builder().a_string_param("hello!").a_bool_param(true).build(); + assert_eq!(conf.a_string_param.unwrap(), "hello!"); + assert_eq!(conf.a_bool_param, Some(true)); + """, + ) + } } // unset fields project.unitTest { - rust( - """ - let conf = crate::Config::builder().a_string_param("hello!").build(); - assert_eq!(conf.a_string_param.unwrap(), "hello!"); - assert_eq!(conf.a_bool_param, None); - """, - ) + if (smithyRuntimeMode.defaultToOrchestrator) { + rust( + """ + let conf = crate::Config::builder().a_string_param("hello!").build(); + assert_eq!(conf.a_string_param().unwrap(), "hello!"); + assert_eq!(conf.a_bool_param(), None); + """, + ) + } else { + rust( + """ + let conf = crate::Config::builder().a_string_param("hello!").build(); + assert_eq!(conf.a_string_param.unwrap(), "hello!"); + assert_eq!(conf.a_bool_param, None); + """, + ) + } } - validateConfigCustomizations(ClientContextConfigCustomization(testClientCodegenContext(model)), project) + val context = testClientCodegenContext(model).withSmithyRuntimeMode(smithyRuntimeMode) + validateConfigCustomizations(context, ClientContextConfigCustomization(context), project) } } diff --git a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/IdempotencyTokenProviderCustomizationTest.kt b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/IdempotencyTokenProviderCustomizationTest.kt index cf65b897f4..a0e715d3e4 100644 --- a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/IdempotencyTokenProviderCustomizationTest.kt +++ b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/IdempotencyTokenProviderCustomizationTest.kt @@ -5,12 +5,51 @@ package software.amazon.smithy.rust.codegen.client.smithy.generators.config -import org.junit.jupiter.api.Test +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.ValueSource +import software.amazon.smithy.rust.codegen.client.smithy.ClientRustModule +import software.amazon.smithy.rust.codegen.client.smithy.SmithyRuntimeMode +import software.amazon.smithy.rust.codegen.client.testutil.testClientCodegenContext +import software.amazon.smithy.rust.codegen.client.testutil.testSymbolProvider import software.amazon.smithy.rust.codegen.client.testutil.validateConfigCustomizations +import software.amazon.smithy.rust.codegen.client.testutil.withSmithyRuntimeMode +import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType +import software.amazon.smithy.rust.codegen.core.testutil.TestWorkspace +import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel class IdempotencyTokenProviderCustomizationTest { - @Test - fun `generates a valid config`() { - validateConfigCustomizations(IdempotencyTokenProviderCustomization()) + @ParameterizedTest + @ValueSource(strings = ["middleware", "orchestrator"]) + fun `generates a valid config`(smithyRuntimeModeStr: String) { + val smithyRuntimeMode = SmithyRuntimeMode.fromString(smithyRuntimeModeStr) + val model = "namespace test".asSmithyModel() + val codegenContext = testClientCodegenContext(model).withSmithyRuntimeMode(smithyRuntimeMode) + val symbolProvider = testSymbolProvider(model) + val project = TestWorkspace.testProject(symbolProvider) + // The following is a workaround for the middleware mode, and without this, the synthesized test crate would + // fail to compile. `IdempotencyTokenProvider` is a smithy inlineable and depends on `aws_smithy_types` crate + // to use the `Storable` trait (there is no smithy runtime mode when handwriting Rust source files since that's + // a codegen concept). When that inlinable is brought in during testing, the orchestrator mode is ok because a + // service config already depends on the `aws_smithy_types` crate, causing it to appear in `Cargo.toml` of the + // synthesized test crate. However, a service config in the middleware mode does not depend on the + // `aws_smithy_types` crate, so `Cargo.toml` of the synthesized test crate will not include it, causing the + // inlinable fail to compile. To work around it, the code below will force the `aws_smithy_types` to appear in + // `Cargo.toml`. + project.withModule(ClientRustModule.Config) { + if (smithyRuntimeMode.defaultToMiddleware) { + rustTemplate( + """ + struct DummyToAddDependencyOnSmithyTypes(#{Layer}); + """, + "Layer" to RuntimeType.smithyTypes(codegenContext.runtimeConfig).resolve("config_bag::Layer"), + ) + } + } + validateConfigCustomizations( + codegenContext, + IdempotencyTokenProviderCustomization(codegenContext.smithyRuntimeMode), + project, + ) } } diff --git a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/ServiceConfigGeneratorTest.kt b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/ServiceConfigGeneratorTest.kt index 2aaa3e21dd..dd8c402859 100644 --- a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/ServiceConfigGeneratorTest.kt +++ b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/ServiceConfigGeneratorTest.kt @@ -7,18 +7,27 @@ package software.amazon.smithy.rust.codegen.client.smithy.generators.config import io.kotest.matchers.shouldBe import org.junit.jupiter.api.Test +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.ValueSource import software.amazon.smithy.model.shapes.ServiceShape +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.SmithyRuntimeMode +import software.amazon.smithy.rust.codegen.client.testutil.testClientCodegenContext import software.amazon.smithy.rust.codegen.client.testutil.testSymbolProvider +import software.amazon.smithy.rust.codegen.client.testutil.withSmithyRuntimeMode 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.RuntimeType import software.amazon.smithy.rust.codegen.core.smithy.customize.NamedCustomization import software.amazon.smithy.rust.codegen.core.testutil.TestWorkspace import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel import software.amazon.smithy.rust.codegen.core.testutil.compileAndTest import software.amazon.smithy.rust.codegen.core.testutil.unitTest import software.amazon.smithy.rust.codegen.core.util.lookup +import software.amazon.smithy.rust.codegen.core.util.toPascalCase internal class ServiceConfigGeneratorTest { @Test @@ -76,45 +85,100 @@ internal class ServiceConfigGeneratorTest { model.lookup("com.example#ResourceService").needsIdempotencyToken(model) shouldBe true } - @Test - fun `generate customizations as specified`() { - class ServiceCustomizer : NamedCustomization() { + @ParameterizedTest + @ValueSource(strings = ["middleware", "orchestrator"]) + fun `generate customizations as specified`(smithyRuntimeModeStr: String) { + class ServiceCustomizer(private val codegenContext: ClientCodegenContext) : + NamedCustomization() { + private val runtimeMode = codegenContext.smithyRuntimeMode + override fun section(section: ServiceConfig): Writable { return when (section) { ServiceConfig.ConfigStructAdditionalDocs -> emptySection - ServiceConfig.ConfigStruct -> writable { rust("config_field: u64,") } + ServiceConfig.ConfigStruct -> writable { + if (runtimeMode.defaultToMiddleware) { + rust("config_field: u64,") + } + } + ServiceConfig.ConfigImpl -> writable { - rust( - """ - pub fn config_field(&self) -> u64 { - self.config_field - } - """, - ) + if (runtimeMode.defaultToOrchestrator) { + rustTemplate( + """ + ##[allow(missing_docs)] + pub fn config_field(&self) -> u64 { + self.inner.load::<#{T}>().map(|u| u.0).unwrap() + } + """, + "T" to configParamNewtype( + "config_field".toPascalCase(), RuntimeType.U64.toSymbol(), + codegenContext.runtimeConfig, + ), + ) + } else { + rust( + """ + ##[allow(missing_docs)] + pub fn config_field(&self) -> u64 { + self.config_field + } + """, + ) + } } + ServiceConfig.BuilderStruct -> writable { rust("config_field: Option") } ServiceConfig.BuilderImpl -> emptySection ServiceConfig.BuilderBuild -> writable { - rust("config_field: self.config_field.unwrap_or_default(),") + if (runtimeMode.defaultToOrchestrator) { + rustTemplate( + """ + layer.store_or_unset(self.config_field.map(#{T})); + """, + "T" to configParamNewtype( + "config_field".toPascalCase(), RuntimeType.U64.toSymbol(), + codegenContext.runtimeConfig, + ), + ) + } else { + rust("config_field: self.config_field.unwrap_or_default(),") + } } + else -> emptySection } } } - val sut = ServiceConfigGenerator(listOf(ServiceCustomizer())) - val symbolProvider = testSymbolProvider("namespace empty".asSmithyModel()) + + val model = "namespace empty".asSmithyModel() + val smithyRuntimeMode = SmithyRuntimeMode.fromString(smithyRuntimeModeStr) + val codegenContext = testClientCodegenContext(model).withSmithyRuntimeMode(smithyRuntimeMode) + val sut = ServiceConfigGenerator(codegenContext, listOf(ServiceCustomizer(codegenContext))) + val symbolProvider = testSymbolProvider(model) val project = TestWorkspace.testProject(symbolProvider) project.withModule(ClientRustModule.Config) { sut.render(this) - unitTest( - "set_config_fields", - """ - let mut builder = Config::builder(); - builder.config_field = Some(99); - let config = builder.build(); - assert_eq!(config.config_field, 99); - """, - ) + if (smithyRuntimeMode.defaultToOrchestrator) { + unitTest( + "set_config_fields", + """ + let mut builder = Config::builder(); + builder.config_field = Some(99); + let config = builder.build(); + assert_eq!(config.config_field(), 99); + """, + ) + } else { + unitTest( + "set_config_fields", + """ + let mut builder = Config::builder(); + builder.config_field = Some(99); + let config = builder.build(); + assert_eq!(config.config_field, 99); + """, + ) + } } project.compileAndTest() } diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/RuntimeType.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/RuntimeType.kt index 6e5b5ee8ff..c8ca035401 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/RuntimeType.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/RuntimeType.kt @@ -274,6 +274,7 @@ data class RuntimeType(val path: String, val dependency: RustDependency? = null) val String = std.resolve("string::String") val Sync = std.resolve("marker::Sync") val TryFrom = stdConvert.resolve("TryFrom") + val U64 = std.resolve("primitive::u64") val Vec = std.resolve("vec::Vec") // external cargo dependency types From 794f063c7cd7a0d38c2e140d5ee53b3ca70a4126 Mon Sep 17 00:00:00 2001 From: Yuki Saito Date: Mon, 12 Jun 2023 14:03:43 -0500 Subject: [PATCH 04/15] Use inlineable in test other than `IdempotencyToken` This commit modifies a Kotlin test for verifying dependencies brought in by an inlineable module. Prior to the commit, the test used an idempotency token, but with smithy-rs#2762, `IdempotencyTokenProvider` will bring in `aws_smithy_types` due to that provider being defined in an inlineable module. The test needed to be bifurcated between middleware and orchestrator but that was not possible because the test was in codegen-core and bifurcation was only possible in codegen-client. For this reason, this commit switches the test to use another inlineable module. --- .../core/rustlang/InlineDependencyTest.kt | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/InlineDependencyTest.kt b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/InlineDependencyTest.kt index 9d613f558f..4e341c769f 100644 --- a/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/InlineDependencyTest.kt +++ b/codegen-core/src/test/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/InlineDependencyTest.kt @@ -10,6 +10,7 @@ import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldNotBe import org.junit.jupiter.api.Test import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType +import software.amazon.smithy.rust.codegen.core.testutil.TestRuntimeConfig import software.amazon.smithy.rust.codegen.core.testutil.TestWorkspace import software.amazon.smithy.rust.codegen.core.testutil.compileAndTest import software.amazon.smithy.rust.codegen.core.testutil.unitTest @@ -32,20 +33,23 @@ internal class InlineDependencyTest { @Test fun `locate dependencies from the inlineable module`() { - val dep = InlineDependency.idempotencyToken() + val runtimeConfig = TestRuntimeConfig + val dep = InlineDependency.serializationSettings(runtimeConfig) val testProject = TestWorkspace.testProject() testProject.lib { rustTemplate( """ + ##[test] - fn idempotency_works() { - use #{idempotency}::uuid_v4; - let res = uuid_v4(0); - assert_eq!(res, "00000000-0000-4000-8000-000000000000"); + fn header_serialization_settings_can_be_constructed() { + use #{serialization_settings}::HeaderSerializationSettings; + use #{aws_smithy_http}::header::set_request_header_if_absent; + let _settings = HeaderSerializationSettings::default(); } """, - "idempotency" to dep.toType(), + "serialization_settings" to dep.toType(), + "aws_smithy_http" to RuntimeType.smithyHttp(runtimeConfig), ) } testProject.compileAndTest() From f98f99dac7f1bc2dac71c730772c0d1c87d439d7 Mon Sep 17 00:00:00 2001 From: ysaito1001 Date: Tue, 13 Jun 2023 10:23:07 -0500 Subject: [PATCH 05/15] Update codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/ServiceConfigGeneratorTest.kt Co-authored-by: Zelda Hessler --- .../smithy/generators/config/ServiceConfigGeneratorTest.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/ServiceConfigGeneratorTest.kt b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/ServiceConfigGeneratorTest.kt index dd8c402859..53dc2f5eb6 100644 --- a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/ServiceConfigGeneratorTest.kt +++ b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/ServiceConfigGeneratorTest.kt @@ -132,9 +132,7 @@ internal class ServiceConfigGeneratorTest { ServiceConfig.BuilderBuild -> writable { if (runtimeMode.defaultToOrchestrator) { rustTemplate( - """ - layer.store_or_unset(self.config_field.map(#{T})); - """, + "layer.store_or_unset(self.config_field.map(#{T}));", "T" to configParamNewtype( "config_field".toPascalCase(), RuntimeType.U64.toSymbol(), codegenContext.runtimeConfig, From 7333e700b4769d070f784a32852f73d59043443c Mon Sep 17 00:00:00 2001 From: Yuki Saito Date: Tue, 13 Jun 2023 16:53:08 -0500 Subject: [PATCH 06/15] Remove unnecessary bifurcation for accessing time_source This commit addresses https://github.com/awslabs/smithy-rs/pull/2762#discussion_r1228153647 --- .../customize/timestream/TimestreamDecorator.kt | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/timestream/TimestreamDecorator.kt b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/timestream/TimestreamDecorator.kt index 4b4c22e387..9d241ffe46 100644 --- a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/timestream/TimestreamDecorator.kt +++ b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/timestream/TimestreamDecorator.kt @@ -11,10 +11,8 @@ import software.amazon.smithy.rust.codegen.client.smithy.endpoint.Types import software.amazon.smithy.rust.codegen.core.rustlang.CargoDependency import software.amazon.smithy.rust.codegen.core.rustlang.DependencyScope import software.amazon.smithy.rust.codegen.core.rustlang.Visibility -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.toType -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.smithy.RustCrate @@ -65,7 +63,7 @@ class TimestreamDecorator : ClientCodegenDecorator { #{ResolveEndpointError}::from_source("failed to call describe_endpoints", e) })?; let endpoint = describe_endpoints.endpoints().unwrap().get(0).unwrap(); - let expiry = client.conf().#{time_source}.now() + #{Duration}::from_secs(endpoint.cache_period_in_minutes() as u64 * 60); + let expiry = client.conf().time_source().now() + #{Duration}::from_secs(endpoint.cache_period_in_minutes() as u64 * 60); Ok(( #{Endpoint}::builder() .url(format!("https://{}", endpoint.address().unwrap())) @@ -81,7 +79,7 @@ class TimestreamDecorator : ClientCodegenDecorator { pub async fn enable_endpoint_discovery(self) -> #{Result}<(Self, #{endpoint_discovery}::ReloadEndpoint), #{ResolveEndpointError}> { let mut new_conf = self.conf().clone(); let sleep = self.conf().sleep_impl().expect("sleep impl must be provided"); - let time = self.conf().#{time_source}.clone(); + let time = self.conf().time_source().clone(); let (resolver, reloader) = #{endpoint_discovery}::create_cache( move || { let client = self.clone(); @@ -97,13 +95,6 @@ class TimestreamDecorator : ClientCodegenDecorator { } """, "endpoint_discovery" to endpointDiscovery.toType(), - "time_source" to writable { - if (runtimeMode.defaultToOrchestrator) { - rust("time_source()") - } else { - rust("time_source") - } - }, "SystemTime" to RuntimeType.std.resolve("time::SystemTime"), "Duration" to RuntimeType.std.resolve("time::Duration"), "SharedEndpointResolver" to RuntimeType.smithyHttp(codegenContext.runtimeConfig) From b988ad96ee91feaabaa8516c3cf0f4d592c4ff2a Mon Sep 17 00:00:00 2001 From: Yuki Saito Date: Tue, 13 Jun 2023 19:21:04 -0500 Subject: [PATCH 07/15] Leave identity_resolvers and interceptors as fields This commit addresses https://github.com/awslabs/smithy-rs/pull/2762#discussion_r1228158044 --- .../customizations/HttpAuthDecorator.kt | 42 +++++++------------ .../InterceptorConfigCustomization.kt | 15 ++++--- .../config/ServiceConfigGenerator.kt | 19 ++++++--- 3 files changed, 37 insertions(+), 39 deletions(-) diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/HttpAuthDecorator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/HttpAuthDecorator.kt index c8b8a55129..67e49d0e6e 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/HttpAuthDecorator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/HttpAuthDecorator.kt @@ -325,41 +325,29 @@ private class HttpAuthConfigCustomization( } is ServiceConfig.BuilderBuild -> { - if (runtimeMode.defaultToOrchestrator) { - rust(" layer.store_put(self.identity_resolvers);") - } else { + if (runtimeMode.defaultToMiddleware) { rust("identity_resolvers: self.identity_resolvers,") } } is ServiceConfig.ConfigStruct -> { - if (runtimeMode.defaultToMiddleware) { - rustTemplate("identity_resolvers: #{IdentityResolvers},", *codegenScope) - } + rustTemplate("identity_resolvers: #{IdentityResolvers},", *codegenScope) } is ServiceConfig.ConfigImpl -> { - if (runtimeMode.defaultToOrchestrator) { - rustTemplate( - """ - /// Returns the identity resolvers. - pub fn identity_resolvers(&self) -> &#{IdentityResolvers} { - self.inner.load::<#{IdentityResolvers}>().expect("Identity resolvers should be set") - } - """, - *codegenScope, - ) - } else { - rustTemplate( - """ - /// Returns the identity resolvers. - pub fn identity_resolvers(&self) -> &#{IdentityResolvers} { - &self.identity_resolvers - } - """, - *codegenScope, - ) - } + rustTemplate( + """ + /// Returns the identity resolvers. + pub fn identity_resolvers(&self) -> &#{IdentityResolvers} { + &self.identity_resolvers + } + """, + *codegenScope, + ) + } + + is ServiceConfig.BuilderBuildExtras -> { + rust("identity_resolvers: self.identity_resolvers,") } else -> {} diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/InterceptorConfigCustomization.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/InterceptorConfigCustomization.kt index 4aceed0b81..104ec09490 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/InterceptorConfigCustomization.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/InterceptorConfigCustomization.kt @@ -25,11 +25,14 @@ class InterceptorConfigCustomization(codegenContext: CodegenContext) : ConfigCus override fun section(section: ServiceConfig) = writable { when (section) { + ServiceConfig.ConfigStruct -> rustTemplate( + "pub(crate) interceptors: Vec<#{SharedInterceptor}>,", + *codegenScope, + ) + ServiceConfig.BuilderStruct -> rustTemplate( - """ - interceptors: Vec<#{SharedInterceptor}>, - """, + "interceptors: Vec<#{SharedInterceptor}>,", *codegenScope, ) @@ -39,7 +42,7 @@ class InterceptorConfigCustomization(codegenContext: CodegenContext) : ConfigCus ##[doc(hidden)] /// Returns interceptors currently registered by the user. pub fn interceptors(&self) -> impl Iterator + '_ { - self.inner.load::<#{SharedInterceptor}>() + self.interceptors.iter() } """, *codegenScope, @@ -164,14 +167,14 @@ class InterceptorConfigCustomization(codegenContext: CodegenContext) : ConfigCus *codegenScope, ) - ServiceConfig.BuilderBuild -> rust("self.interceptors.into_iter().for_each(|i| { layer.store_append(i); });") - is ServiceConfig.RuntimePluginInterceptors -> rust( """ ${section.interceptors}.extend(self.interceptors.iter().cloned()); """, ) + is ServiceConfig.BuilderBuildExtras -> rust("interceptors: self.interceptors,") + else -> emptySection } } diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/ServiceConfigGenerator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/ServiceConfigGenerator.kt index b1cd276e66..bf1fe50bb5 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/ServiceConfigGenerator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/ServiceConfigGenerator.kt @@ -92,6 +92,14 @@ sealed class ServiceConfig(name: String) : Section(name) { */ object BuilderBuild : ServiceConfig("BuilderBuild") + // TODO(enableNewSmithyRuntime): This is temporary until config builder is backed by a CloneableLayer. + // It is needed because certain config fields appear explicitly regardless of the smithy runtime mode, e.g. + // interceptors. The [BuilderBuild] section is bifurcated depending on the runtime mode (in the orchestrator mode, + // storing a field into a frozen layer and in the middleware moving it into a corresponding service config field) + // so we need a different temporary section to always move a field from a builder to service config within the + // build method. + object BuilderBuildExtras : ServiceConfig("BuilderBuildExtras") + /** * A section for setting up a field to be used by RuntimePlugin */ @@ -409,13 +417,12 @@ class ServiceConfigGenerator( customizations.forEach { it.section(ServiceConfig.BuilderBuild)(this) } - rustTemplate( - """ - Config { - inner: layer.freeze(), + rustBlock("Config") { + customizations.forEach { + it.section(ServiceConfig.BuilderBuildExtras)(this) } - """, - ) + rust("inner: layer.freeze(),") + } } else { rustBlock("Config") { customizations.forEach { From 52a0d6e97f977c72aa92480c4e48f5fd066ac596 Mon Sep 17 00:00:00 2001 From: Yuki Saito Date: Tue, 13 Jun 2023 19:35:16 -0500 Subject: [PATCH 08/15] Avoid unsetting fields during the `build` method This commit addresses https://github.com/awslabs/smithy-rs/pull/2762#discussion_r1228156748 https://github.com/awslabs/smithy-rs/pull/2762#discussion_r1228159320 --- .../smithy/customizations/HttpConnectorConfigDecorator.kt | 2 +- .../smithy/customizations/ResiliencyConfigCustomization.kt | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/HttpConnectorConfigDecorator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/HttpConnectorConfigDecorator.kt index 8d1cb133ae..3fe3c56737 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/HttpConnectorConfigDecorator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/HttpConnectorConfigDecorator.kt @@ -162,7 +162,7 @@ private class HttpConnectorConfigCustomization( is ServiceConfig.BuilderBuild -> writable { if (runtimeMode.defaultToOrchestrator) { - rust("layer.store_or_unset(self.http_connector);") + rust("self.http_connector.map(|c| layer.store_put(c));") } else { rust("http_connector: self.http_connector,") } diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/ResiliencyConfigCustomization.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/ResiliencyConfigCustomization.kt index 5136a2cc38..44c91aa1de 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/ResiliencyConfigCustomization.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/ResiliencyConfigCustomization.kt @@ -248,9 +248,9 @@ class ResiliencyConfigCustomization(codegenContext: ClientCodegenContext) : Conf if (runtimeMode.defaultToOrchestrator) { rustTemplate( """ - layer.store_or_unset(self.retry_config); - layer.store_or_unset(self.sleep_impl.clone()); - layer.store_or_unset(self.timeout_config); + self.retry_config.map(|r| layer.store_put(r)); + self.sleep_impl.clone().map(|s| layer.store_put(s)); + self.timeout_config.map(|t| layer.store_put(t)); """, *codegenScope, ) From f7b96adde4f2d1907e1facdf411633245345d045 Mon Sep 17 00:00:00 2001 From: Yuki Saito Date: Tue, 13 Jun 2023 20:59:29 -0500 Subject: [PATCH 09/15] Update externl-types.toml based on the latest main --- aws/rust-runtime/aws-credential-types/external-types.toml | 6 +++--- aws/rust-runtime/aws-types/external-types.toml | 6 +++--- rust-runtime/aws-smithy-async/external-types.toml | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/aws/rust-runtime/aws-credential-types/external-types.toml b/aws/rust-runtime/aws-credential-types/external-types.toml index e5650b346c..e65c743b10 100644 --- a/aws/rust-runtime/aws-credential-types/external-types.toml +++ b/aws/rust-runtime/aws-credential-types/external-types.toml @@ -1,6 +1,6 @@ allowed_external_types = [ "aws_smithy_async::rt::sleep::SharedAsyncSleep", - "aws_smithy_types::config_bag::Storable", - "aws_smithy_types::config_bag::StoreReplace", - "aws_smithy_types::config_bag::Storer", + "aws_smithy_types::config_bag::storable::Storable", + "aws_smithy_types::config_bag::storable::StoreReplace", + "aws_smithy_types::config_bag::storable::Storer", ] diff --git a/aws/rust-runtime/aws-types/external-types.toml b/aws/rust-runtime/aws-types/external-types.toml index c14e24ee25..e43510d69e 100644 --- a/aws/rust-runtime/aws-types/external-types.toml +++ b/aws/rust-runtime/aws-types/external-types.toml @@ -9,9 +9,9 @@ allowed_external_types = [ "aws_smithy_http::endpoint::Endpoint", "aws_smithy_http::endpoint::EndpointPrefix", "aws_smithy_http::endpoint::error::InvalidEndpointError", - "aws_smithy_types::config_bag::Storable", - "aws_smithy_types::config_bag::StoreReplace", - "aws_smithy_types::config_bag::Storer", + "aws_smithy_types::config_bag::storable::Storable", + "aws_smithy_types::config_bag::storable::StoreReplace", + "aws_smithy_types::config_bag::storable::Storer", "aws_smithy_types::retry::RetryConfig", "aws_smithy_types::timeout::TimeoutConfig", "http::uri::Uri", diff --git a/rust-runtime/aws-smithy-async/external-types.toml b/rust-runtime/aws-smithy-async/external-types.toml index 67a89e03da..dee6e8bb30 100644 --- a/rust-runtime/aws-smithy-async/external-types.toml +++ b/rust-runtime/aws-smithy-async/external-types.toml @@ -1,7 +1,7 @@ allowed_external_types = [ - "aws_smithy_types::config_bag::Storable", - "aws_smithy_types::config_bag::StoreReplace", - "aws_smithy_types::config_bag::Storer", + "aws_smithy_types::config_bag::storable::Storable", + "aws_smithy_types::config_bag::storable::StoreReplace", + "aws_smithy_types::config_bag::storable::Storer", # TODO(https://github.com/awslabs/smithy-rs/issues/1193): Switch to AsyncIterator once standardized "futures_core::stream::Stream", From 303c90a17faff6179900f64523e2d0b8dd47669f Mon Sep 17 00:00:00 2001 From: Yuki Saito Date: Tue, 13 Jun 2023 21:09:19 -0500 Subject: [PATCH 10/15] Fix redundant-clone clippy warning --- .../smithy/rustsdk/customize/timestream/TimestreamDecorator.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/timestream/TimestreamDecorator.kt b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/timestream/TimestreamDecorator.kt index 9d241ffe46..c066562ac3 100644 --- a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/timestream/TimestreamDecorator.kt +++ b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/timestream/TimestreamDecorator.kt @@ -79,7 +79,7 @@ class TimestreamDecorator : ClientCodegenDecorator { pub async fn enable_endpoint_discovery(self) -> #{Result}<(Self, #{endpoint_discovery}::ReloadEndpoint), #{ResolveEndpointError}> { let mut new_conf = self.conf().clone(); let sleep = self.conf().sleep_impl().expect("sleep impl must be provided"); - let time = self.conf().time_source().clone(); + let time = self.conf().time_source(); let (resolver, reloader) = #{endpoint_discovery}::create_cache( move || { let client = self.clone(); From 7b9b56ac98a97252141ab6c5e453ab8460ba9cba Mon Sep 17 00:00:00 2001 From: Yuki Saito Date: Thu, 15 Jun 2023 12:20:26 -0500 Subject: [PATCH 11/15] Update service config and builder in `ApiKeyAuthDecorator` --- .../customizations/ApiKeyAuthDecorator.kt | 52 +++++++++++++------ 1 file changed, 37 insertions(+), 15 deletions(-) diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/ApiKeyAuthDecorator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/ApiKeyAuthDecorator.kt index a224915435..c1ed00adc5 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/ApiKeyAuthDecorator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/ApiKeyAuthDecorator.kt @@ -25,6 +25,7 @@ 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.util.letIf @@ -46,7 +47,7 @@ class ApiKeyAuthDecorator : ClientCodegenDecorator { baseCustomizations: List, ): List { return baseCustomizations.letIf(applies(codegenContext)) { customizations -> - customizations + ApiKeyConfigCustomization(codegenContext.runtimeConfig) + customizations + ApiKeyConfigCustomization(codegenContext) } } @@ -156,15 +157,18 @@ private class ApiKeyOperationCustomization(private val runtimeConfig: RuntimeCon } } -private class ApiKeyConfigCustomization(runtimeConfig: RuntimeConfig) : ConfigCustomization() { +private class ApiKeyConfigCustomization(codegenContext: ClientCodegenContext) : ConfigCustomization() { + val runtimeMode = codegenContext.smithyRuntimeMode + val runtimeConfig = codegenContext.runtimeConfig private val codegenScope = arrayOf( + *preludeScope, "ApiKey" to apiKey(runtimeConfig), ) override fun section(section: ServiceConfig): Writable = when (section) { is ServiceConfig.BuilderStruct -> writable { - rustTemplate("api_key: Option<#{ApiKey}>,", *codegenScope) + rustTemplate("api_key: #{Option}<#{ApiKey}>,", *codegenScope) } is ServiceConfig.BuilderImpl -> writable { rustTemplate( @@ -176,7 +180,7 @@ private class ApiKeyConfigCustomization(runtimeConfig: RuntimeConfig) : ConfigCu } /// Sets the API key that will be used by the client. - pub fn set_api_key(&mut self, api_key: Option<#{ApiKey}>) -> &mut Self { + pub fn set_api_key(&mut self, api_key: #{Option}<#{ApiKey}>) -> &mut Self { self.api_key = api_key; self } @@ -185,21 +189,39 @@ private class ApiKeyConfigCustomization(runtimeConfig: RuntimeConfig) : ConfigCu ) } is ServiceConfig.BuilderBuild -> writable { - rust("api_key: self.api_key,") + if (runtimeMode.defaultToOrchestrator) { + rust("layer.store_or_unset(self.api_key);") + } else { + rust("api_key: self.api_key,") + } } is ServiceConfig.ConfigStruct -> writable { - rustTemplate("api_key: Option<#{ApiKey}>,", *codegenScope) + if (runtimeMode.defaultToMiddleware) { + rustTemplate("api_key: #{Option}<#{ApiKey}>,", *codegenScope) + } } is ServiceConfig.ConfigImpl -> writable { - rustTemplate( - """ - /// Returns API key used by the client, if it was provided. - pub fn api_key(&self) -> Option<&#{ApiKey}> { - self.api_key.as_ref() - } - """, - *codegenScope, - ) + if (runtimeMode.defaultToOrchestrator) { + rustTemplate( + """ + /// Returns API key used by the client, if it was provided. + pub fn api_key(&self) -> #{Option}<&#{ApiKey}> { + self.inner.load::<#{ApiKey}>() + } + """, + *codegenScope, + ) + } else { + rustTemplate( + """ + /// Returns API key used by the client, if it was provided. + pub fn api_key(&self) -> #{Option}<&#{ApiKey}> { + self.api_key.as_ref() + } + """, + *codegenScope, + ) + } } else -> emptySection } From 89185fafa24a86b3114ffc27874d6d478cf92d26 Mon Sep 17 00:00:00 2001 From: Yuki Saito Date: Thu, 15 Jun 2023 15:51:31 -0500 Subject: [PATCH 12/15] Update `make_token` to `token_provider` This commit addresses https://github.com/awslabs/smithy-rs/pull/2762#discussion_r1231462878 --- .../IdempotencyTokenProviderCustomization.kt | 64 ++++--------------- 1 file changed, 13 insertions(+), 51 deletions(-) diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/IdempotencyTokenProviderCustomization.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/IdempotencyTokenProviderCustomization.kt index e29b5f7331..4b12aed8b6 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/IdempotencyTokenProviderCustomization.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/IdempotencyTokenProviderCustomization.kt @@ -14,7 +14,7 @@ import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.smithy.customize.NamedCustomization /** - * Add a `make_token` field to Service config. See below for the resulting generated code. + * Add a `token_provider` field to Service config. See below for the resulting generated code. */ class IdempotencyTokenProviderCustomization(private val runtimeMode: SmithyRuntimeMode) : NamedCustomization() { @@ -22,7 +22,7 @@ class IdempotencyTokenProviderCustomization(private val runtimeMode: SmithyRunti return when (section) { is ServiceConfig.ConfigStruct -> writable { if (runtimeMode.defaultToMiddleware) { - rust("pub (crate) make_token: #T::IdempotencyTokenProvider,", RuntimeType.IdempotencyToken) + rust("pub (crate) token_provider: #T::IdempotencyTokenProvider,", RuntimeType.IdempotencyToken) } } @@ -33,7 +33,7 @@ class IdempotencyTokenProviderCustomization(private val runtimeMode: SmithyRunti /// Returns a copy of the idempotency token provider. /// If a random token provider was configured, /// a newly-randomized token provider will be returned. - pub fn make_token(&self) -> #{IdempotencyTokenProvider} { + pub fn token_provider(&self) -> #{IdempotencyTokenProvider} { self.inner.load::<#{IdempotencyTokenProvider}>().expect("the idempotency provider should be set").clone() } """, @@ -45,8 +45,8 @@ class IdempotencyTokenProviderCustomization(private val runtimeMode: SmithyRunti /// Returns a copy of the idempotency token provider. /// If a random token provider was configured, /// a newly-randomized token provider will be returned. - pub fn make_token(&self) -> #T::IdempotencyTokenProvider { - self.make_token.clone() + pub fn token_provider(&self) -> #T::IdempotencyTokenProvider { + self.token_provider.clone() } """, RuntimeType.IdempotencyToken, @@ -55,21 +55,21 @@ class IdempotencyTokenProviderCustomization(private val runtimeMode: SmithyRunti } ServiceConfig.BuilderStruct -> writable { - rust("make_token: Option<#T::IdempotencyTokenProvider>,", RuntimeType.IdempotencyToken) + rust("token_provider: Option<#T::IdempotencyTokenProvider>,", RuntimeType.IdempotencyToken) } ServiceConfig.BuilderImpl -> writable { rustTemplate( """ /// Sets the idempotency token provider to use for service calls that require tokens. - pub fn make_token(mut self, make_token: impl Into<#{TokenProvider}>) -> Self { - self.set_make_token(Some(make_token.into())); + pub fn token_provider(mut self, token_provider: impl Into<#{TokenProvider}>) -> Self { + self.set_token_provider(Some(token_provider.into())); self } /// Sets the idempotency token provider to use for service calls that require tokens. - pub fn set_make_token(&mut self, make_token: Option<#{TokenProvider}>) -> &mut Self { - self.make_token = make_token; + pub fn set_token_provider(&mut self, token_provider: Option<#{TokenProvider}>) -> &mut Self { + self.token_provider = token_provider; self } """, @@ -80,60 +80,22 @@ class IdempotencyTokenProviderCustomization(private val runtimeMode: SmithyRunti ServiceConfig.BuilderBuild -> writable { if (runtimeMode.defaultToOrchestrator) { rust( - "layer.store_put(self.make_token.unwrap_or_else(#T::default_provider));", + "layer.store_put(self.token_provider.unwrap_or_else(#T::default_provider));", RuntimeType.IdempotencyToken, ) } else { rust( - "make_token: self.make_token.unwrap_or_else(#T::default_provider),", + "token_provider: self.token_provider.unwrap_or_else(#T::default_provider),", RuntimeType.IdempotencyToken, ) } } is ServiceConfig.DefaultForTests -> writable { - rust("""${section.configBuilderRef}.set_make_token(Some("00000000-0000-4000-8000-000000000000".into()));""") + rust("""${section.configBuilderRef}.set_token_provider(Some("00000000-0000-4000-8000-000000000000".into()));""") } else -> writable { } } } } - -/* Generated Code -pub struct Config { - pub(crate) make_token: Box, -} -impl Config { - pub fn builder() -> Builder { - Builder::default() - } -} -#[derive(Default)] -pub struct Builder { - #[allow(dead_code)] - make_token: Option>, -} -impl Builder { - pub fn new() -> Self { - Self::default() - } - - /// Sets the idempotency token provider to use for service calls that require tokens. - pub fn make_token( - mut self, - make_token: impl crate::idempotency_token::MakeIdempotencyToken + 'static, - ) -> Self { - self.make_token = Some(Box::new(make_token)); - self - } - - pub fn build(self) -> Config { - Config { - make_token: self - .make_token - .unwrap_or_else(|| Box::new(crate::idempotency_token::default_provider())), - } - } -} - */ From 0e7772162ccd871a0e5d796dae9a7ccf43059f1e Mon Sep 17 00:00:00 2001 From: Yuki Saito Date: Thu, 15 Jun 2023 16:22:26 -0500 Subject: [PATCH 13/15] Add `aws-smithy-types` dep to `idempotency_token` inlineable This commit addresses https://github.com/awslabs/smithy-rs/pull/2762#discussion_r1231469796 --- .../IdempotencyTokenProviderCustomization.kt | 44 +++++++++++-------- .../config/ServiceConfigGenerator.kt | 2 +- ...empotencyTokenProviderCustomizationTest.kt | 29 +----------- .../codegen/core/rustlang/CargoDependency.kt | 11 +++-- .../rust/codegen/core/smithy/RuntimeType.kt | 3 +- 5 files changed, 38 insertions(+), 51 deletions(-) diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/IdempotencyTokenProviderCustomization.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/IdempotencyTokenProviderCustomization.kt index 4b12aed8b6..a165a5d89e 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/IdempotencyTokenProviderCustomization.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/IdempotencyTokenProviderCustomization.kt @@ -5,24 +5,32 @@ package software.amazon.smithy.rust.codegen.client.smithy.generators.config -import software.amazon.smithy.rust.codegen.client.smithy.SmithyRuntimeMode +import software.amazon.smithy.rust.codegen.client.smithy.ClientCodegenContext 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.RuntimeType +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.preludeScope import software.amazon.smithy.rust.codegen.core.smithy.customize.NamedCustomization /** * Add a `token_provider` field to Service config. See below for the resulting generated code. */ -class IdempotencyTokenProviderCustomization(private val runtimeMode: SmithyRuntimeMode) : NamedCustomization() { +class IdempotencyTokenProviderCustomization(codegenContext: ClientCodegenContext) : NamedCustomization() { + private val runtimeConfig = codegenContext.runtimeConfig + private val runtimeMode = codegenContext.smithyRuntimeMode + private val codegenScope = arrayOf( + *preludeScope, + "default_provider" to RuntimeType.idempotencyToken(runtimeConfig).resolve("default_provider"), + "IdempotencyTokenProvider" to RuntimeType.idempotencyToken(runtimeConfig).resolve("IdempotencyTokenProvider"), + ) override fun section(section: ServiceConfig): Writable { return when (section) { is ServiceConfig.ConfigStruct -> writable { if (runtimeMode.defaultToMiddleware) { - rust("pub (crate) token_provider: #T::IdempotencyTokenProvider,", RuntimeType.IdempotencyToken) + rustTemplate("pub (crate) token_provider: #{IdempotencyTokenProvider},", *codegenScope) } } @@ -37,56 +45,56 @@ class IdempotencyTokenProviderCustomization(private val runtimeMode: SmithyRunti self.inner.load::<#{IdempotencyTokenProvider}>().expect("the idempotency provider should be set").clone() } """, - "IdempotencyTokenProvider" to RuntimeType.IdempotencyToken.resolve("IdempotencyTokenProvider"), + *codegenScope, ) } else { - rust( + rustTemplate( """ /// Returns a copy of the idempotency token provider. /// If a random token provider was configured, /// a newly-randomized token provider will be returned. - pub fn token_provider(&self) -> #T::IdempotencyTokenProvider { + pub fn token_provider(&self) -> #{IdempotencyTokenProvider} { self.token_provider.clone() } """, - RuntimeType.IdempotencyToken, + *codegenScope, ) } } ServiceConfig.BuilderStruct -> writable { - rust("token_provider: Option<#T::IdempotencyTokenProvider>,", RuntimeType.IdempotencyToken) + rustTemplate("token_provider: #{Option}<#{IdempotencyTokenProvider}>,", *codegenScope) } ServiceConfig.BuilderImpl -> writable { rustTemplate( """ /// Sets the idempotency token provider to use for service calls that require tokens. - pub fn token_provider(mut self, token_provider: impl Into<#{TokenProvider}>) -> Self { - self.set_token_provider(Some(token_provider.into())); + pub fn token_provider(mut self, token_provider: impl #{Into}<#{IdempotencyTokenProvider}>) -> Self { + self.set_token_provider(#{Some}(token_provider.into())); self } /// Sets the idempotency token provider to use for service calls that require tokens. - pub fn set_token_provider(&mut self, token_provider: Option<#{TokenProvider}>) -> &mut Self { + pub fn set_token_provider(&mut self, token_provider: #{Option}<#{IdempotencyTokenProvider}>) -> &mut Self { self.token_provider = token_provider; self } """, - "TokenProvider" to RuntimeType.IdempotencyToken.resolve("IdempotencyTokenProvider"), + *codegenScope, ) } ServiceConfig.BuilderBuild -> writable { if (runtimeMode.defaultToOrchestrator) { - rust( - "layer.store_put(self.token_provider.unwrap_or_else(#T::default_provider));", - RuntimeType.IdempotencyToken, + rustTemplate( + "layer.store_put(self.token_provider.unwrap_or_else(#{default_provider}));", + *codegenScope, ) } else { - rust( - "token_provider: self.token_provider.unwrap_or_else(#T::default_provider),", - RuntimeType.IdempotencyToken, + rustTemplate( + "token_provider: self.token_provider.unwrap_or_else(#{default_provider}),", + *codegenScope, ) } } diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/ServiceConfigGenerator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/ServiceConfigGenerator.kt index bf1fe50bb5..c5e14c301b 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/ServiceConfigGenerator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/ServiceConfigGenerator.kt @@ -300,7 +300,7 @@ class ServiceConfigGenerator( ): ServiceConfigGenerator { val baseFeatures = mutableListOf() if (codegenContext.serviceShape.needsIdempotencyToken(codegenContext.model)) { - baseFeatures.add(IdempotencyTokenProviderCustomization(codegenContext.smithyRuntimeMode)) + baseFeatures.add(IdempotencyTokenProviderCustomization(codegenContext)) } return ServiceConfigGenerator(codegenContext, baseFeatures + extraCustomizations) } diff --git a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/IdempotencyTokenProviderCustomizationTest.kt b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/IdempotencyTokenProviderCustomizationTest.kt index a0e715d3e4..2ae469608e 100644 --- a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/IdempotencyTokenProviderCustomizationTest.kt +++ b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/IdempotencyTokenProviderCustomizationTest.kt @@ -7,15 +7,10 @@ package software.amazon.smithy.rust.codegen.client.smithy.generators.config import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.ValueSource -import software.amazon.smithy.rust.codegen.client.smithy.ClientRustModule import software.amazon.smithy.rust.codegen.client.smithy.SmithyRuntimeMode import software.amazon.smithy.rust.codegen.client.testutil.testClientCodegenContext -import software.amazon.smithy.rust.codegen.client.testutil.testSymbolProvider import software.amazon.smithy.rust.codegen.client.testutil.validateConfigCustomizations import software.amazon.smithy.rust.codegen.client.testutil.withSmithyRuntimeMode -import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate -import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType -import software.amazon.smithy.rust.codegen.core.testutil.TestWorkspace import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel class IdempotencyTokenProviderCustomizationTest { @@ -25,31 +20,9 @@ class IdempotencyTokenProviderCustomizationTest { val smithyRuntimeMode = SmithyRuntimeMode.fromString(smithyRuntimeModeStr) val model = "namespace test".asSmithyModel() val codegenContext = testClientCodegenContext(model).withSmithyRuntimeMode(smithyRuntimeMode) - val symbolProvider = testSymbolProvider(model) - val project = TestWorkspace.testProject(symbolProvider) - // The following is a workaround for the middleware mode, and without this, the synthesized test crate would - // fail to compile. `IdempotencyTokenProvider` is a smithy inlineable and depends on `aws_smithy_types` crate - // to use the `Storable` trait (there is no smithy runtime mode when handwriting Rust source files since that's - // a codegen concept). When that inlinable is brought in during testing, the orchestrator mode is ok because a - // service config already depends on the `aws_smithy_types` crate, causing it to appear in `Cargo.toml` of the - // synthesized test crate. However, a service config in the middleware mode does not depend on the - // `aws_smithy_types` crate, so `Cargo.toml` of the synthesized test crate will not include it, causing the - // inlinable fail to compile. To work around it, the code below will force the `aws_smithy_types` to appear in - // `Cargo.toml`. - project.withModule(ClientRustModule.Config) { - if (smithyRuntimeMode.defaultToMiddleware) { - rustTemplate( - """ - struct DummyToAddDependencyOnSmithyTypes(#{Layer}); - """, - "Layer" to RuntimeType.smithyTypes(codegenContext.runtimeConfig).resolve("config_bag::Layer"), - ) - } - } validateConfigCustomizations( codegenContext, - IdempotencyTokenProviderCustomization(codegenContext.smithyRuntimeMode), - project, + IdempotencyTokenProviderCustomization(codegenContext), ) } } diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/CargoDependency.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/CargoDependency.kt index 72eba06a7d..73709b6328 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/CargoDependency.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/CargoDependency.kt @@ -103,8 +103,12 @@ class InlineDependency( CargoDependency.Http, ) - fun idempotencyToken() = - forInlineableRustFile("idempotency_token", CargoDependency.FastRand) + fun idempotencyToken(runtimeConfig: RuntimeConfig) = + forInlineableRustFile( + "idempotency_token", + CargoDependency.FastRand, + CargoDependency.smithyTypes(runtimeConfig), + ) fun ec2QueryErrors(runtimeConfig: RuntimeConfig): InlineDependency = forInlineableRustFile("ec2_query_errors", CargoDependency.smithyXml(runtimeConfig)) @@ -231,7 +235,8 @@ data class CargoDependency( val AsyncStream: CargoDependency = CargoDependency("async-stream", CratesIo("0.3.0"), DependencyScope.Dev) val Criterion: CargoDependency = CargoDependency("criterion", CratesIo("0.4.0"), DependencyScope.Dev) val FuturesCore: CargoDependency = CargoDependency("futures-core", CratesIo("0.3.25"), DependencyScope.Dev) - val FuturesUtil: CargoDependency = CargoDependency("futures-util", CratesIo("0.3.25"), DependencyScope.Dev, defaultFeatures = false) + val FuturesUtil: CargoDependency = + CargoDependency("futures-util", CratesIo("0.3.25"), DependencyScope.Dev, defaultFeatures = false) val HdrHistogram: CargoDependency = CargoDependency("hdrhistogram", CratesIo("7.5.2"), DependencyScope.Dev) val Hound: CargoDependency = CargoDependency("hound", CratesIo("3.4.0"), DependencyScope.Dev) val PrettyAssertions: CargoDependency = diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/RuntimeType.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/RuntimeType.kt index c8ca035401..fca8e07e1a 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/RuntimeType.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/RuntimeType.kt @@ -427,7 +427,8 @@ data class RuntimeType(val path: String, val dependency: RustDependency? = null) fun unwrappedXmlErrors(runtimeConfig: RuntimeConfig) = forInlineDependency(InlineDependency.unwrappedXmlErrors(runtimeConfig)) - val IdempotencyToken by lazy { forInlineDependency(InlineDependency.idempotencyToken()) } + fun idempotencyToken(runtimeConfig: RuntimeConfig) = + forInlineDependency(InlineDependency.idempotencyToken(runtimeConfig)) fun runtimePlugin(runtimeConfig: RuntimeConfig) = RuntimeType.smithyRuntimeApi(runtimeConfig).resolve("client::runtime_plugin::RuntimePlugin") From c449eb4ddeecaab7707301bed5353faab0c6f1a1 Mon Sep 17 00:00:00 2001 From: Yuki Saito Date: Thu, 15 Jun 2023 16:42:56 -0500 Subject: [PATCH 14/15] Update call site of `make_token` to use `token_provider` --- .../client/smithy/customizations/IdempotencyTokenGenerator.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/IdempotencyTokenGenerator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/IdempotencyTokenGenerator.kt index b9e36bd30c..a95678220a 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/IdempotencyTokenGenerator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/IdempotencyTokenGenerator.kt @@ -32,7 +32,7 @@ class IdempotencyTokenGenerator(codegenContext: CodegenContext, operationShape: rustTemplate( """ if ${section.input}.$memberName.is_none() { - ${section.input}.$memberName = #{Some}(${section.config}.make_token.make_idempotency_token()); + ${section.input}.$memberName = #{Some}(${section.config}.token_provider.make_idempotency_token()); } """, *preludeScope, From 8d573f24c68c7811f9a6316e6067c218d7b0638f Mon Sep 17 00:00:00 2001 From: Yuki Saito Date: Thu, 15 Jun 2023 17:37:20 -0500 Subject: [PATCH 15/15] Revert `token_provider` to `make_token` Renaming `make_token` to `idempotency_token_provider` will be handled in a separate PR. --- .../IdempotencyTokenGenerator.kt | 2 +- .../IdempotencyTokenProviderCustomization.kt | 26 +++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/IdempotencyTokenGenerator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/IdempotencyTokenGenerator.kt index a95678220a..b9e36bd30c 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/IdempotencyTokenGenerator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/customizations/IdempotencyTokenGenerator.kt @@ -32,7 +32,7 @@ class IdempotencyTokenGenerator(codegenContext: CodegenContext, operationShape: rustTemplate( """ if ${section.input}.$memberName.is_none() { - ${section.input}.$memberName = #{Some}(${section.config}.token_provider.make_idempotency_token()); + ${section.input}.$memberName = #{Some}(${section.config}.make_token.make_idempotency_token()); } """, *preludeScope, diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/IdempotencyTokenProviderCustomization.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/IdempotencyTokenProviderCustomization.kt index a165a5d89e..f7c0b3789f 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/IdempotencyTokenProviderCustomization.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/IdempotencyTokenProviderCustomization.kt @@ -15,7 +15,7 @@ import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.pre import software.amazon.smithy.rust.codegen.core.smithy.customize.NamedCustomization /** - * Add a `token_provider` field to Service config. See below for the resulting generated code. + * Add a `make_token` field to Service config. See below for the resulting generated code. */ class IdempotencyTokenProviderCustomization(codegenContext: ClientCodegenContext) : NamedCustomization() { private val runtimeConfig = codegenContext.runtimeConfig @@ -30,7 +30,7 @@ class IdempotencyTokenProviderCustomization(codegenContext: ClientCodegenContext return when (section) { is ServiceConfig.ConfigStruct -> writable { if (runtimeMode.defaultToMiddleware) { - rustTemplate("pub (crate) token_provider: #{IdempotencyTokenProvider},", *codegenScope) + rustTemplate("pub (crate) make_token: #{IdempotencyTokenProvider},", *codegenScope) } } @@ -41,7 +41,7 @@ class IdempotencyTokenProviderCustomization(codegenContext: ClientCodegenContext /// Returns a copy of the idempotency token provider. /// If a random token provider was configured, /// a newly-randomized token provider will be returned. - pub fn token_provider(&self) -> #{IdempotencyTokenProvider} { + pub fn make_token(&self) -> #{IdempotencyTokenProvider} { self.inner.load::<#{IdempotencyTokenProvider}>().expect("the idempotency provider should be set").clone() } """, @@ -53,8 +53,8 @@ class IdempotencyTokenProviderCustomization(codegenContext: ClientCodegenContext /// Returns a copy of the idempotency token provider. /// If a random token provider was configured, /// a newly-randomized token provider will be returned. - pub fn token_provider(&self) -> #{IdempotencyTokenProvider} { - self.token_provider.clone() + pub fn make_token(&self) -> #{IdempotencyTokenProvider} { + self.make_token.clone() } """, *codegenScope, @@ -63,21 +63,21 @@ class IdempotencyTokenProviderCustomization(codegenContext: ClientCodegenContext } ServiceConfig.BuilderStruct -> writable { - rustTemplate("token_provider: #{Option}<#{IdempotencyTokenProvider}>,", *codegenScope) + rustTemplate("make_token: #{Option}<#{IdempotencyTokenProvider}>,", *codegenScope) } ServiceConfig.BuilderImpl -> writable { rustTemplate( """ /// Sets the idempotency token provider to use for service calls that require tokens. - pub fn token_provider(mut self, token_provider: impl #{Into}<#{IdempotencyTokenProvider}>) -> Self { - self.set_token_provider(#{Some}(token_provider.into())); + pub fn make_token(mut self, make_token: impl #{Into}<#{IdempotencyTokenProvider}>) -> Self { + self.set_make_token(#{Some}(make_token.into())); self } /// Sets the idempotency token provider to use for service calls that require tokens. - pub fn set_token_provider(&mut self, token_provider: #{Option}<#{IdempotencyTokenProvider}>) -> &mut Self { - self.token_provider = token_provider; + pub fn set_make_token(&mut self, make_token: #{Option}<#{IdempotencyTokenProvider}>) -> &mut Self { + self.make_token = make_token; self } """, @@ -88,19 +88,19 @@ class IdempotencyTokenProviderCustomization(codegenContext: ClientCodegenContext ServiceConfig.BuilderBuild -> writable { if (runtimeMode.defaultToOrchestrator) { rustTemplate( - "layer.store_put(self.token_provider.unwrap_or_else(#{default_provider}));", + "layer.store_put(self.make_token.unwrap_or_else(#{default_provider}));", *codegenScope, ) } else { rustTemplate( - "token_provider: self.token_provider.unwrap_or_else(#{default_provider}),", + "make_token: self.make_token.unwrap_or_else(#{default_provider}),", *codegenScope, ) } } is ServiceConfig.DefaultForTests -> writable { - rust("""${section.configBuilderRef}.set_token_provider(Some("00000000-0000-4000-8000-000000000000".into()));""") + rust("""${section.configBuilderRef}.set_make_token(Some("00000000-0000-4000-8000-000000000000".into()));""") } else -> writable { }