From a83fc468d6e99f7d8abfda93d9729ee6a4866bb0 Mon Sep 17 00:00:00 2001 From: Russell Cohen Date: Mon, 24 Jul 2023 16:38:03 -0400 Subject: [PATCH 1/3] WASM example on wasm-unknown-unknown now working e2e Split out a wiremock feature to allow test-util to compile without Hyper --- aws/rust-runtime/aws-config/Cargo.toml | 1 + .../src/default_provider/credentials.rs | 16 ++-- .../aws-config/src/imds/client.rs | 16 ++-- .../aws-config/src/imds/credentials.rs | 23 ++--- aws/rust-runtime/aws-config/src/lib.rs | 14 ++- .../aws-config/src/provider_config.rs | 7 +- aws/rust-runtime/aws-config/src/sso.rs | 1 + .../aws-config/src/sts/assume_role.rs | 15 ++-- aws/rust-runtime/aws-config/src/test_case.rs | 8 +- .../src/cache/lazy_caching.rs | 46 +++++----- .../aws-credential-types/src/lib.rs | 4 +- .../aws-credential-types/src/time_source.rs | 86 +++---------------- .../aws-inlineable/src/presigning.rs | 5 +- .../aws-runtime/src/request_info.rs | 20 +++-- .../aws-sig-auth/src/event_stream.rs | 12 ++- aws/rust-runtime/clippy.toml | 1 + .../rustsdk/IntegrationTestDependencies.kt | 2 +- aws/sdk/build.gradle.kts | 2 + aws/sdk/integration-tests/Cargo.toml | 2 +- .../.cargo/config.toml | 3 + .../.vscode/settings.json | 0 .../Cargo.toml | 8 +- .../webassembly-wasi/README.md | 18 ++++ .../src/adapter/http_client.rs | 10 +-- .../src/adapter/mod.rs | 3 +- .../webassembly-wasi/src/default_config.rs | 47 ++++++++++ .../webassembly-wasi/src/lib.rs | 21 +++++ .../webassembly-wasi/src/list_buckets.rs | 49 +++++++++++ .../lib.rs => webassembly-wasi/src/main.rs} | 6 +- .../webassembly/src/default_config.rs | 33 ------- .../webassembly/src/list_buckets.rs | 20 ----- .../aws-smithy-async/src/test_util.rs | 5 ++ rust-runtime/aws-smithy-async/src/time.rs | 1 + rust-runtime/aws-smithy-client/Cargo.toml | 7 +- rust-runtime/aws-smithy-client/src/lib.rs | 2 +- .../aws-smithy-client/src/test_connection.rs | 1 + .../src/client/runtime_components.rs | 3 +- .../interceptors/service_clock_skew.rs | 11 ++- 38 files changed, 286 insertions(+), 243 deletions(-) create mode 120000 aws/rust-runtime/clippy.toml rename aws/sdk/integration-tests/{webassembly => webassembly-wasi}/.cargo/config.toml (76%) rename aws/sdk/integration-tests/{webassembly => webassembly-wasi}/.vscode/settings.json (100%) rename aws/sdk/integration-tests/{webassembly => webassembly-wasi}/Cargo.toml (87%) create mode 100644 aws/sdk/integration-tests/webassembly-wasi/README.md rename aws/sdk/integration-tests/{webassembly => webassembly-wasi}/src/adapter/http_client.rs (86%) rename aws/sdk/integration-tests/{webassembly => webassembly-wasi}/src/adapter/mod.rs (96%) create mode 100644 aws/sdk/integration-tests/webassembly-wasi/src/default_config.rs create mode 100644 aws/sdk/integration-tests/webassembly-wasi/src/lib.rs create mode 100644 aws/sdk/integration-tests/webassembly-wasi/src/list_buckets.rs rename aws/sdk/integration-tests/{webassembly/src/lib.rs => webassembly-wasi/src/main.rs} (64%) delete mode 100644 aws/sdk/integration-tests/webassembly/src/default_config.rs delete mode 100644 aws/sdk/integration-tests/webassembly/src/list_buckets.rs diff --git a/aws/rust-runtime/aws-config/Cargo.toml b/aws/rust-runtime/aws-config/Cargo.toml index c19658d9c3..6d6115db8a 100644 --- a/aws/rust-runtime/aws-config/Cargo.toml +++ b/aws/rust-runtime/aws-config/Cargo.toml @@ -63,6 +63,7 @@ serde_json = "1" aws-credential-types = { path = "../../sdk/build/aws-sdk/sdk/aws-credential-types", features = ["test-util"] } aws-smithy-client = { path = "../../sdk/build/aws-sdk/sdk/aws-smithy-client", features = ["test-util"] } +aws-smithy-async = { path = "../../sdk/build/aws-sdk/sdk/aws-smithy-async", features = ["test-util"] } # used for a usage example hyper-rustls = { version = "0.24", features = ["webpki-tokio", "http2", "http1"] } diff --git a/aws/rust-runtime/aws-config/src/default_provider/credentials.rs b/aws/rust-runtime/aws-config/src/default_provider/credentials.rs index 115cafcab1..f64af97b28 100644 --- a/aws/rust-runtime/aws-config/src/default_provider/credentials.rs +++ b/aws/rust-runtime/aws-config/src/default_provider/credentials.rs @@ -199,6 +199,7 @@ impl Builder { #[cfg(test)] mod test { use aws_credential_types::provider::ProvideCredentials; + use aws_smithy_async::time::{SharedTimeSource, StaticTimeSource}; use crate::default_provider::credentials::DefaultCredentialsChain; @@ -279,21 +280,15 @@ mod test { make_test!(imds_no_iam_role); make_test!(imds_default_chain_error); make_test!(imds_default_chain_success, builder: |config| { - config.with_time_source(aws_credential_types::time_source::TimeSource::testing( - &aws_credential_types::time_source::TestingTimeSource::new(std::time::UNIX_EPOCH), - )) + config.with_time_source(StaticTimeSource::new(std::time::UNIX_EPOCH)) }); make_test!(imds_assume_role); make_test!(imds_config_with_no_creds, builder: |config| { - config.with_time_source(aws_credential_types::time_source::TimeSource::testing( - &aws_credential_types::time_source::TestingTimeSource::new(std::time::UNIX_EPOCH), - )) + config.with_time_source(StaticTimeSource::new(std::time::UNIX_EPOCH)) }); make_test!(imds_disabled); make_test!(imds_default_chain_retries, builder: |config| { - config.with_time_source(aws_credential_types::time_source::TimeSource::testing( - &aws_credential_types::time_source::TestingTimeSource::new(std::time::UNIX_EPOCH), - )) + config.with_time_source(StaticTimeSource::new(std::time::UNIX_EPOCH)) }); make_test!(ecs_assume_role); make_test!(ecs_credentials); @@ -335,7 +330,6 @@ mod test { async fn no_providers_configured_err() { use crate::provider_config::ProviderConfig; use aws_credential_types::provider::error::CredentialsError; - use aws_credential_types::time_source::TimeSource; use aws_smithy_async::rt::sleep::TokioSleep; use aws_smithy_client::erase::boxclone::BoxCloneService; use aws_smithy_client::never::NeverConnected; @@ -343,7 +337,7 @@ mod test { tokio::time::pause(); let conf = ProviderConfig::no_configuration() .with_tcp_connector(BoxCloneService::new(NeverConnected::new())) - .with_time_source(TimeSource::default()) + .with_time_source(SharedTimeSource::default()) .with_sleep(TokioSleep::new()); let provider = DefaultCredentialsChain::builder() .configure(conf) diff --git a/aws/rust-runtime/aws-config/src/imds/client.rs b/aws/rust-runtime/aws-config/src/imds/client.rs index cb77b0759d..f084bc9a83 100644 --- a/aws/rust-runtime/aws-config/src/imds/client.rs +++ b/aws/rust-runtime/aws-config/src/imds/client.rs @@ -571,8 +571,8 @@ impl ClassifyRetry, SdkError> for ImdsResponseRetryClassi pub(crate) mod test { use crate::imds::client::{Client, EndpointMode, ImdsResponseRetryClassifier}; use crate::provider_config::ProviderConfig; - use aws_credential_types::time_source::{TestingTimeSource, TimeSource}; use aws_smithy_async::rt::sleep::TokioSleep; + use aws_smithy_async::test_util::instant_time_and_sleep; use aws_smithy_client::erase::DynConnector; use aws_smithy_client::test_connection::{capture_request, TestConnection}; use aws_smithy_client::{SdkError, SdkSuccess}; @@ -700,14 +700,13 @@ pub(crate) mod test { imds_response(r#"test-imds-output2"#), ), ]); - let mut time_source = TestingTimeSource::new(UNIX_EPOCH); - tokio::time::pause(); + let (time_source, sleep) = instant_time_and_sleep(UNIX_EPOCH); let client = super::Client::builder() .configure( &ProviderConfig::no_configuration() .with_http_connector(DynConnector::new(connection.clone())) - .with_time_source(TimeSource::testing(&time_source)) - .with_sleep(TokioSleep::new()), + .with_time_source(time_source.clone()) + .with_sleep(sleep), ) .endpoint_mode(EndpointMode::IpV6) .token_ttl(Duration::from_secs(600)) @@ -752,14 +751,13 @@ pub(crate) mod test { imds_response(r#"test-imds-output3"#), ), ]); - tokio::time::pause(); - let mut time_source = TestingTimeSource::new(UNIX_EPOCH); + let (time_source, sleep) = instant_time_and_sleep(UNIX_EPOCH); let client = super::Client::builder() .configure( &ProviderConfig::no_configuration() - .with_sleep(TokioSleep::new()) + .with_sleep(sleep) .with_http_connector(DynConnector::new(connection.clone())) - .with_time_source(TimeSource::testing(&time_source)), + .with_time_source(time_source.clone()), ) .endpoint_mode(EndpointMode::IpV6) .token_ttl(Duration::from_secs(600)) diff --git a/aws/rust-runtime/aws-config/src/imds/credentials.rs b/aws/rust-runtime/aws-config/src/imds/credentials.rs index c0c5707f24..ccc65eaf99 100644 --- a/aws/rust-runtime/aws-config/src/imds/credentials.rs +++ b/aws/rust-runtime/aws-config/src/imds/credentials.rs @@ -306,8 +306,7 @@ mod test { }; use crate::provider_config::ProviderConfig; use aws_credential_types::provider::ProvideCredentials; - use aws_credential_types::time_source::{TestingTimeSource, TimeSource}; - use aws_smithy_async::rt::sleep::TokioSleep; + use aws_smithy_async::test_util::instant_time_and_sleep; use aws_smithy_client::erase::DynConnector; use aws_smithy_client::test_connection::TestConnection; use tracing_test::traced_test; @@ -369,16 +368,12 @@ mod test { // set to 2021-09-21T04:16:50Z that makes returned credentials' expiry (2021-09-21T04:16:53Z) // not stale let time_of_request_to_fetch_credentials = UNIX_EPOCH + Duration::from_secs(1632197810); - let time_source = TimeSource::testing(&TestingTimeSource::new( - time_of_request_to_fetch_credentials, - )); - - tokio::time::pause(); + let (time_source, sleep) = instant_time_and_sleep(time_of_request_to_fetch_credentials); let provider_config = ProviderConfig::no_configuration() .with_http_connector(DynConnector::new(connection.clone())) - .with_time_source(time_source) - .with_sleep(TokioSleep::new()); + .with_sleep(sleep) + .with_time_source(time_source); let client = crate::imds::Client::builder() .configure(&provider_config) .build() @@ -419,16 +414,12 @@ mod test { // set to 2021-09-21T17:41:25Z that renders fetched credentials already expired (2021-09-21T04:16:53Z) let time_of_request_to_fetch_credentials = UNIX_EPOCH + Duration::from_secs(1632246085); - let time_source = TimeSource::testing(&TestingTimeSource::new( - time_of_request_to_fetch_credentials, - )); - - tokio::time::pause(); + let (time_source, sleep) = instant_time_and_sleep(time_of_request_to_fetch_credentials); let provider_config = ProviderConfig::no_configuration() .with_http_connector(DynConnector::new(connection.clone())) - .with_time_source(time_source) - .with_sleep(TokioSleep::new()); + .with_sleep(sleep) + .with_time_source(time_source); let client = crate::imds::Client::builder() .configure(&provider_config) .build() diff --git a/aws/rust-runtime/aws-config/src/lib.rs b/aws/rust-runtime/aws-config/src/lib.rs index 154659377f..f9cfdce2e2 100644 --- a/aws/rust-runtime/aws-config/src/lib.rs +++ b/aws/rust-runtime/aws-config/src/lib.rs @@ -547,10 +547,17 @@ mod loader { /// This means that if you provide a region provider that does not return a region, no region will /// be set in the resulting [`SdkConfig`](aws_types::SdkConfig) pub async fn load(self) -> SdkConfig { - let conf = self + let mut poisoned_conf = self .provider_config .unwrap_or_default() .with_profile_config(self.profile_files_override, self.profile_name_override); + if let Some(time_source) = &self.time_source { + poisoned_conf = poisoned_conf.with_time_source(time_source.clone()); + } + if let Some(sleep) = &self.sleep { + poisoned_conf = poisoned_conf.with_sleep(sleep.clone()); + } + let conf = poisoned_conf; let region = if let Some(provider) = self.region { provider.region().await } else { @@ -620,9 +627,8 @@ mod loader { let credentials_cache = if credentials_provider.is_some() { Some(self.credentials_cache.unwrap_or_else(|| { - let mut builder = CredentialsCache::lazy_builder().time_source( - aws_credential_types::time_source::TimeSource::shared(conf.time_source()), - ); + let mut builder = + CredentialsCache::lazy_builder().time_source(conf.time_source()); builder.set_sleep(conf.sleep()); builder.into_credentials_cache() })) diff --git a/aws/rust-runtime/aws-config/src/provider_config.rs b/aws/rust-runtime/aws-config/src/provider_config.rs index 27bc23108d..af932c6361 100644 --- a/aws/rust-runtime/aws-config/src/provider_config.rs +++ b/aws/rust-runtime/aws-config/src/provider_config.rs @@ -5,9 +5,8 @@ //! Configuration Options for Credential Providers -use aws_credential_types::time_source::TimeSource; use aws_smithy_async::rt::sleep::{default_async_sleep, AsyncSleep, SharedAsyncSleep}; -use aws_smithy_async::time::SharedTimeSource; +use aws_smithy_async::time::{SharedTimeSource, TimeSource}; use aws_smithy_client::erase::DynConnector; use aws_smithy_types::error::display::DisplayErrorContext; use aws_types::os_shim_internal::{Env, Fs}; @@ -291,8 +290,8 @@ impl ProviderConfig { } } - #[doc(hidden)] - pub fn with_time_source(self, time_source: TimeSource) -> Self { + /// Override the time source used for these credential providers + pub fn with_time_source(self, time_source: impl TimeSource + 'static) -> Self { ProviderConfig { time_source: SharedTimeSource::new(time_source), ..self diff --git a/aws/rust-runtime/aws-config/src/sso.rs b/aws/rust-runtime/aws-config/src/sso.rs index 592ed5b6bc..4eb59720bf 100644 --- a/aws/rust-runtime/aws-config/src/sso.rs +++ b/aws/rust-runtime/aws-config/src/sso.rs @@ -68,6 +68,7 @@ impl SsoCredentialsProvider { "The SSO credentials provider", provider_config.connector(&Default::default()), )) + .time_source(provider_config.time_source()) .retry_config(RetryConfig::standard()); sso_config.set_sleep_impl(provider_config.sleep()); diff --git a/aws/rust-runtime/aws-config/src/sts/assume_role.rs b/aws/rust-runtime/aws-config/src/sts/assume_role.rs index 50a83b4b6d..20bcd6b7df 100644 --- a/aws/rust-runtime/aws-config/src/sts/assume_role.rs +++ b/aws/rust-runtime/aws-config/src/sts/assume_role.rs @@ -291,9 +291,10 @@ mod test { use crate::sts::AssumeRoleProvider; use aws_credential_types::credential_fn::provide_credentials_fn; use aws_credential_types::provider::ProvideCredentials; - use aws_credential_types::time_source::{TestingTimeSource, TimeSource}; use aws_credential_types::Credentials; use aws_smithy_async::rt::sleep::TokioSleep; + use aws_smithy_async::test_util::instant_time_and_sleep; + use aws_smithy_async::time::StaticTimeSource; use aws_smithy_client::erase::DynConnector; use aws_smithy_client::test_connection::{capture_request, TestConnection}; use aws_smithy_http::body::SdkBody; @@ -305,9 +306,9 @@ mod test { let (server, request) = capture_request(None); let provider_conf = ProviderConfig::empty() .with_sleep(TokioSleep::new()) - .with_time_source(TimeSource::testing(&TestingTimeSource::new( + .with_time_source(StaticTimeSource::new( UNIX_EPOCH + Duration::from_secs(1234567890 - 120), - ))) + )) .with_http_connector(DynConnector::new(server)); let provider = AssumeRoleProvider::builder("myrole") .configure(&provider_conf) @@ -335,13 +336,13 @@ mod test { )).unwrap()), ]); - let mut testing_time_source = TestingTimeSource::new( + let (testing_time_source, sleep_impl) = instant_time_and_sleep( UNIX_EPOCH + Duration::from_secs(1234567890 - 120), // 1234567890 since UNIX_EPOCH is 2009-02-13T23:31:30Z ); let provider_conf = ProviderConfig::empty() - .with_sleep(TokioSleep::new()) - .with_time_source(TimeSource::testing(&testing_time_source)) + .with_sleep(sleep_impl) + .with_time_source(testing_time_source.clone()) .with_http_connector(DynConnector::new(conn)); let credentials_list = std::sync::Arc::new(std::sync::Mutex::new(vec![ Credentials::new( @@ -371,8 +372,6 @@ mod test { } })); - tokio::time::pause(); - let creds_first = provider .provide_credentials() .await diff --git a/aws/rust-runtime/aws-config/src/test_case.rs b/aws/rust-runtime/aws-config/src/test_case.rs index 14859d57ef..c04cd4ec0e 100644 --- a/aws/rust-runtime/aws-config/src/test_case.rs +++ b/aws/rust-runtime/aws-config/src/test_case.rs @@ -6,7 +6,7 @@ use crate::provider_config::ProviderConfig; use aws_credential_types::provider::{self, ProvideCredentials}; -use aws_smithy_async::rt::sleep::{AsyncSleep, Sleep, TokioSleep}; +use aws_smithy_async::rt::sleep::{AsyncSleep, Sleep}; use aws_smithy_client::dvr::{NetworkTraffic, RecordingConnection, ReplayingConnection}; use aws_smithy_client::erase::DynConnector; use aws_types::os_shim_internal::{Env, Fs}; @@ -14,6 +14,7 @@ use aws_types::os_shim_internal::{Env, Fs}; use serde::Deserialize; use crate::connector::default_connector; +use aws_smithy_async::test_util::instant_time_and_sleep; use aws_smithy_types::error::display::DisplayErrorContext; use std::collections::HashMap; use std::env; @@ -229,11 +230,13 @@ impl TestEnvironment { .map_err(|e| format!("failed to load test case: {}", e))?, )?; let connector = ReplayingConnection::new(network_traffic.events().clone()); + let (timeource, sleep) = instant_time_and_sleep(UNIX_EPOCH); let provider_config = ProviderConfig::empty() .with_fs(fs.clone()) .with_env(env.clone()) .with_http_connector(DynConnector::new(connector.clone())) - .with_sleep(TokioSleep::new()) + .with_sleep(sleep) + .with_time_source(timeource) .load_default_region() .await; Ok(TestEnvironment { @@ -336,7 +339,6 @@ impl TestEnvironment { let (_guard, rx) = capture_test_logs(); let provider = make_provider(self.provider_config.clone()).await; let result = provider.provide_credentials().await; - tokio::time::pause(); self.log_info(); self.check_results(result); // todo: validate bodies diff --git a/aws/rust-runtime/aws-credential-types/src/cache/lazy_caching.rs b/aws/rust-runtime/aws-credential-types/src/cache/lazy_caching.rs index ae1a6e2d36..60a2b658f8 100644 --- a/aws/rust-runtime/aws-credential-types/src/cache/lazy_caching.rs +++ b/aws/rust-runtime/aws-credential-types/src/cache/lazy_caching.rs @@ -5,16 +5,16 @@ //! Lazy, credentials cache implementation -use std::time::{Duration, Instant}; +use std::time::Duration; use aws_smithy_async::future::timeout::Timeout; use aws_smithy_async::rt::sleep::{AsyncSleep, SharedAsyncSleep}; +use aws_smithy_async::time::SharedTimeSource; use tracing::{debug, info, info_span, Instrument}; use crate::cache::{ExpiringCache, ProvideCachedCredentials}; use crate::provider::SharedCredentialsProvider; use crate::provider::{error::CredentialsError, future, ProvideCredentials}; -use crate::time_source::TimeSource; const DEFAULT_LOAD_TIMEOUT: Duration = Duration::from_secs(5); const DEFAULT_CREDENTIAL_EXPIRATION: Duration = Duration::from_secs(15 * 60); @@ -23,7 +23,7 @@ const DEFAULT_BUFFER_TIME_JITTER_FRACTION: fn() -> f64 = fastrand::f64; #[derive(Debug)] pub(crate) struct LazyCredentialsCache { - time: TimeSource, + time: SharedTimeSource, sleeper: SharedAsyncSleep, cache: ExpiringCache, provider: SharedCredentialsProvider, @@ -35,7 +35,7 @@ pub(crate) struct LazyCredentialsCache { impl LazyCredentialsCache { fn new( - time: TimeSource, + time: SharedTimeSource, sleeper: SharedAsyncSleep, provider: SharedCredentialsProvider, load_timeout: Duration, @@ -61,6 +61,7 @@ impl ProvideCachedCredentials for LazyCredentialsCache { where Self: 'a, { + tracing::info!("provider: {:#?}", self); let now = self.time.now(); let provider = self.provider.clone(); let timeout_future = self.sleeper.sleep(self.load_timeout); @@ -79,7 +80,7 @@ impl ProvideCachedCredentials for LazyCredentialsCache { // since the futures are not eagerly executed, and the cache will only run one // of them. let future = Timeout::new(provider.provide_credentials(), timeout_future); - let start_time = Instant::now(); + let start_time = self.time.now(); let result = cache .get_or_load(|| { let span = info_span!("lazy_load_credentials"); @@ -111,14 +112,14 @@ impl ProvideCachedCredentials for LazyCredentialsCache { // only once for the first thread that succeeds in populating a cache value. info!( "credentials cache miss occurred; added new AWS credentials (took {:?})", - start_time.elapsed() + self.time.now().duration_since(start_time) ); Ok((credentials, expiry + jitter)) } - // Only instrument the the actual load future so that no span - // is opened if the cache decides not to execute it. - .instrument(span) + // Only instrument the the actual load future so that no span + // is opened if the cache decides not to execute it. + .instrument(span) }) .await; debug!("loaded credentials"); @@ -137,8 +138,8 @@ mod builder { use crate::cache::{CredentialsCache, Inner}; use crate::provider::SharedCredentialsProvider; use aws_smithy_async::rt::sleep::{default_async_sleep, SharedAsyncSleep}; + use aws_smithy_async::time::SharedTimeSource; - use super::TimeSource; use super::{ LazyCredentialsCache, DEFAULT_BUFFER_TIME, DEFAULT_BUFFER_TIME_JITTER_FRACTION, DEFAULT_CREDENTIAL_EXPIRATION, DEFAULT_LOAD_TIMEOUT, @@ -159,7 +160,7 @@ mod builder { #[derive(Clone, Debug, Default)] pub struct Builder { sleep: Option, - time_source: Option, + time_source: Option, load_timeout: Option, buffer_time: Option, buffer_time_jitter_fraction: Option f64>, @@ -193,13 +194,13 @@ mod builder { } #[doc(hidden)] // because they only exist for tests - pub fn time_source(mut self, time_source: TimeSource) -> Self { + pub fn time_source(mut self, time_source: SharedTimeSource) -> Self { self.set_time_source(Some(time_source)); self } #[doc(hidden)] // because they only exist for tests - pub fn set_time_source(&mut self, time_source: Option) -> &mut Self { + pub fn set_time_source(&mut self, time_source: Option) -> &mut Self { self.time_source = time_source; self } @@ -346,6 +347,7 @@ mod tests { use std::time::{Duration, SystemTime, UNIX_EPOCH}; use aws_smithy_async::rt::sleep::{SharedAsyncSleep, TokioSleep}; + use aws_smithy_async::time::SharedTimeSource; use tracing::info; use tracing_test::traced_test; @@ -356,20 +358,20 @@ mod tests { }; use super::{ - LazyCredentialsCache, TimeSource, DEFAULT_BUFFER_TIME, DEFAULT_CREDENTIAL_EXPIRATION, + LazyCredentialsCache, DEFAULT_BUFFER_TIME, DEFAULT_CREDENTIAL_EXPIRATION, DEFAULT_LOAD_TIMEOUT, }; const BUFFER_TIME_NO_JITTER: fn() -> f64 = || 0_f64; fn test_provider( - time: TimeSource, + time: &TestingTimeSource, buffer_time_jitter_fraction: fn() -> f64, load_list: Vec, ) -> LazyCredentialsCache { let load_list = Arc::new(Mutex::new(load_list)); LazyCredentialsCache::new( - time, + SharedTimeSource::new(time.clone()), SharedAsyncSleep::new(TokioSleep::new()), SharedCredentialsProvider::new(provide_credentials_fn(move || { let list = load_list.clone(); @@ -411,7 +413,7 @@ mod tests { Ok(credentials(1000)) })); let credentials_cache = LazyCredentialsCache::new( - TimeSource::testing(&time), + SharedTimeSource::new(time), SharedAsyncSleep::new(TokioSleep::new()), provider, DEFAULT_LOAD_TIMEOUT, @@ -435,7 +437,7 @@ mod tests { async fn reload_expired_credentials() { let mut time = TestingTimeSource::new(epoch_secs(100)); let credentials_cache = test_provider( - TimeSource::testing(&time), + &time, BUFFER_TIME_NO_JITTER, vec![ Ok(credentials(1000)), @@ -459,7 +461,7 @@ mod tests { async fn load_failed_error() { let mut time = TestingTimeSource::new(epoch_secs(100)); let credentials_cache = test_provider( - TimeSource::testing(&time), + &time, BUFFER_TIME_NO_JITTER, vec![ Ok(credentials(1000)), @@ -486,7 +488,7 @@ mod tests { let time = TestingTimeSource::new(epoch_secs(0)); let credentials_cache = Arc::new(test_provider( - TimeSource::testing(&time), + &time, BUFFER_TIME_NO_JITTER, vec![ Ok(credentials(500)), @@ -531,7 +533,7 @@ mod tests { async fn load_timeout() { let time = TestingTimeSource::new(epoch_secs(100)); let credentials_cache = LazyCredentialsCache::new( - TimeSource::testing(&time), + SharedTimeSource::new(time.clone()), SharedAsyncSleep::new(TokioSleep::new()), SharedCredentialsProvider::new(provide_credentials_fn(|| async { aws_smithy_async::future::never::Never::new().await; @@ -554,7 +556,7 @@ mod tests { let mut time = TestingTimeSource::new(epoch_secs(100)); let buffer_time_jitter_fraction = || 0.5_f64; let credentials_cache = test_provider( - TimeSource::testing(&time), + &time, buffer_time_jitter_fraction, vec![Ok(credentials(1000)), Ok(credentials(2000))], ); diff --git a/aws/rust-runtime/aws-credential-types/src/lib.rs b/aws/rust-runtime/aws-credential-types/src/lib.rs index b2f8330b58..88dae33d4a 100644 --- a/aws/rust-runtime/aws-credential-types/src/lib.rs +++ b/aws/rust-runtime/aws-credential-types/src/lib.rs @@ -21,7 +21,7 @@ pub mod cache; pub mod credential_fn; mod credentials_impl; pub mod provider; -#[doc(hidden)] -pub mod time_source; +#[cfg(test)] +mod time_source; pub use credentials_impl::Credentials; diff --git a/aws/rust-runtime/aws-credential-types/src/time_source.rs b/aws/rust-runtime/aws-credential-types/src/time_source.rs index 212c7aa904..374d330e81 100644 --- a/aws/rust-runtime/aws-credential-types/src/time_source.rs +++ b/aws/rust-runtime/aws-credential-types/src/time_source.rs @@ -3,68 +3,22 @@ * SPDX-License-Identifier: Apache-2.0 */ -use aws_smithy_async::time::{SharedTimeSource, TimeSource as TimeSourceTrait}; -use std::ops::Deref; +use aws_smithy_async::time::TimeSource as TimeSourceTrait; use std::sync::{Arc, Mutex}; use std::time::{Duration, SystemTime}; -impl TimeSourceTrait for TimeSource { +impl TimeSourceTrait for TestingTimeSource { fn now(&self) -> SystemTime { self.now() } } -/// Time source abstraction -/// -/// Simple abstraction representing time either real-time or manually-specified for testing -#[derive(Debug, Clone)] -// TODO(breakingChangeWindow): Delete this struct -pub struct TimeSource(Inner); - -impl TimeSource { - /// Creates `TimeSource` from the manually specified `time_source`. - pub fn testing(time_source: &TestingTimeSource) -> Self { - TimeSource(Inner::Testing(time_source.clone())) - } - - /// Creates `TimeSource` from a shared time source - pub fn shared(time_source: SharedTimeSource) -> Self { - TimeSource(Inner::Shared(time_source)) - } - - /// Returns the current system time based on the mode. - pub fn now(&self) -> SystemTime { - match &self.0 { - Inner::Default => SystemTime::now(), - Inner::Testing(testing) => testing.now(), - Inner::Shared(ts) => ts.now(), - } - } -} - -impl Default for TimeSource { - /// Creates `TimeSource` from the current system time. - fn default() -> Self { - TimeSource(Inner::Default) - } -} - /// Time Source that can be manually moved for tests /// > This has been superseded by [`aws_smithy_async::time::TimeSource`] and will be removed in a /// > future release. /// /// # Examples /// -/// ```rust -/// # struct Client { -/// # // stub -/// # } -/// # -/// # impl Client { -/// # fn with_timesource(ts: TimeSource) -> Self { -/// # Client { } -/// # } -/// # } /// use aws_credential_types::time_source::{TestingTimeSource, TimeSource}; /// use std::time::{UNIX_EPOCH, Duration}; /// let mut time = TestingTimeSource::new(UNIX_EPOCH); @@ -72,14 +26,14 @@ impl Default for TimeSource { /// time.advance(Duration::from_secs(100)); /// ``` #[derive(Clone, Debug)] -pub struct TestingTimeSource { +pub(crate) struct TestingTimeSource { queries: Arc>>, now: Arc>, } impl TestingTimeSource { /// Creates `TestingTimeSource` with `start_time`. - pub fn new(start_time: SystemTime) -> Self { + pub(crate) fn new(start_time: SystemTime) -> Self { Self { queries: Default::default(), now: Arc::new(Mutex::new(start_time)), @@ -87,56 +41,36 @@ impl TestingTimeSource { } /// Sets time to the specified `time`. - pub fn set_time(&mut self, time: SystemTime) { + pub(crate) fn set_time(&mut self, time: SystemTime) { let mut now = self.now.lock().unwrap(); *now = time; } /// Advances time by `delta`. - pub fn advance(&mut self, delta: Duration) { + pub(crate) fn advance(&mut self, delta: Duration) { let mut now = self.now.lock().unwrap(); *now += delta; } - /// Returns a `Vec` of queried times so far. - pub fn queries(&self) -> impl Deref> + '_ { - self.queries.lock().unwrap() - } - /// Returns the current time understood by `TestingTimeSource`. - pub fn now(&self) -> SystemTime { + pub(crate) fn now(&self) -> SystemTime { let ts = *self.now.lock().unwrap(); self.queries.lock().unwrap().push(ts); ts } } -#[derive(Debug, Clone)] -enum Inner { - Default, - Testing(TestingTimeSource), - Shared(SharedTimeSource), -} - #[cfg(test)] mod test { - use super::{TestingTimeSource, TimeSource}; + use super::TestingTimeSource; use std::time::{Duration, UNIX_EPOCH}; - #[test] - fn default_time_source_should_not_panic_on_calling_now() { - let time_source = TimeSource::default(); - // no panics - let _ = time_source.now(); - } - #[test] fn testing_time_source_should_behave_as_expected() { - let mut testing = TestingTimeSource::new(UNIX_EPOCH); - let time_source = TimeSource::testing(&testing); + let mut time_source = TestingTimeSource::new(UNIX_EPOCH); assert_eq!(time_source.now(), UNIX_EPOCH); - testing.advance(Duration::from_secs(10)); + time_source.advance(Duration::from_secs(10)); assert_eq!(time_source.now(), UNIX_EPOCH + Duration::from_secs(10)); } } diff --git a/aws/rust-runtime/aws-inlineable/src/presigning.rs b/aws/rust-runtime/aws-inlineable/src/presigning.rs index 1bc9f42e6f..afe30ad81e 100644 --- a/aws/rust-runtime/aws-inlineable/src/presigning.rs +++ b/aws/rust-runtime/aws-inlineable/src/presigning.rs @@ -147,7 +147,10 @@ impl PresigningConfigBuilder { return Err(ErrorKind::ExpiresInDurationTooLong.into()); } Ok(PresigningConfig { - start_time: self.start_time.unwrap_or_else(SystemTime::now), + start_time: self.start_time.unwrap_or_else( + #[allow(clippy::disallowed_methods)] + SystemTime::now, + ), expires_in, }) } diff --git a/aws/rust-runtime/aws-runtime/src/request_info.rs b/aws/rust-runtime/aws-runtime/src/request_info.rs index f0abff3041..bb4221ca01 100644 --- a/aws/rust-runtime/aws-runtime/src/request_info.rs +++ b/aws/rust-runtime/aws-runtime/src/request_info.rs @@ -3,6 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +use aws_smithy_async::time::TimeSource; use aws_smithy_runtime::client::orchestrator::interceptors::ServiceClockSkew; use aws_smithy_runtime_api::box_error::BoxError; use aws_smithy_runtime_api::client::interceptors::context::BeforeTransmitInterceptorContextMut; @@ -16,7 +17,7 @@ use aws_smithy_types::timeout::TimeoutConfig; use aws_smithy_types::DateTime; use http::{HeaderName, HeaderValue}; use std::borrow::Cow; -use std::time::{Duration, SystemTime}; +use std::time::Duration; #[allow(clippy::declare_interior_mutable_const)] // we will never mutate this const AMZ_SDK_REQUEST: HeaderName = HeaderName::from_static("amz-sdk-request"); @@ -63,11 +64,15 @@ impl RequestInfoInterceptor { } } - fn build_ttl_pair(&self, cfg: &ConfigBag) -> Option<(Cow<'static, str>, Cow<'static, str>)> { + fn build_ttl_pair( + &self, + cfg: &ConfigBag, + timesource: impl TimeSource, + ) -> Option<(Cow<'static, str>, Cow<'static, str>)> { let timeout_config = cfg.load::()?; let socket_read = timeout_config.read_timeout()?; let estimated_skew: Duration = cfg.load::().cloned()?.into(); - let current_time = SystemTime::now(); + let current_time = timesource.now(); let ttl = current_time.checked_add(socket_read + estimated_skew)?; let mut timestamp = DateTime::from(ttl); // Set subsec_nanos to 0 so that the formatted `DateTime` won't have fractional seconds. @@ -90,11 +95,16 @@ impl Interceptor for RequestInfoInterceptor { fn modify_before_transmit( &self, context: &mut BeforeTransmitInterceptorContextMut<'_>, - _runtime_components: &RuntimeComponents, + runtime_components: &RuntimeComponents, cfg: &mut ConfigBag, ) -> Result<(), BoxError> { let mut pairs = RequestPairs::new(); - if let Some(pair) = self.build_ttl_pair(cfg) { + if let Some(pair) = self.build_ttl_pair( + cfg, + runtime_components + .time_source() + .ok_or("A timesource must be provided")?, + ) { pairs = pairs.with_pair(pair); } if let Some(pair) = self.build_attempts_pair(cfg) { diff --git a/aws/rust-runtime/aws-sig-auth/src/event_stream.rs b/aws/rust-runtime/aws-sig-auth/src/event_stream.rs index 01a1dd55fa..880b2b469c 100644 --- a/aws/rust-runtime/aws-sig-auth/src/event_stream.rs +++ b/aws/rust-runtime/aws-sig-auth/src/event_stream.rs @@ -49,7 +49,11 @@ impl SigV4MessageSigner { .secret_key(self.credentials.secret_access_key()) .region(self.signing_region.as_ref()) .service_name(self.signing_service.as_ref()) - .time(self.time.unwrap_or_else(SystemTime::now)) + .time(self.time.unwrap_or_else( + // dead code + #[allow(clippy::disallowed_methods)] + SystemTime::now, + )) .settings(()); builder.set_security_token(self.credentials.session_token()); builder.build().unwrap() @@ -149,7 +153,11 @@ impl SigV4Signer { let time = properties .get::() .copied() - .unwrap_or_else(SystemTime::now); + // dead code + .unwrap_or_else( + #[allow(clippy::disallowed_method)] + SystemTime::now, + ); let mut builder = SigningParams::builder() .access_key(credentials.access_key_id()) .secret_key(credentials.secret_access_key()) diff --git a/aws/rust-runtime/clippy.toml b/aws/rust-runtime/clippy.toml new file mode 120000 index 0000000000..e33e0863dc --- /dev/null +++ b/aws/rust-runtime/clippy.toml @@ -0,0 +1 @@ +../../clippy.toml \ No newline at end of file diff --git a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/IntegrationTestDependencies.kt b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/IntegrationTestDependencies.kt index 38c7d76a83..5a39041ef2 100644 --- a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/IntegrationTestDependencies.kt +++ b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/IntegrationTestDependencies.kt @@ -83,7 +83,7 @@ class IntegrationTestDependencies( val smithyAsync = CargoDependency.smithyAsync(codegenContext.runtimeConfig) .copy(features = setOf("test-util"), scope = DependencyScope.Dev) val smithyClient = CargoDependency.smithyClient(codegenContext.runtimeConfig) - .copy(features = setOf("test-util"), scope = DependencyScope.Dev) + .copy(features = setOf("test-util", "wiremock"), scope = DependencyScope.Dev) val smithyTypes = CargoDependency.smithyTypes(codegenContext.runtimeConfig) .copy(features = setOf("test-util"), scope = DependencyScope.Dev) addDependency(smithyAsync) diff --git a/aws/sdk/build.gradle.kts b/aws/sdk/build.gradle.kts index 920cb7579e..b1308dbfb1 100644 --- a/aws/sdk/build.gradle.kts +++ b/aws/sdk/build.gradle.kts @@ -338,6 +338,7 @@ tasks.register("generateCargoWorkspace") { doFirst { outputDir.mkdirs() outputDir.resolve("Cargo.toml").writeText(generateCargoWorkspace(awsServices)) + rootProject.rootDir.resolve("clippy.toml").copyTo(outputDir.resolve("clippy.toml")) } inputs.property("servicelist", awsServices.moduleNames.toString()) if (awsServices.examples.isNotEmpty()) { @@ -347,6 +348,7 @@ tasks.register("generateCargoWorkspace") { inputs.dir(test.path) } outputs.file(outputDir.resolve("Cargo.toml")) + outputs.file(outputDir.resolve("clippy.toml")) outputs.upToDateWhen { false } } diff --git a/aws/sdk/integration-tests/Cargo.toml b/aws/sdk/integration-tests/Cargo.toml index 284bc1bcb1..52dadecb00 100644 --- a/aws/sdk/integration-tests/Cargo.toml +++ b/aws/sdk/integration-tests/Cargo.toml @@ -16,5 +16,5 @@ members = [ "sts", "transcribestreaming", "timestreamquery", - "webassembly", + "webassembly-wasi", ] diff --git a/aws/sdk/integration-tests/webassembly/.cargo/config.toml b/aws/sdk/integration-tests/webassembly-wasi/.cargo/config.toml similarity index 76% rename from aws/sdk/integration-tests/webassembly/.cargo/config.toml rename to aws/sdk/integration-tests/webassembly-wasi/.cargo/config.toml index e6e321b297..8e2a80f27d 100644 --- a/aws/sdk/integration-tests/webassembly/.cargo/config.toml +++ b/aws/sdk/integration-tests/webassembly-wasi/.cargo/config.toml @@ -4,6 +4,9 @@ target = "wasm32-wasi" [target.wasm32-wasi] rustflags = ["-C", "opt-level=1"] +[target.wasm32-unknown-unknown] +runner = "webassembly-test-runner" + # TODO(Rust 1.70): The sparse registry config can be removed when upgrading to Rust 1.70 [registries.crates-io] protocol = "sparse" diff --git a/aws/sdk/integration-tests/webassembly/.vscode/settings.json b/aws/sdk/integration-tests/webassembly-wasi/.vscode/settings.json similarity index 100% rename from aws/sdk/integration-tests/webassembly/.vscode/settings.json rename to aws/sdk/integration-tests/webassembly-wasi/.vscode/settings.json diff --git a/aws/sdk/integration-tests/webassembly/Cargo.toml b/aws/sdk/integration-tests/webassembly-wasi/Cargo.toml similarity index 87% rename from aws/sdk/integration-tests/webassembly/Cargo.toml rename to aws/sdk/integration-tests/webassembly-wasi/Cargo.toml index b66406e6f5..fbc29e19fe 100644 --- a/aws/sdk/integration-tests/webassembly/Cargo.toml +++ b/aws/sdk/integration-tests/webassembly-wasi/Cargo.toml @@ -12,18 +12,16 @@ license = "Apache-2.0" repository = "https://github.com/awslabs/smithy-rs" publish = false -[lib] -crate-type = ["cdylib"] - # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -aws-config = { path = "../../build/aws-sdk/sdk/aws-config", default-features = false, features = ["rt-tokio"]} +aws-config = { path = "../../build/aws-sdk/sdk/aws-config", default-features = false, features = ["rt-tokio"] } aws-credential-types = { path = "../../build/aws-sdk/sdk/aws-credential-types", features = ["hardcoded-credentials"] } aws-sdk-s3 = { path = "../../build/aws-sdk/sdk/s3", default-features = false } -aws-smithy-client = { path = "../../build/aws-sdk/sdk/aws-smithy-client", default-features = false } +aws-smithy-client = { path = "../../build/aws-sdk/sdk/aws-smithy-client", default-features = false, features = ["test-util"] } aws-smithy-http = { path = "../../build/aws-sdk/sdk/aws-smithy-http" } aws-smithy-types = { path = "../../build/aws-sdk/sdk/aws-smithy-types" } +aws-smithy-async = { path = "../../build/aws-sdk/sdk/aws-smithy-async" } aws-types = { path = "../../build/aws-sdk/sdk/aws-types" } http = "0.2.8" tokio = { version = "1.24.2", features = ["macros", "rt"] } diff --git a/aws/sdk/integration-tests/webassembly-wasi/README.md b/aws/sdk/integration-tests/webassembly-wasi/README.md new file mode 100644 index 0000000000..99b8152b68 --- /dev/null +++ b/aws/sdk/integration-tests/webassembly-wasi/README.md @@ -0,0 +1,18 @@ +## webassembly-wasi test +This crate tests the `wasm32-wasi` target with the SDK (configured by `.cargo/config.toml`). + +## Running the tests +1. Ensure prerequesites are installed: + ```bash + rustup target add wasm32-wasi + cargo install cargo-wasi + ``` + +2. If wasmtime has not been installed, `cargo wasi` will prompt you to install it. +3. `cargo wasi test` + +## Testing this crate on wasm32-unknown-unknown +This crate can also be compiled on wasm32-unknown-unknown, however Rust >1.71 must be used: +``` +cargo +stable check --target wasm32-unknown-unknown +``` diff --git a/aws/sdk/integration-tests/webassembly/src/adapter/http_client.rs b/aws/sdk/integration-tests/webassembly-wasi/src/adapter/http_client.rs similarity index 86% rename from aws/sdk/integration-tests/webassembly/src/adapter/http_client.rs rename to aws/sdk/integration-tests/webassembly-wasi/src/adapter/http_client.rs index 5ca84838c9..c808c61132 100644 --- a/aws/sdk/integration-tests/webassembly/src/adapter/http_client.rs +++ b/aws/sdk/integration-tests/webassembly-wasi/src/adapter/http_client.rs @@ -5,10 +5,7 @@ use aws_smithy_http::body::SdkBody; -pub(crate) fn make_request(_req: http::Request) -> Result, ()> { - // Consumers here would pass the HTTP request to - // the Wasm host in order to get the response back - let body = " +pub(crate) const RESPONSE_BODY: &str = " @@ -25,5 +22,8 @@ pub(crate) fn make_request(_req: http::Request) -> Resulta3a42310-42d0-46d1-9745-0cee9f4fb851 "; - Ok(http::Response::new(SdkBody::from(body))) +pub(crate) fn make_request(_req: http::Request) -> Result, ()> { + // Consumers here would pass the HTTP request to + // the Wasm host in order to get the response back + Ok(http::Response::new(SdkBody::from(RESPONSE_BODY))) } diff --git a/aws/sdk/integration-tests/webassembly/src/adapter/mod.rs b/aws/sdk/integration-tests/webassembly-wasi/src/adapter/mod.rs similarity index 96% rename from aws/sdk/integration-tests/webassembly/src/adapter/mod.rs rename to aws/sdk/integration-tests/webassembly-wasi/src/adapter/mod.rs index b563eb097a..6367af4932 100644 --- a/aws/sdk/integration-tests/webassembly/src/adapter/mod.rs +++ b/aws/sdk/integration-tests/webassembly-wasi/src/adapter/mod.rs @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -mod http_client; +pub(crate) mod http_client; use aws_smithy_client::erase::DynConnector; use aws_smithy_client::http_connector::HttpConnector; @@ -38,7 +38,6 @@ impl Service> for Adapter { fn call(&mut self, req: http::Request) -> Self::Future { println!("Adapter: sending request..."); let res = http_client::make_request(req).unwrap(); - println!("{:?}", res); Box::pin(async move { Ok(res) }) } } diff --git a/aws/sdk/integration-tests/webassembly-wasi/src/default_config.rs b/aws/sdk/integration-tests/webassembly-wasi/src/default_config.rs new file mode 100644 index 0000000000..6c5e11bdc2 --- /dev/null +++ b/aws/sdk/integration-tests/webassembly-wasi/src/default_config.rs @@ -0,0 +1,47 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +use aws_config::retry::RetryConfig; +use aws_credential_types::Credentials; +use aws_smithy_async::time::StaticTimeSource; +use aws_smithy_client::http_connector::HttpConnector; +use aws_smithy_types::timeout::TimeoutConfig; +use aws_types::region::Region; +use std::future::Future; +use std::time::{Duration, UNIX_EPOCH}; + +pub(crate) fn get_default_config( + connector: impl Into, +) -> impl Future { + aws_config::from_env() + .region(Region::from_static("us-west-2")) + .credentials_provider(Credentials::from_keys( + "access_key", + "secret_key", + Some("session_token".to_string()), + )) + .timeout_config(TimeoutConfig::disabled()) + .time_source(StaticTimeSource::new( + UNIX_EPOCH + Duration::from_secs(1234567890), + )) + .retry_config(RetryConfig::disabled()) + .http_connector(connector) + .load() +} + +#[cfg(test)] +mod test { + use crate::default_config::get_default_config; + use aws_smithy_client::test_connection::capture_request; + + #[tokio::test] + pub async fn test_default_config() { + let (connector, req) = capture_request(None); + let shared_config = get_default_config(connector).await; + let client = aws_sdk_s3::Client::new(&shared_config); + assert_eq!(client.conf().region().unwrap().to_string(), "us-west-2"); + req.expect_no_request(); + } +} diff --git a/aws/sdk/integration-tests/webassembly-wasi/src/lib.rs b/aws/sdk/integration-tests/webassembly-wasi/src/lib.rs new file mode 100644 index 0000000000..d90a8b1cee --- /dev/null +++ b/aws/sdk/integration-tests/webassembly-wasi/src/lib.rs @@ -0,0 +1,21 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +mod adapter; +mod default_config; +mod list_buckets; + +pub async fn test() { + let response = crate::list_buckets::s3_list_buckets().await; + println!( + "{:#?}", + response + .buckets() + .unwrap_or_default() + .iter() + .map(|b| b.name().unwrap()) + .collect::>() + ); +} diff --git a/aws/sdk/integration-tests/webassembly-wasi/src/list_buckets.rs b/aws/sdk/integration-tests/webassembly-wasi/src/list_buckets.rs new file mode 100644 index 0000000000..63b7a30f37 --- /dev/null +++ b/aws/sdk/integration-tests/webassembly-wasi/src/list_buckets.rs @@ -0,0 +1,49 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +use aws_sdk_s3::operation::list_buckets::ListBucketsOutput; + +pub async fn s3_list_buckets() -> ListBucketsOutput { + use aws_sdk_s3::Client; + + use crate::default_config::get_default_config; + + let shared_config = get_default_config(crate::adapter::Adapter::to_http_connector()).await; + let client = Client::new(&shared_config); + let result = client.list_buckets().send().await.unwrap(); + result +} + +#[cfg(test)] +mod test { + use crate::adapter::http_client::RESPONSE_BODY; + use crate::default_config::get_default_config; + use aws_sdk_s3::Client; + use aws_smithy_client::test_connection::capture_request; + use aws_smithy_http::body::SdkBody; + use http::header::AUTHORIZATION; + + #[tokio::test] + pub async fn test_s3_list_buckets() { + let (conn, req) = capture_request(Some( + http::Response::builder() + .body(SdkBody::from(RESPONSE_BODY)) + .unwrap(), + )); + let shared_config = get_default_config(conn).await; + let client = Client::new(&shared_config); + let _result = client.list_buckets().send().await.unwrap(); + let req = req.expect_request(); + assert_eq!(req.uri().to_string(), "https://s3.us-west-2.amazonaws.com/"); + assert_eq!( + req.headers() + .get(AUTHORIZATION) + .expect("should exist") + .to_str() + .unwrap(), + "AWS4-HMAC-SHA256 Credential=access_key/20090213/us-west-2/s3/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date;x-amz-security-token;x-amz-user-agent, Signature=a85e38189eca7104d0782e08434c628b73f68f7d0ba57e11958cf8ccf19f3759" + ); + } +} diff --git a/aws/sdk/integration-tests/webassembly/src/lib.rs b/aws/sdk/integration-tests/webassembly-wasi/src/main.rs similarity index 64% rename from aws/sdk/integration-tests/webassembly/src/lib.rs rename to aws/sdk/integration-tests/webassembly-wasi/src/main.rs index bc9c1a112b..2f6e5a98b1 100644 --- a/aws/sdk/integration-tests/webassembly/src/lib.rs +++ b/aws/sdk/integration-tests/webassembly-wasi/src/main.rs @@ -3,11 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -mod adapter; -mod default_config; -mod list_buckets; - #[tokio::main(flavor = "current_thread")] pub async fn main() { - crate::list_buckets::s3_list_buckets().await + webassembly::test().await } diff --git a/aws/sdk/integration-tests/webassembly/src/default_config.rs b/aws/sdk/integration-tests/webassembly/src/default_config.rs deleted file mode 100644 index fd8899cbe0..0000000000 --- a/aws/sdk/integration-tests/webassembly/src/default_config.rs +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0 - */ - -use aws_config::retry::RetryConfig; -use aws_credential_types::Credentials; -use aws_smithy_types::timeout::TimeoutConfig; -use aws_types::region::Region; -use std::future::Future; - -use crate::adapter::Adapter; - -pub(crate) fn get_default_config() -> impl Future { - aws_config::from_env() - .region(Region::from_static("us-west-2")) - .credentials_provider(Credentials::from_keys( - "access_key", - "secret_key", - Some("session_token".to_string()), - )) - .timeout_config(TimeoutConfig::disabled()) - .retry_config(RetryConfig::disabled()) - .http_connector(Adapter::to_http_connector()) - .load() -} - -#[tokio::test] -pub async fn test_default_config() { - let shared_config = get_default_config().await; - let client = aws_sdk_s3::Client::new(&shared_config); - assert_eq!(client.conf().region().unwrap().to_string(), "us-west-2") -} diff --git a/aws/sdk/integration-tests/webassembly/src/list_buckets.rs b/aws/sdk/integration-tests/webassembly/src/list_buckets.rs deleted file mode 100644 index 53504e6644..0000000000 --- a/aws/sdk/integration-tests/webassembly/src/list_buckets.rs +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0 - */ - -pub async fn s3_list_buckets() { - use aws_sdk_s3::Client; - - use crate::default_config::get_default_config; - - let shared_config = get_default_config().await; - let client = Client::new(&shared_config); - let result = client.list_buckets().send().await.unwrap(); - assert_eq!(result.buckets().unwrap().len(), 2) -} - -#[tokio::test] -pub async fn test_s3_list_buckets() { - s3_list_buckets().await -} diff --git a/rust-runtime/aws-smithy-async/src/test_util.rs b/rust-runtime/aws-smithy-async/src/test_util.rs index fa1dfe300b..a3ed031239 100644 --- a/rust-runtime/aws-smithy-async/src/test_util.rs +++ b/rust-runtime/aws-smithy-async/src/test_util.rs @@ -35,6 +35,11 @@ impl ManualTimeSource { .unwrap() .as_secs_f64() } + + /// Manually advances time by the specified duration + pub fn advance(&self, time: Duration) { + self.log.lock().unwrap().push(time); + } } impl TimeSource for ManualTimeSource { diff --git a/rust-runtime/aws-smithy-async/src/time.rs b/rust-runtime/aws-smithy-async/src/time.rs index 2abe332c88..7bb1bc3701 100644 --- a/rust-runtime/aws-smithy-async/src/time.rs +++ b/rust-runtime/aws-smithy-async/src/time.rs @@ -28,6 +28,7 @@ impl SystemTimeSource { impl TimeSource for SystemTimeSource { fn now(&self) -> SystemTime { + #[allow(clippy::disallowed_methods)] SystemTime::now() } } diff --git a/rust-runtime/aws-smithy-client/Cargo.toml b/rust-runtime/aws-smithy-client/Cargo.toml index 826ce5eb3d..85cf28de4e 100644 --- a/rust-runtime/aws-smithy-client/Cargo.toml +++ b/rust-runtime/aws-smithy-client/Cargo.toml @@ -9,11 +9,12 @@ repository = "https://github.com/awslabs/smithy-rs" [features] rt-tokio = ["aws-smithy-async/rt-tokio"] -test-util = ["dep:aws-smithy-protocol-test", "dep:hyper", "hyper?/server", "hyper?/h2", "dep:serde", "dep:serde_json", "serde?/derive", "rustls", "tokio/full"] +test-util = ["dep:aws-smithy-protocol-test", "dep:serde", "dep:serde_json", "serde?/derive"] +wiremock = ["dep:hyper", "hyper?/server", "hyper?/h2", "rustls", "tokio/full"] native-tls = [] allow-compilation = [] # our tests use `cargo test --all-features` and native-tls breaks CI rustls = ["dep:hyper-rustls", "dep:lazy_static", "dep:rustls", "client-hyper", "rt-tokio"] -client-hyper = ["dep:hyper"] +client-hyper = ["dep:hyper", "hyper?/client", "hyper?/http2", "hyper?/http1", "hyper?/tcp"] hyper-webpki-doctest-only = ["dep:hyper-rustls", "hyper-rustls?/webpki-roots"] [dependencies] @@ -26,7 +27,7 @@ bytes = "1" fastrand = "2.0.0" http = "0.2.3" http-body = "0.4.4" -hyper = { version = "0.14.26", features = ["client", "http2", "http1", "tcp"], optional = true } +hyper = { version = "0.14.26", default-features = false, optional = true } # cargo does not support optional test dependencies, so to completely disable rustls # we need to add the webpki-roots feature here. # https://github.com/rust-lang/cargo/issues/1596 diff --git a/rust-runtime/aws-smithy-client/src/lib.rs b/rust-runtime/aws-smithy-client/src/lib.rs index 935dddd2f0..82ddc4cacb 100644 --- a/rust-runtime/aws-smithy-client/src/lib.rs +++ b/rust-runtime/aws-smithy-client/src/lib.rs @@ -34,7 +34,7 @@ pub mod timeout; mod builder; pub use builder::Builder; -#[cfg(feature = "test-util")] +#[cfg(all(feature = "test-util", feature = "client-hyper"))] pub mod dvr; #[cfg(feature = "test-util")] pub mod test_connection; diff --git a/rust-runtime/aws-smithy-client/src/test_connection.rs b/rust-runtime/aws-smithy-client/src/test_connection.rs index 86466944df..54627e1b1c 100644 --- a/rust-runtime/aws-smithy-client/src/test_connection.rs +++ b/rust-runtime/aws-smithy-client/src/test_connection.rs @@ -358,6 +358,7 @@ impl tower::Service> for ConnectionFn { /// match_events!(ev!(dns), ev!(connect), ev!(http(200)))(&mock.events()); /// # } /// ``` +#[cfg(feature = "wiremock")] pub mod wire_mock { use bytes::Bytes; use http::{Request, Response}; diff --git a/rust-runtime/aws-smithy-runtime-api/src/client/runtime_components.rs b/rust-runtime/aws-smithy-runtime-api/src/client/runtime_components.rs index 520c164e74..bd47e2ad5b 100644 --- a/rust-runtime/aws-smithy-runtime-api/src/client/runtime_components.rs +++ b/rust-runtime/aws-smithy-runtime-api/src/client/runtime_components.rs @@ -201,6 +201,7 @@ declare_runtime_components! { #[required] retry_strategy: Option, + #[required] time_source: Option, sleep_impl: Option, @@ -258,7 +259,7 @@ impl RuntimeComponents { /// Returns the time source. pub fn time_source(&self) -> Option { - self.time_source.as_ref().map(|s| s.value.clone()) + Some(self.time_source.value.clone()) } } diff --git a/rust-runtime/aws-smithy-runtime/src/client/orchestrator/interceptors/service_clock_skew.rs b/rust-runtime/aws-smithy-runtime/src/client/orchestrator/interceptors/service_clock_skew.rs index 110f720a81..4c49b9bda5 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/orchestrator/interceptors/service_clock_skew.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/orchestrator/interceptors/service_clock_skew.rs @@ -10,7 +10,7 @@ use aws_smithy_runtime_api::client::runtime_components::RuntimeComponents; use aws_smithy_types::config_bag::{ConfigBag, Storable, StoreReplace}; use aws_smithy_types::date_time::Format; use aws_smithy_types::DateTime; -use std::time::{Duration, SystemTime}; +use std::time::Duration; #[derive(Debug, Clone)] #[non_exhaustive] @@ -69,10 +69,15 @@ impl Interceptor for ServiceClockSkewInterceptor { fn modify_before_deserialization( &self, ctx: &mut BeforeDeserializationInterceptorContextMut<'_>, - _runtime_components: &RuntimeComponents, + runtime_components: &RuntimeComponents, cfg: &mut ConfigBag, ) -> Result<(), BoxError> { - let time_received = DateTime::from(SystemTime::now()); + let time_received = DateTime::from( + runtime_components + .time_source() + .ok_or("a time source is required (service clock skew)")? + .now(), + ); let time_sent = match extract_time_sent_from_response(ctx) { Ok(time_sent) => time_sent, Err(e) => { From 85d502de3f7adf22346fbcd7385b1e41e3517312 Mon Sep 17 00:00:00 2001 From: Russell Cohen Date: Tue, 25 Jul 2023 16:57:53 -0400 Subject: [PATCH 2/3] Share the HTTP connector between the clients and the credentials provider --- CHANGELOG.next.toml | 18 +++ .../src/default_provider/app_name.rs | 9 +- aws/rust-runtime/aws-config/src/lib.rs | 117 +++++++----------- .../aws-config/src/provider_config.rs | 25 ++-- aws/rust-runtime/aws-config/src/test_case.rs | 12 +- 5 files changed, 91 insertions(+), 90 deletions(-) diff --git a/CHANGELOG.next.toml b/CHANGELOG.next.toml index 7b24ac49ef..36ea8756a5 100644 --- a/CHANGELOG.next.toml +++ b/CHANGELOG.next.toml @@ -664,3 +664,21 @@ message = "The `alb_health_check` module has been moved out of the `plugin` modu references = ["smithy-rs#2865"] meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "server" } author = "david-perez" + +[[aws-sdk-rust]] +message = "Credential providers now share the HTTP connector used by the SDK. As a result, the `ConfigLoader::configure(...)` method has been removed. If you want to keep a separate connector for clients, use `::ConfigBuilder::http_connector` when constructing the client." +references = ["aws-sdk-rust#579", "aws-sdk-rust#338"] +meta = { "breaking" = true, "tada" = false, "bug" = false } +author = "rcoh" + +[[aws-sdk-rust]] +message = "When creating the default credentials chain with `aws_config::from_env()`, the internal providers now use the configured sleep and time source implmentation. Prior to this fix, they always used the default implementation." +references = ["aws-sdk-rust#59"] +meta = { "breaking" = false, "tada" = false, "bug" = true } +author = "rcoh" + +[[aws-sdk-rust]] +message = "ProviderConfig::with_http_connector now accepts an `HttpConnector` instead of a `DynConnector`. This allows HTTP connectors to be configured which correctly respect timeouts." +references = ["aws-sdk-rust#579", "aws-sdk-rust#338"] +meta = { "breaking" = true, "tada" = false, "bug" = false } +author = "rcoh" diff --git a/aws/rust-runtime/aws-config/src/default_provider/app_name.rs b/aws/rust-runtime/aws-config/src/default_provider/app_name.rs index 7d91c6d363..236def6a87 100644 --- a/aws/rust-runtime/aws-config/src/default_provider/app_name.rs +++ b/aws/rust-runtime/aws-config/src/default_provider/app_name.rs @@ -118,12 +118,9 @@ mod tests { async fn profile_name_override() { let fs = Fs::from_slice(&[("test_config", "[profile custom]\nsdk_ua_app_id = correct")]); let conf = crate::from_env() - .configure( - ProviderConfig::empty() - .with_fs(fs) - .with_sleep(InstantSleep) - .with_http_connector(no_traffic_connector()), - ) + .fs(fs) + .sleep_impl(InstantSleep) + .http_connector(no_traffic_connector()) .profile_name("custom") .profile_files( ProfileFiles::builder() diff --git a/aws/rust-runtime/aws-config/src/lib.rs b/aws/rust-runtime/aws-config/src/lib.rs index f9cfdce2e2..fe6d33ea1b 100644 --- a/aws/rust-runtime/aws-config/src/lib.rs +++ b/aws/rust-runtime/aws-config/src/lib.rs @@ -161,6 +161,7 @@ mod loader { use aws_smithy_types::timeout::TimeoutConfig; use aws_types::app_name::AppName; use aws_types::docs_for; + use aws_types::os_shim_internal::{Env, Fs}; use aws_types::SdkConfig; use crate::connector::default_connector; @@ -198,13 +199,14 @@ mod loader { retry_config: Option, sleep: Option, timeout_config: Option, - provider_config: Option, http_connector: Option, profile_name_override: Option, profile_files_override: Option, use_fips: Option, use_dual_stack: Option, time_source: Option, + fs: Option, + env: Option, } impl ConfigLoader { @@ -513,30 +515,6 @@ mod loader { self } - /// Set configuration for all sub-loaders (credentials, region etc.) - /// - /// Update the `ProviderConfig` used for all nested loaders. This can be used to override - /// the HTTPs connector used by providers or to stub in an in memory `Env` or `Fs` for testing. - /// - /// # Examples - /// ```no_run - /// # #[cfg(feature = "hyper-client")] - /// # async fn create_config() { - /// use aws_config::provider_config::ProviderConfig; - /// let custom_https_connector = hyper_rustls::HttpsConnectorBuilder::new() - /// .with_webpki_roots() - /// .https_only() - /// .enable_http1() - /// .build(); - /// let provider_config = ProviderConfig::default().with_tcp_connector(custom_https_connector); - /// let shared_config = aws_config::from_env().configure(provider_config).load().await; - /// # } - /// ``` - pub fn configure(mut self, provider_config: ProviderConfig) -> Self { - self.provider_config = Some(provider_config); - self - } - /// Load the default configuration chain /// /// If fields have been overridden during builder construction, the override values will be used. @@ -547,17 +525,30 @@ mod loader { /// This means that if you provide a region provider that does not return a region, no region will /// be set in the resulting [`SdkConfig`](aws_types::SdkConfig) pub async fn load(self) -> SdkConfig { - let mut poisoned_conf = self - .provider_config - .unwrap_or_default() - .with_profile_config(self.profile_files_override, self.profile_name_override); - if let Some(time_source) = &self.time_source { - poisoned_conf = poisoned_conf.with_time_source(time_source.clone()); - } - if let Some(sleep) = &self.sleep { - poisoned_conf = poisoned_conf.with_sleep(sleep.clone()); - } - let conf = poisoned_conf; + let sleep_impl = if self.sleep.is_some() { + self.sleep + } else { + if default_async_sleep().is_none() { + tracing::warn!( + "An implementation of AsyncSleep was requested by calling default_async_sleep \ + but no default was set. + This happened when ConfigLoader::load was called during Config construction. \ + You can fix this by setting a sleep_impl on the ConfigLoader before calling \ + load or by enabling the rt-tokio feature" + ); + } + default_async_sleep() + }; + let http_connector = self + .http_connector + .unwrap_or_else(|| HttpConnector::ConnectorFn(Arc::new(default_connector))); + + let ts = self.time_source.unwrap_or_default(); + let conf = ProviderConfig::init(ts.clone(), sleep_impl.clone()) + .with_profile_config(self.profile_files_override, self.profile_name_override) + .with_fs(self.fs.unwrap_or_default()) + .with_http_connector(http_connector.clone()) + .with_env(self.env.unwrap_or_default()); let region = if let Some(provider) = self.region { provider.region().await } else { @@ -586,21 +577,6 @@ mod loader { .await }; - let sleep_impl = if self.sleep.is_some() { - self.sleep - } else { - if default_async_sleep().is_none() { - tracing::warn!( - "An implementation of AsyncSleep was requested by calling default_async_sleep \ - but no default was set. - This happened when ConfigLoader::load was called during Config construction. \ - You can fix this by setting a sleep_impl on the ConfigLoader before calling \ - load or by enabling the rt-tokio feature" - ); - } - default_async_sleep() - }; - let timeout_config = if let Some(timeout_config) = self.timeout_config { timeout_config } else { @@ -610,10 +586,6 @@ mod loader { .await }; - let http_connector = self - .http_connector - .unwrap_or_else(|| HttpConnector::ConnectorFn(Arc::new(default_connector))); - let credentials_provider = match self.credentials_provider { CredentialsProviderOption::Set(provider) => Some(provider), CredentialsProviderOption::NotSet => { @@ -648,8 +620,6 @@ mod loader { use_dual_stack_provider(&conf).await }; - let ts = self.time_source.unwrap_or_default(); - let mut builder = SdkConfig::builder() .region(region) .retry_config(retry_config) @@ -668,6 +638,19 @@ mod loader { } } + #[cfg(test)] + impl ConfigLoader { + pub(crate) fn env(mut self, env: Env) -> Self { + self.env = Some(env); + self + } + + pub(crate) fn fs(mut self, fs: Fs) -> Self { + self.fs = Some(fs); + self + } + } + #[cfg(test)] mod test { use aws_credential_types::provider::ProvideCredentials; @@ -679,7 +662,6 @@ mod loader { use tracing_test::traced_test; use crate::profile::profile_file::{ProfileFileKind, ProfileFiles}; - use crate::provider_config::ProviderConfig; use crate::test_case::{no_traffic_connector, InstantSleep}; use crate::{from_env, ConfigLoader}; @@ -695,13 +677,10 @@ mod loader { let fs = Fs::from_slice(&[("test_config", "[profile custom]\nsdk-ua-app-id = correct")]); let loader = from_env() - .configure( - ProviderConfig::empty() - .with_sleep(TokioSleep::new()) - .with_env(env) - .with_fs(fs) - .with_http_connector(DynConnector::new(NeverConnector::new())), - ) + .sleep_impl(TokioSleep::new()) + .http_connector(DynConnector::new(NeverConnector::new())) + .env(env) + .fs(fs) .profile_name("custom") .profile_files( ProfileFiles::builder() @@ -741,11 +720,9 @@ mod loader { } fn base_conf() -> ConfigLoader { - from_env().configure( - ProviderConfig::empty() - .with_sleep(InstantSleep) - .with_http_connector(no_traffic_connector()), - ) + from_env() + .sleep_impl(InstantSleep) + .http_connector(no_traffic_connector()) } #[tokio::test] diff --git a/aws/rust-runtime/aws-config/src/provider_config.rs b/aws/rust-runtime/aws-config/src/provider_config.rs index af932c6361..deb63542fb 100644 --- a/aws/rust-runtime/aws-config/src/provider_config.rs +++ b/aws/rust-runtime/aws-config/src/provider_config.rs @@ -150,6 +150,21 @@ impl ProviderConfig { } } + /// Initializer for ConfigBag to avoid possibly setting incorrect defaults. + pub(crate) fn init(time_source: SharedTimeSource, sleep: Option) -> Self { + Self { + parsed_profile: Default::default(), + profile_files: ProfileFiles::default(), + env: Env::default(), + fs: Fs::default(), + time_source, + connector: HttpConnector::Prebuilt(None), + sleep, + region: None, + profile_name_override: None, + } + } + /// Create a default provider config with the region region automatically loaded from the default chain. /// /// # Examples @@ -299,15 +314,9 @@ impl ProviderConfig { } /// Override the HTTPS connector for this configuration - /// - /// **Warning**: Use of this method will prevent you from taking advantage of the HTTP connect timeouts. - /// Consider [`ProviderConfig::with_tcp_connector`]. - /// - /// # Stability - /// This method is expected to change to support HTTP configuration. - pub fn with_http_connector(self, connector: DynConnector) -> Self { + pub fn with_http_connector(self, connector: impl Into) -> Self { ProviderConfig { - connector: HttpConnector::Prebuilt(Some(connector)), + connector: connector.into(), ..self } } diff --git a/aws/rust-runtime/aws-config/src/test_case.rs b/aws/rust-runtime/aws-config/src/test_case.rs index c04cd4ec0e..6a0d37f259 100644 --- a/aws/rust-runtime/aws-config/src/test_case.rs +++ b/aws/rust-runtime/aws-config/src/test_case.rs @@ -8,13 +8,13 @@ use crate::provider_config::ProviderConfig; use aws_credential_types::provider::{self, ProvideCredentials}; use aws_smithy_async::rt::sleep::{AsyncSleep, Sleep}; use aws_smithy_client::dvr::{NetworkTraffic, RecordingConnection, ReplayingConnection}; -use aws_smithy_client::erase::DynConnector; use aws_types::os_shim_internal::{Env, Fs}; use serde::Deserialize; use crate::connector::default_connector; use aws_smithy_async::test_util::instant_time_and_sleep; +use aws_smithy_client::http_connector::HttpConnector; use aws_smithy_types::error::display::DisplayErrorContext; use std::collections::HashMap; use std::env; @@ -79,8 +79,8 @@ pub(crate) struct TestEnvironment { } /// Connector which expects no traffic -pub(crate) fn no_traffic_connector() -> DynConnector { - DynConnector::new(ReplayingConnection::new(vec![])) +pub(crate) fn no_traffic_connector() -> HttpConnector { + ReplayingConnection::new(vec![]).into() } #[derive(Debug)] @@ -234,7 +234,7 @@ impl TestEnvironment { let provider_config = ProviderConfig::empty() .with_fs(fs.clone()) .with_env(env.clone()) - .with_http_connector(DynConnector::new(connector.clone())) + .with_http_connector(connector.clone()) .with_sleep(sleep) .with_time_source(timeource) .load_default_region() @@ -277,7 +277,7 @@ impl TestEnvironment { let config = self .provider_config .clone() - .with_http_connector(DynConnector::new(live_connector.clone())); + .with_http_connector(live_connector.clone()); let provider = make_provider(config).await; let result = provider.provide_credentials().await; std::fs::write( @@ -302,7 +302,7 @@ impl TestEnvironment { let config = self .provider_config .clone() - .with_http_connector(DynConnector::new(recording_connector.clone())); + .with_http_connector(recording_connector.clone()); let provider = make_provider(config).await; let result = provider.provide_credentials().await; std::fs::write( From 3eea6fa1d4a037a709a385b58b4ecbc7721c9292 Mon Sep 17 00:00:00 2001 From: Russell Cohen Date: Wed, 26 Jul 2023 10:27:07 -0400 Subject: [PATCH 3/3] Add clippy symlinks --- aws/rust-runtime/aws-config/clippy.toml | 1 + clippy.toml | 7 +++++++ rust-runtime/clippy.toml | 1 + 3 files changed, 9 insertions(+) create mode 120000 aws/rust-runtime/aws-config/clippy.toml create mode 100644 clippy.toml create mode 120000 rust-runtime/clippy.toml diff --git a/aws/rust-runtime/aws-config/clippy.toml b/aws/rust-runtime/aws-config/clippy.toml new file mode 120000 index 0000000000..85f6167cb1 --- /dev/null +++ b/aws/rust-runtime/aws-config/clippy.toml @@ -0,0 +1 @@ +../clippy.toml \ No newline at end of file diff --git a/clippy.toml b/clippy.toml new file mode 100644 index 0000000000..6c1918c26d --- /dev/null +++ b/clippy.toml @@ -0,0 +1,7 @@ +disallowed-methods = [ + # fully qualified function/method name: + "std::time::SystemTime::now", + "std::time::SystemTime::elapsed", + "std::time::Instant::now", + "std::time::Instant::elapsed" +] diff --git a/rust-runtime/clippy.toml b/rust-runtime/clippy.toml new file mode 120000 index 0000000000..85f6167cb1 --- /dev/null +++ b/rust-runtime/clippy.toml @@ -0,0 +1 @@ +../clippy.toml \ No newline at end of file