Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change the default runtime mode to orchestrator #2847

Merged
merged 21 commits into from
Jul 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
e717206
Change the default runtime mode to orchestrator
jdisanti Jul 14, 2023
e803842
Fix examples
jdisanti Jul 14, 2023
bb57867
Fix Python examples
jdisanti Jul 14, 2023
8641b04
Fix duplicate endpoint url methods
jdisanti Jul 15, 2023
870b89e
Fix codegen-client tests
jdisanti Jul 17, 2023
bf66ce4
Merge remote-tracking branch 'origin/main' into jdisanti-change-defau…
jdisanti Jul 18, 2023
bd3b0a0
Fix missing prelude scope
jdisanti Jul 18, 2023
95adcff
Fix no-default-features test
jdisanti Jul 18, 2023
f672e54
Fix borrow checker errors in config
jdisanti Jul 18, 2023
f21da3a
Merge remote-tracking branch 'origin/main' into jdisanti-change-defau…
jdisanti Jul 18, 2023
d8100f3
Restore the middleware version of the protocol test generator test
jdisanti Jul 18, 2023
ec46e30
Restore middleware versions of AwsQueryCompatibleTest
jdisanti Jul 18, 2023
f963eb4
Fix aws-config test failure and improve error messages
jdisanti Jul 18, 2023
07180eb
Fix erroneous aws-sig-auth dependency
jdisanti Jul 18, 2023
72ee499
Eliminate `getrandom` dependency to fix `wasm-unknown-unknown`
jdisanti Jul 19, 2023
0b0d488
Fix `fastrand` versioning issue
jdisanti Jul 19, 2023
acf7de5
Fix external types config
jdisanti Jul 19, 2023
ce3ee36
Merge remote-tracking branch 'origin/main' into jdisanti-change-defau…
jdisanti Jul 19, 2023
dc6976b
Fix mutability error
jdisanti Jul 19, 2023
68d6a99
Change default for SDK unit tests
jdisanti Jul 19, 2023
ed4ea9b
Merge remote-tracking branch 'origin/main' into jdisanti-change-defau…
jdisanti Jul 19, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ jobs:
test:
- action: check-aws-sdk-adhoc-tests
runner: ubuntu-latest
# TODO(enableNewSmithyRuntimeCleanup): Remove `check-aws-sdk-orchestrator-impl` when cleaning up middleware
- action: check-aws-sdk-orchestrator-impl
# TODO(enableNewSmithyRuntimeCleanup): Remove `check-aws-sdk-middleware-impl` when cleaning up middleware
- action: check-aws-sdk-middleware-impl
runner: smithy_ubuntu-latest_8-core
- action: check-client-codegen-integration-tests
runner: smithy_ubuntu-latest_8-core
Expand Down
2 changes: 1 addition & 1 deletion aws/rust-runtime/aws-config/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ tokio = { version = "1.13.1", features = ["sync"] }
tracing = { version = "0.1" }

# implementation detail of IMDS credentials provider
fastrand = "1"
fastrand = "2.0.0"

bytes = "1.1.0"
http = "0.2.4"
Expand Down
9 changes: 6 additions & 3 deletions aws/rust-runtime/aws-config/src/connector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@

use aws_smithy_client::erase::DynConnector;

