Skip to content

Commit 9ae9d64

Browse files
committed
Print descriptive errors on failures
1 parent 6db0ed8 commit 9ae9d64

File tree

4 files changed

+89
-13
lines changed

4 files changed

+89
-13
lines changed

src/commands.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1832,7 +1832,7 @@ pub fn delete_policy_definition_keys(
18321832
let str_keys: Vec<&str> = keys.iter().map(AsRef::as_ref).collect::<Vec<_>>();
18331833

18341834
let pol = client.get_policy(vhost, &name)?;
1835-
let updated_pol = pol.without_keys(str_keys);
1835+
let updated_pol = pol.without_keys(&str_keys);
18361836

18371837
let params = PolicyParams::from(&updated_pol);
18381838
client.declare_policy(&params)
@@ -1852,7 +1852,7 @@ pub fn delete_policy_definition_keys_in(
18521852
let str_keys: Vec<&str> = keys.iter().map(AsRef::as_ref).collect::<Vec<_>>();
18531853

18541854
for pol in pols {
1855-
let updated_pol = pol.without_keys(str_keys.clone());
1855+
let updated_pol = pol.without_keys(&str_keys);
18561856

18571857
let params = PolicyParams::from(&updated_pol);
18581858
client.declare_policy(&params)?
@@ -1875,7 +1875,7 @@ pub fn delete_operator_policy_definition_keys(
18751875
let str_keys: Vec<&str> = keys.iter().map(AsRef::as_ref).collect::<Vec<_>>();
18761876

18771877
let pol = client.get_operator_policy(vhost, &name)?;
1878-
let updated_pol = pol.without_keys(str_keys);
1878+
let updated_pol = pol.without_keys(&str_keys);
18791879

18801880
let params = PolicyParams::from(&updated_pol);
18811881
client.declare_operator_policy(&params)
@@ -1895,7 +1895,7 @@ pub fn delete_operator_policy_definition_keys_in(
18951895
let str_keys: Vec<&str> = keys.iter().map(AsRef::as_ref).collect::<Vec<_>>();
18961896

18971897
for pol in pols {
1898-
let updated_pol = pol.without_keys(str_keys.clone());
1898+
let updated_pol = pol.without_keys(&str_keys);
18991899

19001900
let params = PolicyParams::from(&updated_pol);
19011901
client.declare_operator_policy(&params)?

src/errors.rs

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,18 +60,20 @@ pub enum CommandRunError {
6060
PrivateKeyFileUnsupported { local_path: String },
6161
#[error("TLS certificate and private key files do not match")]
6262
CertificateKeyMismatch { cert_path: String, key_path: String },
63-
#[error("API responded with a client error: status code of {status_code}")]
63+
#[error("{}", format_client_error(.status_code, .error_details))]
6464
ClientError {
6565
status_code: StatusCode,
6666
url: Option<Url>,
6767
body: Option<String>,
68+
error_details: Option<rabbitmq_http_client::error::ErrorDetails>,
6869
headers: Option<HeaderMap>,
6970
},
70-
#[error("API responded with a client error: status code of {status_code}")]
71+
#[error("{}", format_server_error(.status_code, .error_details))]
7172
ServerError {
7273
status_code: StatusCode,
7374
url: Option<Url>,
7475
body: Option<String>,
76+
error_details: Option<rabbitmq_http_client::error::ErrorDetails>,
7577
headers: Option<HeaderMap>,
7678
},
7779
#[error("Health check failed")]
@@ -115,11 +117,11 @@ impl From<HttpClientError> for CommandRunError {
115117
use ApiClientError::*;
116118
match value {
117119
UnsupportedArgumentValue { property } => Self::UnsupportedArgumentValue { property },
118-
ClientErrorResponse { status_code, url, body, headers, .. } => {
119-
Self::ClientError { status_code, url, body, headers }
120+
ClientErrorResponse { status_code, url, body, error_details, headers, .. } => {
121+
Self::ClientError { status_code, url, body, error_details, headers }
120122
}
121-
ServerErrorResponse { status_code, url, body, headers, .. } => {
122-
Self::ServerError { status_code, url, body, headers }
123+
ServerErrorResponse { status_code, url, body, error_details, headers, .. } => {
124+
Self::ServerError { status_code, url, body, error_details, headers }
123125
}
124126
HealthCheckFailed { path, details, status_code } => {
125127
Self::HealthCheckFailed { health_check_path: path, details, status_code }
@@ -137,3 +139,36 @@ impl From<HttpClientError> for CommandRunError {
137139
}
138140
}
139141
}
142+
143+
fn format_client_error(
144+
status_code: &StatusCode,
145+
error_details: &Option<rabbitmq_http_client::error::ErrorDetails>,
146+
) -> String {
147+
if let Some(details) = error_details {
148+
if let Some(reason) = details.reason() {
149+
return reason.to_string();
150+
}
151+
}
152+
format!(
153+
"API responded with a client error: status code of {}",
154+
status_code
155+
)
156+
}
157+
158+
fn format_server_error(
159+
status_code: &StatusCode,
160+
error_details: &Option<rabbitmq_http_client::error::ErrorDetails>,
161+
) -> String {
162+
if let Some(details) = error_details {
163+
if let Some(reason) = details.reason() {
164+
return format!(
165+
"API responded with a server error: status code of {}\n\n{}",
166+
status_code, reason
167+
);
168+
}
169+
}
170+
format!(
171+
"API responded with a server error: status code of {}",
172+
status_code
173+
)
174+
}

src/tables.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -314,14 +314,16 @@ pub fn failure_details(error: &HttpClientError) -> Table {
314314
status_code,
315315
url,
316316
body,
317+
error_details,
317318
..
318-
} => generic_failed_request_details(status_code, url, body),
319+
} => generic_failed_request_details(status_code, url, body, error_details),
319320
HttpClientError::ServerErrorResponse {
320321
status_code,
321322
url,
322323
body,
324+
error_details,
323325
..
324-
} => generic_failed_request_details(status_code, url, body),
326+
} => generic_failed_request_details(status_code, url, body, error_details),
325327
HttpClientError::HealthCheckFailed {
326328
status_code,
327329
path,
@@ -496,12 +498,13 @@ fn generic_failed_request_details(
496498
status_code: &StatusCode,
497499
url: &Option<Url>,
498500
body: &Option<String>,
501+
error_details: &Option<rabbitmq_http_client::error::ErrorDetails>,
499502
) -> Table {
500503
let status_code_s = status_code.to_string();
501504
let url_s = url.clone().unwrap().to_string();
502505
let body_s = body.clone().unwrap_or("N/A".to_string());
503506

504-
let data = vec![
507+
let mut data = vec![
505508
RowOfTwo {
506509
key: "result",
507510
value: "request failed",
@@ -520,6 +523,15 @@ fn generic_failed_request_details(
520523
},
521524
];
522525

526+
if let Some(details) = error_details {
527+
if let Some(reason) = details.reason() {
528+
data.push(RowOfTwo {
529+
key: "error",
530+
value: reason,
531+
});
532+
}
533+
}
534+
523535
build_simple_table(data)
524536
}
525537

tests/policies_tests.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,3 +676,32 @@ fn test_policies_declare_blanket() -> Result<(), Box<dyn Error>> {
676676

677677
Ok(())
678678
}
679+
680+
#[test]
681+
fn test_policy_validation_error() -> Result<(), Box<dyn Error>> {
682+
let policy_name = "test_policy_validation_error";
683+
684+
// Attempt to declare a policy with invalid/unknown settings in the definition
685+
// This should fail with a descriptive validation error message
686+
run_fails([
687+
"declare",
688+
"policy",
689+
"--name",
690+
policy_name,
691+
"--pattern",
692+
"^qq$",
693+
"--apply-to",
694+
"queues",
695+
"--priority",
696+
"1",
697+
"--definition",
698+
r#"{"foo": "bar", "invalid-setting": 12345}"#,
699+
])
700+
.stderr(output_includes("Validation failed"))
701+
.stderr(output_includes("not recognised").or(output_includes("not recognized")));
702+
703+
// Verify the policy was not created
704+
run_succeeds(["list", "policies"]).stdout(output_includes(policy_name).not());
705+
706+
Ok(())
707+
}

0 commit comments

Comments
 (0)