Skip to content

Commit 42b02d0

Browse files
Anish Cherakuanishcheraku
authored andcommitted
address code review suggestions 2
1 parent 2dcca21 commit 42b02d0

File tree

4 files changed

+191
-161
lines changed

4 files changed

+191
-161
lines changed

sources/Cargo.lock

Lines changed: 2 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: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ fips = ["tls", "aws-lc-rs/fips", "rustls/fips"]
1616

1717
[dependencies]
1818
async-trait.workspace = true
19-
aws-smithy-types.workspace = true
2019
aws-config.workspace = true
2120
aws-lc-rs = { workspace = true, optional = true, features = ["bindgen"] }
2221
aws-sdk-s3.workspace = true
@@ -37,14 +36,15 @@ log.workspace = true
3736
models.workspace = true
3837
nix.workspace = true
3938
rand = { workspace = true, features = ["default"] }
40-
reqwest.workspace = true
39+
reqwest.workspace = true
4140
retry-read.workspace = true
4241
rustls = { workspace = true, optional = true }
4342
serde = { workspace = true, features = ["derive"] }
4443
serde_json.workspace = true
4544
signal-hook.workspace = true
4645
simplelog.workspace = true
4746
snafu = { workspace = true, features = ["futures"] }
47+
test-case = "*"
4848
tokio = { workspace = true, features = ["fs", "io-std", "io-util", "macros", "rt-multi-thread", "time"] }
4949
tokio-tungstenite = { workspace = true, features = ["connect"] }
5050
toml.workspace = true

sources/api/apiclient/src/apply.rs

Lines changed: 34 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! This module allows application of settings from URIs or stdin. The inputs are expected to be
22
//! TOML settings files, in the same format as user data, or the JSON equivalent. The inputs are
33
//! pulled and applied to the API server in a single transaction.
4-
use aws_sdk_secretsmanager::config::http::HttpResponse as SdkHttpResponse;
4+
use crate::apply::error::ResolverFailureSnafu;
55
use crate::rando;
66
use futures::future::{join, ready};
77
use futures::stream::{self, StreamExt};
@@ -11,7 +11,6 @@ use snafu::{OptionExt, ResultExt};
1111
use std::convert::TryFrom;
1212
use std::path::Path;
1313

14-
1514
/// Reads settings in TOML or JSON format from files at the requested URIs (or from stdin, if given
1615
/// "-"), then commits them in a single transaction and applies them to the system.
1716
pub async fn apply<P>(socket_path: P, input_sources: Vec<String>) -> Result<()>
@@ -67,53 +66,65 @@ where
6766
Ok(())
6867
}
6968

69+
/// Holds the raw input string and (if it parses) the URL.
70+
pub struct SettingsInput {
71+
pub input: String,
72+
pub parsed_url: Option<Url>,
73+
}
74+
impl SettingsInput {
75+
pub(crate) fn new(input: impl Into<String>) -> Self {
76+
let input = input.into();
77+
let parsed_url = Url::parse(&input).ok();
78+
SettingsInput { input, parsed_url }
79+
}
80+
}
81+
7082
/// Retrieves the given source location and returns the result in a String.
7183
async fn get<S>(input_source: S) -> Result<String>
7284
where
7385
S: AsRef<str>,
7486
{
75-
let resolver = select_resolver(input_source.as_ref())?;
76-
resolver.resolve().await
87+
let settings = SettingsInput::new(input_source.as_ref());
88+
let resolver = select_resolver(&settings)?;
89+
resolver.resolve().await.context(ResolverFailureSnafu)
7790
}
7891