// unused when all crate features are disabled
/// Unwrap an [`Option<DynConnector>`](aws_smithy_client::erase::DynConnector), and panic with a helpful error message if it's `None`
pub(crate) fn expect_connector(connector: Option<DynConnector>) -> DynConnector {
connector.expect("No HTTP connector was available. Enable the `rustls` crate feature or set a connector to fix this.")
pub(crate) fn expect_connector(for_what: &str, connector: Option<DynConnector>) -> DynConnector {
if let Some(conn) = connector {
conn
} else {
panic!("{for_what} require(s) a HTTP connector, but none was available. Enable the `rustls` crate feature or set a connector to fix this.")
}
}

#[cfg(feature = "client-hyper")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,10 @@ impl Builder {
.read_timeout(DEFAULT_READ_TIMEOUT)
.build()
});
let connector = expect_connector(provider_config.connector(&connector_settings));
let connector = expect_connector(
"The HTTP credentials provider",
provider_config.connector(&connector_settings),
);
let mut client_builder = aws_smithy_client::Client::builder()
.connector(connector)
.middleware(Identity::new());
Expand Down
5 changes: 4 additions & 1 deletion aws/rust-runtime/aws-config/src/imds/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,10 @@ impl Builder {
.read_timeout(self.read_timeout.unwrap_or(DEFAULT_READ_TIMEOUT))
.build();
let connector_settings = ConnectorSettings::from_timeout_config(&timeout_config);
let connector = expect_connector(config.connector(&connector_settings));
let connector = expect_connector(
"The IMDS credentials provider",
config.connector(&connector_settings),
);
let endpoint_source = self
.endpoint
.unwrap_or_else(|| EndpointSource::Env(config.clone()));
Expand Down
2 changes: 1 addition & 1 deletion aws/rust-runtime/aws-config/src/imds/credentials.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ impl ImdsCredentialsProvider {
return expiration;
}

let rng = fastrand::Rng::with_seed(
let mut rng = fastrand::Rng::with_seed(
now.duration_since(SystemTime::UNIX_EPOCH)
.expect("now should be after UNIX EPOCH")
.as_secs(),
Expand Down
2 changes: 1 addition & 1 deletion aws/rust-runtime/aws-config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -764,7 +764,7 @@ mod loader {
assert_eq!(Some(&app_name), conf.app_name());
}

#[cfg(aws_sdk_orchestrator_mode)]
#[cfg(all(not(aws_sdk_middleware_mode), feature = "rustls"))]
#[tokio::test]
async fn disable_default_credentials() {
let config = from_env().no_credentials().load().await;
Expand Down
1 change: 1 addition & 0 deletions aws/rust-runtime/aws-config/src/sso.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ impl SsoCredentialsProvider {

let mut sso_config = SsoConfig::builder()
.http_connector(expect_connector(
"The SSO credentials provider",
provider_config.connector(&Default::default()),
))
.retry_config(RetryConfig::standard());
Expand Down
5 changes: 4 additions & 1 deletion aws/rust-runtime/aws-config/src/sts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ use aws_smithy_types::retry::RetryConfig;
impl crate::provider_config::ProviderConfig {
pub(crate) fn sts_client_config(&self) -> StsConfigBuilder {
let mut builder = aws_sdk_sts::Config::builder()
.http_connector(expect_connector(self.connector(&Default::default())))
.http_connector(expect_connector(
"The STS features of aws-config",
self.connector(&Default::default()),
))
.retry_config(RetryConfig::standard())
.region(self.region())
.time_source(self.time_source());
Expand Down
5 changes: 4 additions & 1 deletion aws/rust-runtime/aws-config/src/sts/assume_role.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,10 @@ impl AssumeRoleProviderBuilder {
.credentials_provider(provider)
.time_source(conf.time_source())
.region(self.region.clone())
.http_connector(expect_connector(conf.connector(&Default::default())));
.http_connector(expect_connector(
"The AssumeRole credentials provider",
conf.connector(&Default::default()),
));
config.set_sleep_impl(conf.sleep());

let session_name = self.session_name.unwrap_or_else(|| {
Expand Down
2 changes: 1 addition & 1 deletion aws/rust-runtime/aws-credential-types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ test-util = []
[dependencies]
aws-smithy-async = { path = "../../../rust-runtime/aws-smithy-async" }
aws-smithy-types = { path = "../../../rust-runtime/aws-smithy-types" }
fastrand = "1.4.0"
fastrand = "2.0.0"
tokio = { version = "1.23.1", features = ["sync"] }
tracing = "0.1"
zeroize = "1"
Expand Down
3 changes: 2 additions & 1 deletion aws/rust-runtime/aws-runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ aws-smithy-runtime = { path = "../../../rust-runtime/aws-smithy-runtime" }
aws-smithy-runtime-api = { path = "../../../rust-runtime/aws-smithy-runtime-api" }
aws-smithy-types = { path = "../../../rust-runtime/aws-smithy-types" }
aws-types = { path = "../aws-types" }
fastrand = "2.0.0"
http = "0.2.3"
percent-encoding = "2.1.0"
tracing = "0.1"
uuid = { version = "1", features = ["v4", "fast-rng"] }
uuid = { version = "1" }

[dev-dependencies]
aws-credential-types = { path = "../aws-credential-types", features = ["test-util"] }
Expand Down
119 changes: 89 additions & 30 deletions aws/rust-runtime/aws-runtime/src/invocation_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ use aws_smithy_runtime_api::client::interceptors::Interceptor;
use aws_smithy_types::config_bag::{ConfigBag, Storable, StoreReplace};
use http::{HeaderName, HeaderValue};
use std::fmt::Debug;
use uuid::Uuid;

use aws_smithy_runtime_api::client::runtime_components::RuntimeComponents;
use fastrand::Rng;
use std::sync::Mutex;
#[cfg(feature = "test-util")]
pub use test_util::{NoInvocationIdGenerator, PredefinedInvocationIdGenerator};

Expand Down Expand Up @@ -46,10 +47,43 @@ impl Storable for DynInvocationIdGenerator {
type Storer = StoreReplace<Self>;
}

/// An invocation ID generator that uses random UUIDs for the invocation ID.
#[derive(Debug, Default)]
pub struct DefaultInvocationIdGenerator {
rng: Mutex<Rng>,
}

impl DefaultInvocationIdGenerator {
/// Creates a new [`DefaultInvocationIdGenerator`].
pub fn new() -> Self {
Default::default()
}

/// Creates a [`DefaultInvocationIdGenerator`] with the given seed.
pub fn with_seed(seed: u64) -> Self {
Self {
rng: Mutex::new(Rng::with_seed(seed)),
}
}
}

impl InvocationIdGenerator for DefaultInvocationIdGenerator {
fn generate(&self) -> Result<Option<InvocationId>, BoxError> {
let mut rng = self.rng.lock().unwrap();
let mut random_bytes = [0u8; 16];
rng.fill(&mut random_bytes);

let id = uuid::Builder::from_random_bytes(random_bytes).into_uuid();
Ok(Some(InvocationId::new(id.to_string())))
}
}

/// This interceptor generates a UUID and attaches it to all request attempts made as part of this operation.
#[non_exhaustive]
#[derive(Debug, Default)]
pub struct InvocationIdInterceptor {}
pub struct InvocationIdInterceptor {
default: DefaultInvocationIdGenerator,
}

impl InvocationIdInterceptor {
/// Creates a new `InvocationIdInterceptor`
Expand All @@ -65,13 +99,13 @@ impl Interceptor for InvocationIdInterceptor {
_runtime_components: &RuntimeComponents,
cfg: &mut ConfigBag,
) -> Result<(), BoxError> {
let id = cfg
let gen = cfg
.load::<DynInvocationIdGenerator>()
.map(|gen| gen.generate())
.transpose()?
.flatten();
cfg.interceptor_state()
.store_put::<InvocationId>(id.unwrap_or_default());
.map(|gen| gen as &dyn InvocationIdGenerator)
.unwrap_or(&self.default);
if let Some(id) = gen.generate()? {
cfg.interceptor_state().store_put::<InvocationId>(id);
}

Ok(())
}
Expand All @@ -83,10 +117,9 @@ impl Interceptor for InvocationIdInterceptor {
cfg: &mut ConfigBag,
) -> Result<(), BoxError> {
let headers = ctx.request_mut().headers_mut();
let id = cfg
.load::<InvocationId>()
.ok_or("Expected an InvocationId in the ConfigBag but none was present")?;
headers.append(AMZ_SDK_INVOCATION_ID, id.0.clone());
if let Some(id) = cfg.load::<InvocationId>() {
headers.append(AMZ_SDK_INVOCATION_ID, id.0.clone());
}
Ok(())
}
}
Expand All @@ -96,21 +129,15 @@ impl Interceptor for InvocationIdInterceptor {
pub struct InvocationId(HeaderValue);

impl InvocationId {
/// Create a new, random, invocation ID.
pub fn new() -> Self {
Self::default()
}
}

/// Defaults to a random UUID.
impl Default for InvocationId {
fn default() -> Self {
let id = Uuid::new_v4();
let id = id
.to_string()
.parse()
.expect("UUIDs always produce a valid header value");
Self(id)
/// Create an invocation ID with the given value.
///
/// # Panics
/// This constructor will panic if the given invocation ID is not a valid HTTP header value.
pub fn new(invocation_id: String) -> Self {
Self(
HeaderValue::try_from(invocation_id)
.expect("invocation ID must be a valid HTTP header value"),
)
}
}

Expand Down Expand Up @@ -181,14 +208,14 @@ mod test_util {

#[cfg(test)]
mod tests {
use crate::invocation_id::{InvocationId, InvocationIdInterceptor};
use super::*;
use aws_smithy_http::body::SdkBody;
use aws_smithy_runtime_api::client::interceptors::context::{
BeforeTransmitInterceptorContextMut, InterceptorContext,
};
use aws_smithy_runtime_api::client::interceptors::Interceptor;
use aws_smithy_runtime_api::client::runtime_components::RuntimeComponentsBuilder;
use aws_smithy_types::config_bag::ConfigBag;
use aws_smithy_types::config_bag::{ConfigBag, Layer};
use aws_smithy_types::type_erasure::TypeErasedBox;
use http::HeaderValue;

Expand All @@ -200,7 +227,7 @@ mod tests {
}

#[test]
fn test_id_is_generated_and_set() {
fn default_id_generator() {
let rc = RuntimeComponentsBuilder::for_tests().build().unwrap();
let mut ctx = InterceptorContext::new(TypeErasedBox::doesnt_matter());
ctx.enter_serialization_phase();
Expand All @@ -224,4 +251,36 @@ mod tests {
// UUID should include 32 chars and 4 dashes
assert_eq!(header.len(), 36);
}

#[cfg(feature = "test-util")]
#[test]
fn custom_id_generator() {
let rc = RuntimeComponentsBuilder::for_tests().build().unwrap();
let mut ctx = InterceptorContext::new(TypeErasedBox::doesnt_matter());
ctx.enter_serialization_phase();
ctx.set_request(http::Request::builder().body(SdkBody::empty()).unwrap());
let _ = ctx.take_input();
ctx.enter_before_transmit_phase();

let mut cfg = ConfigBag::base();
let mut layer = Layer::new("test");
layer.store_put(DynInvocationIdGenerator::new(
PredefinedInvocationIdGenerator::new(vec![InvocationId::new(
"the-best-invocation-id".into(),
)]),
));
cfg.push_layer(layer);

let interceptor = InvocationIdInterceptor::new();
let mut ctx = Into::into(&mut ctx);
interceptor
.modify_before_retry_loop(&mut ctx, &rc, &mut cfg)
.unwrap();
interceptor
.modify_before_transmit(&mut ctx, &rc, &mut cfg)
.unwrap();

let header = expect_header(&ctx, "amz-sdk-invocation-id");
assert_eq!("the-best-invocation-id", header);
}
}
4 changes: 2 additions & 2 deletions aws/rust-runtime/aws-types/src/sdk_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ impl Builder {
self
}

/// Set the endpoint url to use when making requests.
/// Set the endpoint URL to use when making requests.
/// # Examples
/// ```
/// use aws_types::SdkConfig;
Expand All @@ -128,7 +128,7 @@ impl Builder {
self
}

/// Set the endpoint url to use when making requests.
/// Set the endpoint URL to use when making requests.
pub fn set_endpoint_url(&mut self, endpoint_url: Option<String>) -> &mut Self {
self.endpoint_url = endpoint_url;
self
Expand Down
2 changes: 1 addition & 1 deletion aws/sdk-adhoc-test/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ dependencies {
implementation("software.amazon.smithy:smithy-aws-traits:$smithyVersion")
}

fun getSmithyRuntimeMode(): String = properties.get("smithy.runtime.mode") ?: "middleware"
fun getSmithyRuntimeMode(): String = properties.get("smithy.runtime.mode") ?: "orchestrator"

val allCodegenTests = listOf(
CodegenTest(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate
import software.amazon.smithy.rust.codegen.core.rustlang.withBlock
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.contextName
import software.amazon.smithy.rust.codegen.core.util.cloneOperation
import software.amazon.smithy.rust.codegen.core.util.expectTrait
Expand Down Expand Up @@ -359,17 +360,18 @@ class AwsPresignedFluentBuilderMethod(
val smithyTypes = RuntimeType.smithyTypes(codegenContext.runtimeConfig)
rustTemplate(
"""
##[derive(Debug)]
##[derive(::std::fmt::Debug)]
struct AlternatePresigningSerializerRuntimePlugin;
impl #{RuntimePlugin} for AlternatePresigningSerializerRuntimePlugin {
fn config(&self) -> Option<#{FrozenLayer}> {
fn config(&self) -> #{Option}<#{FrozenLayer}> {
use #{ConfigBagAccessors};
let mut cfg = #{Layer}::new("presigning_serializer");
cfg.set_request_serializer(#{SharedRequestSerializer}::new(#{AlternateSerializer}));
Some(cfg.freeze())
#{Some}(cfg.freeze())
}
}
""",
*preludeScope,
"AlternateSerializer" to alternateSerializer(operationShape),
"ConfigBagAccessors" to RuntimeType.configBagAccessors(runtimeConfig),
"FrozenLayer" to smithyTypes.resolve("config_bag::FrozenLayer"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,12 +195,8 @@ class CredentialCacheConfig(codegenContext: ClientCodegenContext) : ConfigCustom
rustTemplate(
"""
match (
layer
.load::<#{CredentialsCache}>()
.cloned(),
layer
.load::<#{SharedCredentialsProvider}>()
.cloned(),
resolver.config_mut().load::<#{CredentialsCache}>().cloned(),
resolver.config_mut().load::<#{SharedCredentialsProvider}>().cloned(),
) {
(#{None}, #{None}) => {}
(#{None}, _) => {
Expand All @@ -213,7 +209,7 @@ class CredentialCacheConfig(codegenContext: ClientCodegenContext) : ConfigCustom
#{Some}(credentials_cache),
#{Some}(credentials_provider),
) => {
layer.store_put(credentials_cache.create_cache(credentials_provider));
resolver.config_mut().store_put(credentials_cache.create_cache(credentials_provider));
}
}
""",
Expand Down
Loading