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

update AWS runtime crates for request compression #3632

Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
2 changes: 1 addition & 1 deletion aws/rust-runtime/aws-config/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "aws-config"
version = "1.4.0"
version = "1.5.0"
authors = [
"AWS Rust SDK Team <aws-sdk-rust@amazon.com>",
"Russell Cohen <rcoh@amazon.com>",
Expand Down
6 changes: 6 additions & 0 deletions aws/rust-runtime/aws-config/src/default_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,9 @@ pub mod ignore_configured_endpoint_urls;

/// Default endpoint URL provider chain
pub mod endpoint_url;

/// Default "disable request compression" provider chain
pub mod disable_request_compression;

/// Default "request minimum compression size bytes" provider chain
pub mod request_min_compression_size_bytes;
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

use crate::environment::parse_bool;
use crate::provider_config::ProviderConfig;
use aws_runtime::env_config::EnvConfigValue;
use aws_smithy_types::error::display::DisplayErrorContext;

mod env {
pub(super) const DISABLE_REQUEST_COMPRESSION: &str = "AWS_DISABLE_REQUEST_COMPRESSION";
}

mod profile_key {
pub(super) const DISABLE_REQUEST_COMPRESSION: &str = "disable_request_compression";
}

/// Load the value for "disable request compression".
///
/// This checks the following sources:
/// 1. The environment variable `AWS_DISABLE_REQUEST_COMPRESSION=true/false`
/// 2. The profile key `disable_request_compression=true/false`
///
/// If invalid values are found, the provider will return None and an error will be logged.
pub async fn disable_request_compression_provider(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems odd to me these end up being public to the world but that seems to be the pattern here. I would have thought pub crate.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was doing it to match the other providers but I don't mind making them pub(crate). We can always undo that later if we decide to.

provider_config: &ProviderConfig,
) -> Option<bool> {
let env = provider_config.env();
let profiles = provider_config.profile().await;

EnvConfigValue::new()
.env(env::DISABLE_REQUEST_COMPRESSION)
.profile(profile_key::DISABLE_REQUEST_COMPRESSION)
.validate(&env, profiles, parse_bool)
.map_err(
|err| tracing::warn!(err = %DisplayErrorContext(&err), "invalid value for `disable request compression` setting"),
)
.unwrap_or(None)
}

#[cfg(test)]
mod test {
use super::disable_request_compression_provider;
#[allow(deprecated)]
use crate::profile::profile_file::{ProfileFileKind, ProfileFiles};
use crate::provider_config::ProviderConfig;
use aws_types::os_shim_internal::{Env, Fs};
use tracing_test::traced_test;

#[tokio::test]
#[traced_test]
async fn log_error_on_invalid_value() {
let conf = ProviderConfig::empty().with_env(Env::from_slice(&[(
"AWS_DISABLE_REQUEST_COMPRESSION",
"not-a-boolean",
)]));
assert_eq!(disable_request_compression_provider(&conf).await, None);
assert!(logs_contain(
"invalid value for `disable request compression` setting"
));
assert!(logs_contain("AWS_DISABLE_REQUEST_COMPRESSION"));
}

#[tokio::test]
#[traced_test]
async fn environment_priority() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe EnvConfigValue itself has already been tested that way, but maybe we should also add a test making sure a value is correctly loaded from a profile config when disabling is only specified in a shared config file, but not set in the environment variable?

let conf = ProviderConfig::empty()
.with_env(Env::from_slice(&[(
"AWS_DISABLE_REQUEST_COMPRESSION",
"TRUE",
)]))
.with_profile_config(
Some(
#[allow(deprecated)]
ProfileFiles::builder()
.with_file(
#[allow(deprecated)]
ProfileFileKind::Config,
"conf",
)
.build(),
),
None,
)
.with_fs(Fs::from_slice(&[(
"conf",
"[default]\ndisable_request_compression = false",
)]));
assert_eq!(
disable_request_compression_provider(&conf).await,
Some(true)
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

use crate::environment::parse_uint;
use crate::provider_config::ProviderConfig;
use aws_runtime::env_config::EnvConfigValue;
use aws_smithy_types::error::display::DisplayErrorContext;

mod env {
pub(super) const REQUEST_MIN_COMPRESSION_SIZE_BYTES: &str =
"AWS_REQUEST_MIN_COMPRESSION_SIZE_BYTES";
}

mod profile_key {
pub(super) const REQUEST_MIN_COMPRESSION_SIZE_BYTES: &str =
"request_min_compression_size_bytes";
}

/// Load the value for "request minimum compression size bytes".
///
/// This checks the following sources:
/// 1. The environment variable `AWS_REQUEST_MIN_COMPRESSION_SIZE_BYTES=10240`
/// 2. The profile key `request_min_compression_size_bytes=10240`
///
/// If invalid values are found, the provider will return None and an error will be logged.
pub async fn request_min_compression_size_bytes_provider(
provider_config: &ProviderConfig,
) -> Option<u32> {
let env = provider_config.env();
let profiles = provider_config.profile().await;

EnvConfigValue::new()
.env(env::REQUEST_MIN_COMPRESSION_SIZE_BYTES)
.profile(profile_key::REQUEST_MIN_COMPRESSION_SIZE_BYTES)
.validate(&env, profiles, parse_uint)
.map_err(
|err| tracing::warn!(err = %DisplayErrorContext(&err), "invalid value for `request minimum compression size bytes` setting"),
)
.unwrap_or(None)
}

#[cfg(test)]
mod test {
use super::request_min_compression_size_bytes_provider;
#[allow(deprecated)]
use crate::profile::profile_file::{ProfileFileKind, ProfileFiles};
use crate::provider_config::ProviderConfig;
use aws_types::os_shim_internal::{Env, Fs};
use tracing_test::traced_test;

#[tokio::test]
#[traced_test]
async fn log_error_on_invalid_value() {
let conf = ProviderConfig::empty().with_env(Env::from_slice(&[(
"AWS_REQUEST_MIN_COMPRESSION_SIZE_BYTES",
"not-a-uint",
)]));
assert_eq!(
request_min_compression_size_bytes_provider(&conf).await,
None
);
assert!(logs_contain(
"invalid value for `request minimum compression size bytes` setting"
));
assert!(logs_contain("AWS_REQUEST_MIN_COMPRESSION_SIZE_BYTES"));
}

#[tokio::test]
#[traced_test]
async fn environment_priority() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The above comment regarding testing against a shared config file also applies here?

let conf = ProviderConfig::empty()
.with_env(Env::from_slice(&[(
"AWS_REQUEST_MIN_COMPRESSION_SIZE_BYTES",
"99",
)]))
.with_profile_config(
Some(
#[allow(deprecated)]
ProfileFiles::builder()
.with_file(
#[allow(deprecated)]
ProfileFileKind::Config,
"conf",
)
.build(),
),
None,
)
.with_fs(Fs::from_slice(&[(
"conf",
"[default]\nrequest_min_compression_size_bytes = 100",
)]));
assert_eq!(
request_min_compression_size_bytes_provider(&conf).await,
Some(99)
);
}
}
19 changes: 19 additions & 0 deletions aws/rust-runtime/aws-config/src/environment/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,25 @@ pub(crate) fn parse_bool(value: &str) -> Result<bool, InvalidBooleanValue> {
}
}

#[derive(Debug)]
pub(crate) struct InvalidUintValue {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume we only enforce non_exhaustive if a struct is public outside of its containing crate?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct. If it's not public then we don't have to worry about forwards compatibility.

value: String,
}

impl fmt::Display for InvalidUintValue {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{} is not a valid u32", self.value)
}
}

