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

Revamp errors in aws-smithy-types #1893

Merged
merged 1 commit into from
Nov 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
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
5 changes: 3 additions & 2 deletions aws/rust-runtime/aws-config/external-types.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ allowed_external_types = [
"aws_smithy_types::retry",
"aws_smithy_types::retry::*",
"aws_smithy_types::timeout",
"aws_smithy_types::timeout::config::TimeoutConfig",
"aws_smithy_types::timeout::error::ConfigError",
"aws_smithy_types::timeout::OperationTimeoutConfig",
"aws_smithy_types::timeout::TimeoutConfig",
"aws_smithy_types::timeout::TimeoutConfigBuilder",
"aws_types::*",
"http::response::Response",
"http::uri::Uri",
Expand Down
7 changes: 5 additions & 2 deletions aws/rust-runtime/aws-config/src/default_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
* SPDX-License-Identifier: Apache-2.0
*/

//! Default Provider chains for [`region`](default_provider::region), [`credentials`](default_provider::credentials),
//! [retries](default_provider::retry_config), [timeouts](default_provider::timeout_config) and [app name](default_provider::app_name).
//! Providers that implement the default AWS provider chain
//!
//! Default Provider chains for [`region`](crate::default_provider::region), [`credentials`](crate::default_provider::credentials),
//! [retries](crate::default_provider::retry_config), [timeouts](crate::default_provider::timeout_config) and
//! [app name](crate::default_provider::app_name).
//!
//! Typically, this module is used via [`load_from_env`](crate::load_from_env) or [`from_env`](crate::from_env). It should only be used directly
//! if you need to set custom configuration options to override the default resolution chain.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
* SPDX-License-Identifier: Apache-2.0
*/

use aws_smithy_types::retry::RetryConfig;

use crate::environment::retry_config::EnvironmentVariableRetryConfigProvider;
use crate::profile;
use crate::provider_config::ProviderConfig;
use aws_smithy_types::error::display::DisplayErrorContext;
use aws_smithy_types::retry::RetryConfig;

/// Default RetryConfig Provider chain
///
Expand Down Expand Up @@ -90,11 +90,11 @@ impl Builder {
// We match this instead of unwrapping so we can print the error with the `Display` impl instead of the `Debug` impl that unwrap uses
let builder_from_env = match self.env_provider.retry_config_builder() {
Ok(retry_config_builder) => retry_config_builder,
Err(err) => panic!("{}", err),
Err(err) => panic!("{}", DisplayErrorContext(&err)),
};
let builder_from_profile = match self.profile_file.build().retry_config_builder().await {
Ok(retry_config_builder) => retry_config_builder,
Err(err) => panic!("{}", err),
Err(err) => panic!("{}", DisplayErrorContext(&err)),
};

builder_from_env
Expand Down
2 changes: 2 additions & 0 deletions aws/rust-runtime/aws-config/src/environment/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
* SPDX-License-Identifier: Apache-2.0
*/

//! Providers that load configuration from environment variables

/// Load app name from the environment
pub mod app_name;
pub use app_name::EnvironmentVariableAppNameProvider;
Expand Down
39 changes: 24 additions & 15 deletions aws/rust-runtime/aws-config/src/environment/retry_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
* SPDX-License-Identifier: Apache-2.0
*/

use std::str::FromStr;

use aws_smithy_types::retry::{RetryConfigBuilder, RetryConfigErr, RetryMode};
use crate::retry::{
error::RetryConfigError, error::RetryConfigErrorKind, RetryConfigBuilder, RetryMode,
};
use aws_types::os_shim_internal::Env;
use std::str::FromStr;

const ENV_VAR_MAX_ATTEMPTS: &str = "AWS_MAX_ATTEMPTS";
const ENV_VAR_RETRY_MODE: &str = "AWS_RETRY_MODE";
Expand Down Expand Up @@ -35,20 +36,22 @@ impl EnvironmentVariableRetryConfigProvider {
}

/// Attempt to create a new `RetryConfig` from environment variables
pub fn retry_config_builder(&self) -> Result<RetryConfigBuilder, RetryConfigErr> {
pub fn retry_config_builder(&self) -> Result<RetryConfigBuilder, RetryConfigError> {
let max_attempts = match self.env.get(ENV_VAR_MAX_ATTEMPTS).ok() {
Some(max_attempts) => match max_attempts.parse::<u32>() {
Ok(max_attempts) if max_attempts == 0 => {
return Err(RetryConfigErr::MaxAttemptsMustNotBeZero {
return Err(RetryConfigErrorKind::MaxAttemptsMustNotBeZero {
set_by: "environment variable".into(),
});
}
.into());
}
Ok(max_attempts) => Some(max_attempts),
Err(source) => {
return Err(RetryConfigErr::FailedToParseMaxAttempts {
return Err(RetryConfigErrorKind::FailedToParseMaxAttempts {
set_by: "environment variable".into(),
source,
});
}
.into());
}
},
None => None,
Expand All @@ -58,10 +61,11 @@ impl EnvironmentVariableRetryConfigProvider {
Ok(retry_mode) => match RetryMode::from_str(&retry_mode) {
Ok(retry_mode) => Some(retry_mode),
Err(retry_mode_err) => {
return Err(RetryConfigErr::InvalidRetryMode {
return Err(RetryConfigErrorKind::InvalidRetryMode {
set_by: "environment variable".into(),
source: retry_mode_err,
});
}
.into());
}
},
Err(_) => None,
Expand All @@ -78,10 +82,11 @@ impl EnvironmentVariableRetryConfigProvider {

#[cfg(test)]
mod test {
use aws_smithy_types::retry::{RetryConfig, RetryConfigErr, RetryMode};
use aws_types::os_shim_internal::Env;

use super::{EnvironmentVariableRetryConfigProvider, ENV_VAR_MAX_ATTEMPTS, ENV_VAR_RETRY_MODE};
use crate::retry::{
error::RetryConfigError, error::RetryConfigErrorKind, RetryConfig, RetryMode,
};
use aws_types::os_shim_internal::Env;

fn test_provider(vars: &[(&str, &str)]) -> EnvironmentVariableRetryConfigProvider {
EnvironmentVariableRetryConfigProvider::new_with_env(Env::from_slice(vars))
Expand Down Expand Up @@ -112,7 +117,9 @@ mod test {
test_provider(&[(ENV_VAR_MAX_ATTEMPTS, "not an integer")])
.retry_config_builder()
.unwrap_err(),
RetryConfigErr::FailedToParseMaxAttempts { .. }
RetryConfigError {
kind: RetryConfigErrorKind::FailedToParseMaxAttempts { .. }
}
));
}

Expand Down Expand Up @@ -148,7 +155,9 @@ mod test {
.unwrap_err();
assert!(matches!(
err,
RetryConfigErr::MaxAttemptsMustNotBeZero { .. }
RetryConfigError {
kind: RetryConfigErrorKind::MaxAttemptsMustNotBeZero { .. }
}
));
}
}
46 changes: 14 additions & 32 deletions aws/rust-runtime/aws-config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
unreachable_pub
)]

//! `aws-config` provides implementations of region, credential resolution.
//! `aws-config` provides implementations of region and credential resolution.
//!
//! These implementations can be used either via the default chain implementation
//! [`from_env`]/[`ConfigLoader`] or ad-hoc individual credential and region providers.
Expand Down Expand Up @@ -92,9 +92,6 @@
//! ```

pub use aws_smithy_http::endpoint;
// Re-export types from smithy-types
pub use aws_smithy_types::retry;
pub use aws_smithy_types::timeout;
// Re-export types from aws-types
pub use aws_types::{
app_name::{AppName, InvalidAppName},
Expand All @@ -106,43 +103,28 @@ pub use loader::ConfigLoader;
#[allow(dead_code)]
const PKG_VERSION: &str = env!("CARGO_PKG_VERSION");

/// Providers that implement the default AWS provider chain
pub mod default_provider;

/// Providers that load configuration from environment variables
pub mod environment;

/// Meta-providers that augment existing providers with new behavior
pub mod meta;

pub mod profile;

pub mod sts;

#[cfg(test)]
mod test_case;

pub mod web_identity_token;

pub mod ecs;

pub mod provider_config;

mod cache;

pub mod imds;

mod json_credentials;

mod fs_util;

mod http_credential_provider;

pub mod sso;
mod json_credentials;

pub mod connector;

pub mod credential_process;
pub mod default_provider;
pub mod ecs;
pub mod environment;
pub mod imds;
pub mod meta;
pub mod profile;
pub mod provider_config;
pub mod retry;
pub mod sso;
pub mod sts;
pub mod timeout;
pub mod web_identity_token;

/// Create an environment loader for AWS Configuration
///
Expand Down
3 changes: 2 additions & 1 deletion aws/rust-runtime/aws-config/src/meta/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

pub mod region;
//! Meta-providers that augment existing providers with new behavior

pub mod credentials;
pub mod region;
2 changes: 1 addition & 1 deletion aws/rust-runtime/aws-config/src/profile/parser/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ struct Location {
}

/// An error encountered while parsing a profile
#[derive(Debug, Clone)]
#[derive(Debug)]
pub struct ProfileParseError {
/// Location where this error occurred
location: Location,
Expand Down
21 changes: 13 additions & 8 deletions aws/rust-runtime/aws-config/src/profile/retry_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@

use crate::profile::profile_file::ProfileFiles;
use crate::provider_config::ProviderConfig;
use crate::retry::{
error::RetryConfigError, error::RetryConfigErrorKind, RetryConfigBuilder, RetryMode,
};
use aws_smithy_types::error::display::DisplayErrorContext;
use aws_smithy_types::retry::{RetryConfigBuilder, RetryConfigErr, RetryMode};
use aws_types::os_shim_internal::{Env, Fs};
use std::str::FromStr;

Expand Down Expand Up @@ -101,7 +103,7 @@ impl ProfileFileRetryConfigProvider {
}

/// Attempt to create a new RetryConfigBuilder from a profile file.
pub async fn retry_config_builder(&self) -> Result<RetryConfigBuilder, RetryConfigErr> {
pub async fn retry_config_builder(&self) -> Result<RetryConfigBuilder, RetryConfigError> {
let profile = match super::parser::load(&self.fs, &self.env, &self.profile_files).await {
Ok(profile) => profile,
Err(err) => {
Expand Down Expand Up @@ -130,16 +132,18 @@ impl ProfileFileRetryConfigProvider {
let max_attempts = match selected_profile.get("max_attempts") {
Some(max_attempts) => match max_attempts.parse::<u32>() {
Ok(max_attempts) if max_attempts == 0 => {
return Err(RetryConfigErr::MaxAttemptsMustNotBeZero {
return Err(RetryConfigErrorKind::MaxAttemptsMustNotBeZero {
set_by: "aws profile".into(),
});
}
.into());
}
Ok(max_attempts) => Some(max_attempts),
Err(source) => {
return Err(RetryConfigErr::FailedToParseMaxAttempts {
return Err(RetryConfigErrorKind::FailedToParseMaxAttempts {
set_by: "aws profile".into(),
source,
});
}
.into());
}
},
None => None,
Expand All @@ -149,10 +153,11 @@ impl ProfileFileRetryConfigProvider {
Some(retry_mode) => match RetryMode::from_str(retry_mode) {
Ok(retry_mode) => Some(retry_mode),
Err(retry_mode_err) => {
return Err(RetryConfigErr::InvalidRetryMode {
return Err(RetryConfigErrorKind::InvalidRetryMode {
set_by: "aws profile".into(),
source: retry_mode_err,
});
}
.into());
}
},
None => None,
Expand Down
87 changes: 87 additions & 0 deletions aws/rust-runtime/aws-config/src/retry.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

//! Retry configuration

// Re-export from aws-smithy-types
pub use aws_smithy_types::retry::ErrorKind;
pub use aws_smithy_types::retry::ProvideErrorKind;
pub use aws_smithy_types::retry::RetryConfig;
pub use aws_smithy_types::retry::RetryConfigBuilder;
pub use aws_smithy_types::retry::RetryKind;
pub use aws_smithy_types::retry::RetryMode;

/// Errors for retry configuration
pub mod error {
use std::borrow::Cow;
use std::fmt;
use std::num::ParseIntError;

// Re-export from aws-smithy-types
pub use aws_smithy_types::retry::RetryModeParseError;

#[derive(Debug)]
pub(crate) enum RetryConfigErrorKind {
/// The configured retry mode wasn't recognized.
InvalidRetryMode {
/// Cause of the error.
source: RetryModeParseError,
/// Where the invalid retry mode value originated from.
set_by: Cow<'static, str>,
},
/// Max attempts must be greater than zero.
MaxAttemptsMustNotBeZero {
/// Where the invalid max attempts value originated from.
set_by: Cow<'static, str>,
},
/// The max attempts value couldn't be parsed to an integer.
FailedToParseMaxAttempts {
/// Cause of the error.
source: ParseIntError,
/// Where the invalid max attempts value originated from.
set_by: Cow<'static, str>,
},
}

/// Failure to parse retry config from profile file or environment variable.
#[derive(Debug)]
pub struct RetryConfigError {
pub(crate) kind: RetryConfigErrorKind,
}

impl fmt::Display for RetryConfigError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use RetryConfigErrorKind::*;
match &self.kind {
InvalidRetryMode { set_by, .. } => {
write!(f, "invalid configuration set by {set_by}")
}
MaxAttemptsMustNotBeZero { set_by } => {
write!(f, "invalid configuration set by {set_by}: It is invalid to set max attempts to 0. Unset it or set it to an integer greater than or equal to one.")
}
FailedToParseMaxAttempts { set_by, .. } => {
write!(f, "failed to parse max attempts set by {set_by}",)
}
}
}
}

impl std::error::Error for RetryConfigError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
use RetryConfigErrorKind::*;
match &self.kind {
InvalidRetryMode { source, .. } => Some(source),
FailedToParseMaxAttempts { source, .. } => Some(source),
MaxAttemptsMustNotBeZero { .. } => None,
}
}
}

impl From<RetryConfigErrorKind> for RetryConfigError {
fn from(kind: RetryConfigErrorKind) -> Self {
Self { kind }
}
}
}
Loading