Skip to content

Commit c9ba519

Browse files
committed
Handle displaying all errors in cli main instead of in command run funcs
This consolidates (almost) all of the error display handling into the cli main(), which is idiomatic since the library side of this shouldn't need to worry about how its errors are presented. There are a couple spots where the Error case is a Vec of things, which can't be handled by the single error handler in main. These have been changed to do their custom error printing, then return a new error to main(). I added TODO comments to these. Signed-off-by: Robert Detjens <[email protected]>
1 parent b1d1c84 commit c9ba519

File tree

6 files changed

+66
-71
lines changed

6 files changed

+66
-71
lines changed

src/commands/build.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use anyhow::Result;
12
use itertools::Itertools;
23
use std::process::exit;
34
use tracing::{debug, error, info, trace, warn};
@@ -6,15 +7,12 @@ use crate::builder::build_challenges;
67
use crate::configparser::{get_config, get_profile_config};
78

89
#[tokio::main(flavor = "current_thread")] // make this a sync function
9-
pub async fn run(profile_name: &str, push: &bool, extract: &bool) {
10+
pub async fn run(profile_name: &str, push: &bool, extract: &bool) -> Result<()> {
1011
info!("building images...");
1112

12-
let results = match build_challenges(profile_name, *push, *extract).await {
13-
Ok(results) => results,
14-
Err(e) => {
15-
error!("{e:?}");
16-
exit(1)
17-
}
18-
};
13+
let results = build_challenges(profile_name, *push, *extract).await?;
14+
1915
info!("images built successfully!");
16+
17+
Ok(())
2018
}

src/commands/check_access.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
1-
use anyhow::{Context, Error, Result};
1+
use anyhow::{bail, Context, Error, Result};
22
use itertools::Itertools;
33
use std::process::exit;
44
use tracing::{debug, error, info, trace, warn};
55

66
use crate::access_handlers as access;
77
use crate::configparser::{get_config, get_profile_config};
88

9-
pub fn run(profile: &str, kubernetes: &bool, frontend: &bool, registry: &bool, bucket: &bool) {
9+
pub fn run(
10+
profile: &str,
11+
kubernetes: &bool,
12+
frontend: &bool,
13+
registry: &bool,
14+
bucket: &bool,
15+
) -> Result<()> {
1016
// if user did not give a specific check, check all of them
1117
let check_all = !kubernetes && !frontend && !registry && !bucket;
1218

@@ -36,6 +42,7 @@ pub fn run(profile: &str, kubernetes: &bool, frontend: &bool, registry: &bool, b
3642
debug!("access results: {results:?}");
3743

3844
// die if there were any errors
45+
// TODO: figure out how to return this error directly
3946
let mut should_exit = false;
4047
for (profile, result) in results.iter() {
4148
match result {
@@ -48,8 +55,10 @@ pub fn run(profile: &str, kubernetes: &bool, frontend: &bool, registry: &bool, b
4855
}
4956
}
5057
if should_exit {
51-
exit(1);
58+
bail!("config validation failed");
5259
}
60+
61+
Ok(())
5362
}
5463

5564
/// checks a single profile (`profile`) for the given accesses

src/commands/cluster_setup.rs

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,15 @@ use crate::cluster_setup as setup;
77
use crate::configparser::{get_config, get_profile_config};
88

99
#[tokio::main(flavor = "current_thread")] // make this a sync function
10-
pub async fn run(profile_name: &str) {
10+
pub async fn run(profile_name: &str) -> Result<()> {
1111
info!("setting up cluster...");
1212
let config = get_profile_config(profile_name).unwrap();
1313

14-
if let Err(e) = setup::install_ingress(config).await {
15-
error!("{e:?}");
16-
exit(1);
17-
}
18-
if let Err(e) = setup::install_certmanager(config).await {
19-
error!("{e:?}");
20-
exit(1);
21-
}
22-
if let Err(e) = setup::install_extdns(config).await {
23-
error!("{e:?}");
24-
exit(1);
25-
}
14+
setup::install_ingress(config).await?;
15+
setup::install_certmanager(config).await?;
16+
setup::install_extdns(config).await?;
2617

27-
info!("charts deployed!")
18+
info!("charts deployed!");
19+
20+
Ok(())
2821
}

src/commands/deploy.rs

Lines changed: 9 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use anyhow::Result;
12
use itertools::Itertools;
23
use std::process::exit;
34
use tracing::{debug, error, info, trace, warn};
@@ -7,14 +8,11 @@ use crate::configparser::{get_config, get_profile_config};
78
use crate::deploy;
89

910
#[tokio::main(flavor = "current_thread")] // make this a sync function
10-
pub async fn run(profile_name: &str, no_build: &bool, _dry_run: &bool) {
11+
pub async fn run(profile_name: &str, no_build: &bool, _dry_run: &bool) -> Result<()> {
1112
let profile = get_profile_config(profile_name).unwrap();
1213

1314
// has the cluster been setup?
14-
if let Err(e) = deploy::check_setup(profile).await {
15-
error!("{e:?}");
16-
exit(1);
17-
}
15+
deploy::check_setup(profile).await?;
1816

1917
// build before deploying
2018
if *no_build {
@@ -24,13 +22,7 @@ pub async fn run(profile_name: &str, no_build: &bool, _dry_run: &bool) {
2422
}
2523

2624
info!("building challenges...");
27-
let build_results = match build_challenges(profile_name, true, true).await {
28-
Ok(result) => result,
29-
Err(e) => {
30-
error!("{e:?}");
31-
exit(1);
32-
}
33-
};
25+
let build_results = build_challenges(profile_name, true, true).await?;
3426

3527
trace!(
3628
"got built results: {:#?}",
@@ -47,20 +39,13 @@ pub async fn run(profile_name: &str, no_build: &bool, _dry_run: &bool) {
4739
// C) update frontend with new state of challenges
4840

4941
// A)
50-
if let Err(e) = deploy::kubernetes::deploy_challenges(profile_name, &build_results).await {
51-
error!("{e:?}");
52-
exit(1);
53-
}
42+
deploy::kubernetes::deploy_challenges(profile_name, &build_results).await?;
5443

5544
// B)
56-
if let Err(e) = deploy::s3::upload_assets(profile_name, &build_results).await {
57-
error!("{e:?}");
58-
exit(1);
59-
}
45+
deploy::s3::upload_assets(profile_name, &build_results).await?;
6046

6147
// C)
62-
if let Err(e) = deploy::frontend::update_frontend(profile_name, &build_results).await {
63-
error!("{e:?}");
64-
exit(1);
65-
}
48+
deploy::frontend::update_frontend(profile_name, &build_results).await?;
49+
50+
Ok(())
6651
}

src/commands/validate.rs

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,26 @@
1+
use anyhow::{bail, Result};
12
use std::path::Path;
23
use std::process::exit;
34
use tracing::{debug, error, info, trace, warn};
45

56
use crate::configparser::{get_challenges, get_config, get_profile_deploy};
67

7-
pub fn run() {
8+
pub fn run() -> Result<()> {
89
info!("validating config...");
9-
let config = match get_config() {
10-
Ok(c) => c,
11-
Err(err) => {
12-
error!("{err:#}");
13-
exit(1);
14-
}
15-
};
10+
11+
let config = get_config()?;
1612
info!(" config ok!");
1713

1814
info!("validating challenges...");
15+
// print these errors here instead of returning, since its a vec of them
16+
// TODO: figure out how to return this error directly
1917
let chals = match get_challenges() {
2018
Ok(c) => c,
2119
Err(errors) => {
2220
for e in errors.iter() {
2321
error!("{e:#}");
2422
}
25-
exit(1);
23+
bail!("failed to validate challenges");
2624
}
2725
};
2826
info!(" challenges ok!");
@@ -31,29 +29,28 @@ pub fn run() {
3129
info!("validating deploy config...");
3230
for (profile_name, _pconfig) in config.profiles.iter() {
3331
// fetch from config
34-
let deploy_challenges = match get_profile_deploy(profile_name) {
35-
Ok(d) => &d.challenges,
36-
Err(err) => {
37-
error!("{err:#}");
38-
exit(1);
39-
}
40-
};
32+
let deploy_challenges = get_profile_deploy(profile_name)?;
4133

4234
// check for missing
4335
let missing: Vec<_> = deploy_challenges
36+
.challenges
4437
.keys()
4538
.filter(
4639
// try to find any challenge paths in deploy config that do not exist
4740
|path| !chals.iter().any(|c| c.directory == Path::new(path)),
4841
)
4942
.collect();
43+
44+
// TODO: figure out how to return this error directly
5045
if !missing.is_empty() {
5146
error!(
5247
"Deploy settings for profile '{profile_name}' has challenges that do not exist:"
5348
);
5449
missing.iter().for_each(|path| error!(" - {path}"));
55-
exit(1)
50+
bail!("failed to validate deploy config");
5651
}
5752
}
58-
info!(" deploy ok!")
53+
info!(" deploy ok!");
54+
55+
Ok(())
5956
}

src/main.rs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,19 @@ fn main() {
3838
.init();
3939

4040
trace!("args: {:?}", cli);
41+
4142
// dispatch commands
43+
match dispatch(cli) {
44+
Ok(_) => (),
45+
Err(e) => {
46+
error!("{e:?}");
47+
std::process::exit(1)
48+
}
49+
};
50+
}
51+
52+
/// dispatch commands
53+
fn dispatch(cli: cli::Cli) -> anyhow::Result<()> {
4254
match &cli.command {
4355
cli::Commands::Validate => commands::validate::run(),
4456

@@ -49,7 +61,7 @@ fn main() {
4961
registry,
5062
bucket,
5163
} => {
52-
commands::validate::run();
64+
commands::validate::run()?;
5365
commands::check_access::run(profile, kubernetes, frontend, registry, bucket)
5466
}
5567

@@ -60,7 +72,7 @@ fn main() {
6072
no_push,
6173
extract_assets,
6274
} => {
63-
commands::validate::run();
75+
commands::validate::run()?;
6476
commands::build::run(profile, &!no_push, extract_assets)
6577
}
6678

@@ -69,12 +81,13 @@ fn main() {
6981
no_build,
7082
dry_run,
7183
} => {
72-
commands::validate::run();
84+
commands::validate::run()?;
7385
commands::deploy::run(profile, no_build, dry_run)
7486
}
7587

7688
cli::Commands::ClusterSetup { profile } => {
77-
commands::cluster_setup::run(profile);
89+
commands::validate::run()?;
90+
commands::cluster_setup::run(profile)
7891
}
7992
}
8093
}

0 commit comments

Comments
 (0)