impl Error for InvalidUintValue {}

pub(crate) fn parse_uint(value: &str) -> Result<u32, InvalidUintValue> {
value.parse::<u32>().map_err(|_| InvalidUintValue {
value: value.to_string(),
})
}

#[derive(Debug)]
pub(crate) struct InvalidUrlValue {
value: String,
Expand Down
60 changes: 57 additions & 3 deletions aws/rust-runtime/aws-config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,8 @@ mod loader {
use aws_types::SdkConfig;

use crate::default_provider::{
app_name, credentials, endpoint_url, ignore_configured_endpoint_urls as ignore_ep, region,
app_name, credentials, disable_request_compression, endpoint_url,
ignore_configured_endpoint_urls as ignore_ep, region, request_min_compression_size_bytes,
retry_config, timeout_config, use_dual_stack, use_fips,
};
use crate::meta::region::ProvideRegion;
Expand Down Expand Up @@ -274,6 +275,8 @@ mod loader {
use_fips: Option<bool>,
use_dual_stack: Option<bool>,
time_source: Option<SharedTimeSource>,
disable_request_compression: Option<bool>,
request_min_compression_size_bytes: Option<u32>,
stalled_stream_protection_config: Option<StalledStreamProtectionConfig>,
env: Option<Env>,
fs: Option<Fs>,
Expand Down Expand Up @@ -654,6 +657,18 @@ mod loader {
self
}

#[doc = docs_for!(disable_request_compression)]
pub fn disable_request_compression(mut self, disable_request_compression: bool) -> Self {
self.disable_request_compression = Some(disable_request_compression);
self
}

#[doc = docs_for!(request_min_compression_size_bytes)]
pub fn request_min_compression_size_bytes(mut self, size: u32) -> Self {
self.request_min_compression_size_bytes = Some(size);
self
}

/// Override the [`StalledStreamProtectionConfig`] used to build [`SdkConfig`].
///
/// This configures stalled stream protection. When enabled, download streams
Expand Down Expand Up @@ -771,6 +786,22 @@ mod loader {
.await
};

let disable_request_compression = if self.disable_request_compression.is_some() {
self.disable_request_compression
} else {
disable_request_compression::disable_request_compression_provider(&conf).await
};

let request_min_compression_size_bytes =
if self.request_min_compression_size_bytes.is_some() {
self.request_min_compression_size_bytes
} else {
request_min_compression_size_bytes::request_min_compression_size_bytes_provider(
&conf,
)
.await
};

let base_config = timeout_config::default_provider()
.configure(&conf)
.timeout_config()
Expand Down Expand Up @@ -846,8 +877,8 @@ mod loader {
v
}
};
builder.set_endpoint_url(endpoint_url);

builder.set_endpoint_url(endpoint_url);
builder.set_behavior_version(self.behavior_version);
builder.set_http_client(self.http_client);
builder.set_app_name(app_name);
Expand All @@ -868,6 +899,8 @@ mod loader {
builder.set_sleep_impl(sleep_impl);
builder.set_use_fips(use_fips);
builder.set_use_dual_stack(use_dual_stack);
builder.set_disable_request_compression(disable_request_compression);
builder.set_request_min_compression_size_bytes(request_min_compression_size_bytes);
builder.set_stalled_stream_protection(self.stalled_stream_protection_config);
builder.build()
}
Expand Down Expand Up @@ -1038,7 +1071,7 @@ mod loader {
}

#[tokio::test]
async fn load_fips() {
async fn load_use_fips() {
let conf = base_conf().use_fips(true).load().await;
assert_eq!(Some(true), conf.use_fips());
}
Expand All @@ -1052,6 +1085,27 @@ mod loader {
assert_eq!(None, conf.use_dual_stack());
}

#[tokio::test]
async fn load_disable_request_compression() {
let conf = base_conf().disable_request_compression(true).load().await;
assert_eq!(Some(true), conf.disable_request_compression());

let conf = base_conf().load().await;
assert_eq!(None, conf.disable_request_compression());
}

#[tokio::test]
async fn load_request_min_compression_size_bytes() {
let conf = base_conf()
.request_min_compression_size_bytes(99)
.load()
.await;
assert_eq!(Some(99), conf.request_min_compression_size_bytes());

let conf = base_conf().load().await;
assert_eq!(None, conf.request_min_compression_size_bytes());
}

#[tokio::test]
async fn app_name() {
let app_name = AppName::new("my-app-name").unwrap();
Expand Down
Loading