92+
/// Choose which UriResolver applies to `input` (stdin, file://, http(s)://, s3://, secretsmanager://, and ssm://).
93+
fn select_resolver(input: &SettingsInput) -> Result<Box<dyn crate::uri_resolver::UriResolver>> {
94+
use crate::uri_resolver;
7995

80-
/// Choose which UriResolver applies to `input` (stdin, file://, http(s):// or s3://).
81-
fn select_resolver(input: &str) -> Result<Box<dyn crate::uri_resolver::UriResolver>> {
82-
// "-" → stdin
83-
if let Ok(r) = crate::uri_resolver::StdinUri::try_from(input) {
96+
// stdin ("-")
97+
if let Ok(r) = uri_resolver::StdinUri::try_from(input) {
8498
return Ok(Box::new(r));
8599
}
86100

87-
// parse as a URL
88-
let url = Url::parse(input).context(error::UriSnafu { input_source: input.to_string() })?;
89-
90101
// file://
91-
if let Ok(r) = crate::uri_resolver::FileUri::try_from(&url) {
102+
if let Ok(r) = uri_resolver::FileUri::try_from(input) {
92103
return Ok(Box::new(r));
93104
}
94105

95106
// http(s)://
96-
if let Ok(r) = crate::uri_resolver::HttpUri::try_from(url.clone()) {
107+
if let Ok(r) = uri_resolver::HttpUri::try_from(input) {
97108
return Ok(Box::new(r));
98109
}
99110

100111
// s3://
101-
if let Ok(r) = crate::uri_resolver::S3Uri::try_from(url.clone()) {
112+
if let Ok(r) = uri_resolver::S3Uri::try_from(input) {
102113
return Ok(Box::new(r));
103114
}
104115

105116
// secretsmanager://
106-
if let Ok(r) = crate::uri_resolver::SecretsManagerUri::try_from(input) {
117+
if let Ok(r) = uri_resolver::SecretsManagerUri::try_from(input) {
107118
return Ok(Box::new(r));
108119
}
109120

110121
// ssm://
111-
if let Ok(r) = crate::uri_resolver::SsmUri::try_from(input) {
122+
if let Ok(r) = uri_resolver::SsmUri::try_from(input) {
112123
return Ok(Box::new(r));
113124
}
114125

115126
error::NoResolverSnafu {
116-
input_source: input.to_string(),
127+
input_source: input.input.clone(),
117128
}
118129
.fail()
119130
}
@@ -152,12 +163,6 @@ fn format_change(input: &str, input_source: &str) -> Result<String> {
152163
}
153164

154165
pub(crate) mod error {
155-
use aws_sdk_secretsmanager::operation::get_secret_value::GetSecretValueError;
156-
use aws_sdk_ssm::operation::get_parameter::GetParameterError;
157-
use crate::apply::SdkHttpResponse;
158-
use aws_smithy_runtime_api::client::result::SdkError;
159-
use aws_sdk_s3::operation::get_object::GetObjectError;
160-
//use aws_smithy_http::result::SdkHttpResponse;
161166
use snafu::Snafu;
162167

163168
#[derive(Debug, Snafu)]
@@ -171,15 +176,6 @@ pub(crate) mod error {
171176
source: Box<crate::Error>,
172177
},
173178

174-
#[snafu(display("Failed to read given file '{}': {}", input_source, source))]
175-
FileRead {
176-
input_source: String,
177-
source: std::io::Error,
178-
},
179-
180-
#[snafu(display("Given invalid file URI '{}'", input_source))]
181-
FileUri { input_source: String },
182-
183179
#[snafu(display("No URI resolver found for '{}'", input_source))]
184180
NoResolver { input_source: String },
185181

@@ -237,77 +233,9 @@ pub(crate) mod error {
237233
source: reqwest::Error,
238234
},
239235

240-
#[snafu(display("Invalid S3 URI '{}': missing bucket name", input_source))]
241-
S3UriMissingBucket { input_source: String },
242-
243-
#[snafu(display("Failed to perform HTTP GET to '{}': {}", uri, source))]
244-
HttpRequest {
245-
uri: String,
246-
source: reqwest::Error,
247-
},
248-
249-
#[snafu(display("Non-success HTTP status from '{}': {}", uri, status))]
250-
HttpStatus {
251-
uri: String,
252-
status: reqwest::StatusCode,
253-
},
254-
255-
#[snafu(display("Failed to read HTTP response body from '{}': {}", uri, source))]
256-
HttpBody {
257-
uri: String,
258-
source: reqwest::Error,
259-
},
260-
261236
#[snafu(display("Given invalid file URI '{}'", input_source))]
262237
InvalidFileUri { input_source: String },
263238

264-
#[snafu(display("Given HTTP(S) URI '{}'", input_source))]
265-
InvalidHTTPUri { input_source: String },
266-
267-
#[snafu(display("Failed to read standard input: {}", source))]
268-
StdinRead { source: std::io::Error },
269-
270-
#[snafu(display("Failed to read S3 object body '{bucket}/{key}': {}", source))]
271-
S3Body {
272-
bucket: String,
273-
key: String,
274-
source: aws_sdk_s3::primitives::ByteStreamError,
275-
},
276-
277-
#[snafu(display("Failed to fetch S3 object '{bucket}/{key}': {}", source))]
278-
S3Get {
279-
bucket: String,
280-
key: String,
281-
source: SdkError<GetObjectError, SdkHttpResponse>,
282-
},
283-
284-
#[snafu(display("Invalid S3 URI scheme for '{}', expected s3://", input_source))]
285-
S3UriScheme { input_source: String },
286-
287-
#[snafu(display("Invalid Secrets Manager URI scheme for '{}', expected secretsmanager://", input_source))]
288-
SecretsManagerUri { input_source: String },
289-
290-
#[snafu(display("Invalid SSM URI scheme for '{}', expected ssm://", input_source))]
291-
SsmUri { input_source: String },
292-
293-
#[snafu(display("Failed to fetch secret '{}' from Secrets Manager: {}", secret_id, source))]
294-
SecretsManagerGet {
295-
secret_id: String,
296-
source: aws_sdk_secretsmanager::error::SdkError<GetSecretValueError>,
297-
},
298-
299-
#[snafu(display("Secrets Manager secret '{}' did not return a string value", secret_id))]
300-
SecretsManagerStringMissing { secret_id: String },
301-
302-
#[snafu(display("Failed to fetch parameter '{}' from SSM: {}", parameter_name, source))]
303-
SsmGetParameter {
304-
parameter_name: String,
305-
source: aws_sdk_ssm::error::SdkError<GetParameterError>,
306-
},
307-
308-
#[snafu(display("SSM parameter '{}' did not return a string value", parameter_name))]
309-
SsmParameterMissing { parameter_name: String },
310-
311239
#[snafu(display(
312240
"Failed to translate TOML from '{}' to JSON for API: {}",
313241
input_source,
@@ -323,7 +251,13 @@ pub(crate) mod error {
323251
input_source: String,
324252
source: url::ParseError,
325253
},
254+
255+
#[snafu(display("Resolver failed: {}", source))]
256+
ResolverFailure { source: crate::uri_resolver::ResolverError },
257+
326258
}
259+
327260
}
328261
pub use error::Error;
329262
pub type Result<T> = std::result::Result<T, error::Error>;
263+

0 commit comments

Comments
 (0)