Skip to content

Commit 0faab71

Browse files
author
Anish Cheraku
committed
apiclient: add support for SSM and Secrets Manager ARNs
apiclient apply: Secrets Manager ARN Support and ARN refinements apiclient apply: add unit tests for ARN resolvers code review 4 code review 4.5 code review 5 removed unnecessary comments added a doc comment for Arn::parse()
1 parent bae3701 commit 0faab71

File tree

4 files changed

+413
-84
lines changed

4 files changed

+413
-84
lines changed

sources/Cargo.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sources/api/apiclient/Cargo.toml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,15 @@ serde_json.workspace = true
4545
signal-hook.workspace = true
4646
simplelog.workspace = true
4747
snafu = { workspace = true, features = ["futures"] }
48-
test-case.workspace = true
4948
tokio = { workspace = true, features = ["fs", "io-std", "io-util", "macros", "rt-multi-thread", "time"] }
5049
tokio-tungstenite = { workspace = true, features = ["connect"] }
5150
toml.workspace = true
5251
unindent.workspace = true
5352
url.workspace = true
54-
aws-smithy-runtime-api.workspace = true
55-
tempfile.workspace = true
5653

5754
[build-dependencies]
5855
generate-readme.workspace = true
56+
57+
[dev-dependencies]
58+
tempfile.workspace = true
59+
test-case.workspace = true

sources/api/apiclient/src/apply.rs

Lines changed: 41 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,13 @@ pub struct SettingsInput {
7474
impl SettingsInput {
7575
pub(crate) fn new(input: impl Into<String>) -> Self {
7676
let input = input.into();
77-
let parsed_url = Url::parse(&input).ok();
77+
let parsed_url = match Url::parse(&input) {
78+
Ok(url) => Some(url),
79+
Err(err) => {
80+
log::debug!("URL parse failed for '{}': {}", input, err);
81+
None
82+
}
83+
};
7884
SettingsInput { input, parsed_url }
7985
}
8086
}
@@ -89,39 +95,33 @@ where
8995
resolver.resolve().await.context(ResolverFailureSnafu)
9096
}
9197

98+
/// Macro to try multiple settings resolver types in sequence, returning the first one that succeeds.
99+
macro_rules! try_resolvers {
100+
($input:expr, $($resolver_type:ty),+ $(,)?) => {
101+
$(
102+
if let Ok(r) = <$resolver_type>::try_from($input) {
103+
log::debug!("select_resolver: picked {}", stringify!($resolver_type));
104+
return Ok(Box::new(r));
105+
}
106+
)+
107+
};
108+
}
109+
92110
/// Choose which UriResolver applies to `input` (stdin, file://, http(s)://, s3://, secretsmanager://, and ssm://).
93111
fn select_resolver(input: &SettingsInput) -> Result<Box<dyn crate::uri_resolver::UriResolver>> {
94-
use crate::uri_resolver;
95-
96-
// stdin ("-")
97-
if let Ok(r) = uri_resolver::StdinUri::try_from(input) {
98-
return Ok(Box::new(r));
99-
}
100-
101-
// file://
102-
if let Ok(r) = uri_resolver::FileUri::try_from(input) {
103-
return Ok(Box::new(r));
104-
}
105-
106-
// http(s)://
107-
if let Ok(r) = uri_resolver::HttpUri::try_from(input) {
108-
return Ok(Box::new(r));
109-
}
110-
111-
// s3://
112-
if let Ok(r) = uri_resolver::S3Uri::try_from(input) {
113-
return Ok(Box::new(r));
114-
}
115-
116-
// secretsmanager://
117-
if let Ok(r) = uri_resolver::SecretsManagerUri::try_from(input) {
118-
return Ok(Box::new(r));
119-
}
120-
121-
// ssm://
122-
if let Ok(r) = uri_resolver::SsmUri::try_from(input) {
123-
return Ok(Box::new(r));
124-
}
112+
use crate::uri_resolver::*;
113+
114+
try_resolvers!(
115+
input,
116+
StdinUri,
117+
FileUri,
118+
HttpUri,
119+
S3Uri,
120+
SecretsManagerArn,
121+
SecretsManagerUri,
122+
SsmArn,
123+
SsmUri,
124+
);
125125

126126
error::NoResolverSnafu {
127127
input_source: input.input.clone(),
@@ -266,13 +266,15 @@ mod resolver_selection_tests {
266266
use std::any::{Any, TypeId};
267267
use test_case::test_case;
268268

269-
#[test_case("-", TypeId::of::<crate::uri_resolver::StdinUri>(); "stdin")]
270-
#[test_case("file:///tmp/folder", TypeId::of::<crate::uri_resolver::FileUri>(); "file")]
271-
#[test_case("http://amazon.com", TypeId::of::<crate::uri_resolver::HttpUri>(); "http")]
272-
#[test_case("https://amazon.com", TypeId::of::<crate::uri_resolver::HttpUri>(); "https")]
273-
#[test_case("s3://mybucket/path", TypeId::of::<crate::uri_resolver::S3Uri>(); "s3")]
274-
#[test_case("secretsmanager://sec", TypeId::of::<crate::uri_resolver::SecretsManagerUri>(); "secrets")]
275-
#[test_case("ssm://param", TypeId::of::<crate::uri_resolver::SsmUri>(); "ssm")]
269+
#[test_case("-", TypeId::of::<crate::uri_resolver::StdinUri>(); "stdin")]
270+
#[test_case("file:///tmp/folder", TypeId::of::<crate::uri_resolver::FileUri>(); "file")]
271+
#[test_case("http://amazon.com", TypeId::of::<crate::uri_resolver::HttpUri>(); "http")]
272+
#[test_case("https://amazon.com", TypeId::of::<crate::uri_resolver::HttpUri>(); "https")]
273+
#[test_case("s3://mybucket/path", TypeId::of::<crate::uri_resolver::S3Uri>(); "s3")]
274+
#[test_case("secretsmanager://sec", TypeId::of::<crate::uri_resolver::SecretsManagerUri>(); "secrets")]
275+
#[test_case("ssm://param", TypeId::of::<crate::uri_resolver::SsmUri>(); "ssmUri")]
276+
#[test_case("arn:aws:ssm:<region>:<account_id>:parameter/<name>", TypeId::of::<crate::uri_resolver::SsmArn>(); "ssmArn")]
277+
#[test_case("arn:aws:secretsmanager:<region>:<account-id>:secret:<secret-id>", TypeId::of::<crate::uri_resolver::SecretsManagerArn>(); "secretsmanagerArn")]
276278

277279
fn resolver_selection(input: &str, expected: std::any::TypeId) {
278280
let settings = SettingsInput::new(input);

0 commit comments

Comments
 (0)