Files
imoje/src/cli/mod.rs
T
2026-09-07 10:52:43 +01:00

251 lines
5.9 KiB
Rust

use crate::logger;
use anyhow::{Context, Result};
use clap::{Parser, ValueEnum};
use log::error;
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
struct Cli {
/// Number of seconds to wait
#[arg(short = 'w', long, default_value_t = 20, env = "IMOJEFS_WAIT")]
pub wait: u64,
/// The logging level
#[arg(short = 'l', long, value_enum, default_value_t = LogLevel::Info, env = "IMOJEFS_LOG_LEVEL"
)]
pub log_level: LogLevel,
/// The configuration to use
#[arg(short = 'c', long, default_value_t = String::from("imoje"))]
config: String,
#[command(subcommand)]
command: Option<Commands>,
}
#[derive(clap::Subcommand, Debug)]
enum Commands {
/// Controls testing features
FileSync,
/// Lists the settings from the configuration file
List,
/// Change Settings
Set {
#[command(subcommand)]
command: Option<SettingsCommands>,
},
}
#[derive(clap::Subcommand, Debug)]
enum SettingsCommands {
/// Set the Salesforce Authentication Url
SfdxAuthUrl {
/// Salesforce Authentication Url
#[arg(
short = 'x',
long,
env = "IMOJEFS_SFDX_AUTH_URL",
hide_env_values = true
)]
url: String,
},
}
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
pub struct Args {
/// AWS Bucket name
#[arg(short = 'b', long, env = "IMOJEFS_S3_BUCKET")]
pub s3_bucket: String,
/// AWS Access Key Id
#[arg(short = 'k', long, env = "IMOJEFS_S3_CLIENT_ID")]
pub s3_client_id: String,
/// AWS Secret Access Key
#[arg(
short = 's',
long,
env = "IMOJEFS_S3_CLIENT_SECRET",
hide_env_values = true
)]
pub s3_client_secret: String,
/// AWS Endpoint URL, [default: AWS url]
#[arg(short = 'e', long, env = "IMOJEFS_S3_ENDPOINT")]
pub s3_endpoint: Option<String>,
/// AWS Region
#[arg(
short = 'r',
long,
default_value = "us-east-1",
env = "IMOJEFS_S3_REGION"
)]
pub s3_region: String,
/// Salesforce Authentication Url
#[arg(
short = 'x',
long,
env = "IMOJEFS_SFDX_AUTH_URL",
hide_env_values = true
)]
pub sfdx_auth_url: String,
/// Retry failures after X runs
#[arg(long, default_value_t = 180, env = "IMOJEFS_RETRY")]
pub retry: u64,
/// A comma separated list of fallback email address,
/// used when Salesforce cannot be reached to deliver log messages
#[arg(short = 'a', long, env = "IMOJEFS_ADMIN_EMAIL")]
pub admin_email: Option<String>,
}
impl Args {
pub(crate) fn s3_bucket(&self) -> &str {
&self.s3_bucket
}
pub(crate) fn s3_client_id(&self) -> &str {
&self.s3_client_id
}
pub(crate) fn s3_client_secret(&self) -> &str {
&self.s3_client_secret
}
pub(crate) fn s3_endpoint(&self) -> Option<&str> {
self.s3_endpoint.as_deref()
}
pub(crate) fn s3_region(&self) -> &str {
&self.s3_region
}
}
/// Represents the different levels of logging that can be used in an application.
///
/// # Variants
/// - `Debug`: Indicates detailed debugging information typically used for development and troubleshooting.
/// - `Info`: Represents general operational information, such as confirmation that things are working as expected.
/// - `Warning`: Denotes potentially harmful situations or actions that warrant attention but are not critical errors.
/// - `Error`: Designates severe error events that lead to application malfunction or require immediate resolution.
///
/// This enum derives `ValueEnum` to allow easy parsing from strings (e.g., for command-line arguments),
/// as well as `Clone` and `Debug` for efficient copying and debugging purposes.
#[derive(ValueEnum, Clone, Debug)]
pub enum LogLevel {
Debug,
Info,
Warning,
Error,
Trace,
}
fn load_configuration_file(config_file: &str) -> Result<()> {
let app_config =
crate::config::load(config_file).context("Failed to load application configuration")?;
crate::APP_CONFIG
.set(app_config)
.map_err(|_| anyhow::anyhow!("Application configuration has already been initialized"))?;
Ok(())
}
fn list_config_settings(config_file: &str) -> Result<()> {
let app_config =
crate::config::load(config_file).context("Failed to load application configuration")?;
println!("Configuration: {config_file}");
println!(
"sfdx_auth_url = {}",
app_config
.sfdx_auth_url
.as_deref()
.unwrap_or("<not set>")
);
Ok(())
}
fn set_sfdx_auth_url(config_file: &str, url: String) -> Result<()> {
let mut app_config =
crate::config::load(config_file).context("Failed to load application configuration")?;
app_config.sfdx_auth_url = Some(url);
crate::config::save(config_file, &app_config)
.context("Failed to save Salesforce authentication URL")?;
Ok(())
}
pub(crate) fn run() {
let cli = Cli::parse();
match &cli.command {
Some(command) => match command {
Commands::Set { command } => {
run_set_command(&cli, command);
},
Commands::List => {
run_list_command(&cli);
},
Commands::FileSync { .. } => {
run_file_sync(&cli);
}
},
None => {
println!("Expected subcommand, none given. Use --help for more information");
std::process::exit(1);
}
}
}
fn run_file_sync(cli: &Cli) {
logger::init(&cli.log_level);
match load_configuration_file(&cli.config) {
Ok(()) => {}
Err(e) => {
error!("Error loading configuration file: {:#}", e);
std::process::exit(1);
}
}
crate::file_sync::run();
}
fn run_list_command(cli: &Cli) {
match list_config_settings(&cli.config) {
Ok(()) => {}
Err(e) => {
error!("Error listing configuration settings: {:#}", e);
std::process::exit(1);
}
}
}
fn run_set_command(cli: &Cli, commands: &Option<SettingsCommands>) {
match commands {
Some(command) => match command {
SettingsCommands::SfdxAuthUrl { url } => {
match set_sfdx_auth_url(&cli.config, url.clone()) {
Ok(()) => {
println!("Salesforce authentication URL saved successfully");
}
Err(e) => {
error!("Error saving Salesforce authentication URL: {:#}", e);
std::process::exit(1);
}
}
}
},
None => {
println!("Expected subcommand, none given. Use --help for more information");
std::process::exit(1);
}
}
}