forked from github-starred/komodo
281 lines
8.3 KiB
Rust
281 lines
8.3 KiB
Rust
use std::{path::PathBuf, sync::OnceLock};
|
|
|
|
use anyhow::Context;
|
|
use clap::Parser;
|
|
use colored::Colorize;
|
|
use environment_file::maybe_read_item_from_file;
|
|
use komodo_client::entities::{
|
|
config::{
|
|
DatabaseConfig,
|
|
cli::{
|
|
CliConfig, Env,
|
|
args::{CliArgs, Command, Execute, database::DatabaseCommand},
|
|
},
|
|
},
|
|
logger::LogConfig,
|
|
};
|
|
|
|
pub fn cli_args() -> &'static CliArgs {
|
|
static CLI_ARGS: OnceLock<CliArgs> = OnceLock::new();
|
|
CLI_ARGS.get_or_init(CliArgs::parse)
|
|
}
|
|
|
|
pub fn cli_env() -> &'static Env {
|
|
static CLI_ARGS: OnceLock<Env> = OnceLock::new();
|
|
CLI_ARGS.get_or_init(|| {
|
|
match envy::from_env()
|
|
.context("Failed to parse Komodo CLI environment")
|
|
{
|
|
Ok(env) => env,
|
|
Err(e) => {
|
|
panic!("{e:?}")
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
pub fn cli_config() -> &'static CliConfig {
|
|
static CLI_CONFIG: OnceLock<CliConfig> = OnceLock::new();
|
|
CLI_CONFIG.get_or_init(|| {
|
|
let args = cli_args();
|
|
let env = cli_env().clone();
|
|
let config_paths = args
|
|
.config_path
|
|
.clone()
|
|
.unwrap_or(env.komodo_cli_config_paths);
|
|
let debug_startup =
|
|
args.debug_startup.unwrap_or(env.komodo_cli_debug_startup);
|
|
|
|
if debug_startup {
|
|
println!(
|
|
"{}: Komodo CLI version: {}",
|
|
"DEBUG".cyan(),
|
|
env!("CARGO_PKG_VERSION").blue().bold()
|
|
);
|
|
println!(
|
|
"{}: {}: {config_paths:?}",
|
|
"DEBUG".cyan(),
|
|
"Config Paths".dimmed(),
|
|
);
|
|
}
|
|
|
|
let config_keywords = args
|
|
.config_keyword
|
|
.clone()
|
|
.unwrap_or(env.komodo_cli_config_keywords);
|
|
let config_keywords = config_keywords
|
|
.iter()
|
|
.map(String::as_str)
|
|
.collect::<Vec<_>>();
|
|
if debug_startup {
|
|
println!(
|
|
"{}: {}: {config_keywords:?}",
|
|
"DEBUG".cyan(),
|
|
"Config File Keywords".dimmed(),
|
|
);
|
|
}
|
|
let mut unparsed_config = (config::ConfigLoader {
|
|
paths: &config_paths
|
|
.iter()
|
|
.map(PathBuf::as_path)
|
|
.collect::<Vec<_>>(),
|
|
match_wildcards: &config_keywords,
|
|
include_file_name: ".kminclude",
|
|
merge_nested: env.komodo_cli_merge_nested_config,
|
|
extend_array: env.komodo_cli_extend_config_arrays,
|
|
debug_print: debug_startup,
|
|
})
|
|
.load::<serde_json::Map<String, serde_json::Value>>()
|
|
.expect("failed at parsing config from paths");
|
|
let init_parsed_config = serde_json::from_value::<CliConfig>(
|
|
serde_json::Value::Object(unparsed_config.clone()),
|
|
)
|
|
.context("Failed to parse config")
|
|
.unwrap();
|
|
|
|
let (host, key, secret) = match &args.command {
|
|
Command::Execute(Execute {
|
|
host, key, secret, ..
|
|
}) => (host.clone(), key.clone(), secret.clone()),
|
|
_ => (None, None, None),
|
|
};
|
|
|
|
let backups_folder = match &args.command {
|
|
Command::Database {
|
|
command: DatabaseCommand::Backup { backups_folder, .. },
|
|
} => backups_folder.clone(),
|
|
Command::Database {
|
|
command: DatabaseCommand::Restore { backups_folder, .. },
|
|
} => backups_folder.clone(),
|
|
_ => None,
|
|
};
|
|
let (uri, address, username, password, db_name) =
|
|
match &args.command {
|
|
Command::Database {
|
|
command:
|
|
DatabaseCommand::Copy {
|
|
uri,
|
|
address,
|
|
username,
|
|
password,
|
|
db_name,
|
|
..
|
|
},
|
|
} => (
|
|
uri.clone(),
|
|
address.clone(),
|
|
username.clone(),
|
|
password.clone(),
|
|
db_name.clone(),
|
|
),
|
|
_ => (None, None, None, None, None),
|
|
};
|
|
|
|
let profile = args
|
|
.profile
|
|
.as_ref()
|
|
.or(init_parsed_config.default_profile.as_ref());
|
|
|
|
let unparsed_config = if let Some(profile) = profile
|
|
&& !profile.is_empty()
|
|
{
|
|
// Find the profile config,
|
|
// then merge it with the Default config.
|
|
let serde_json::Value::Array(profiles) = unparsed_config
|
|
.remove("profile")
|
|
.context("Config has no profiles, but a profile is required")
|
|
.unwrap()
|
|
else {
|
|
panic!("`config.profile` is not array");
|
|
};
|
|
let Some(profile_config) = profiles.into_iter().find(|p| {
|
|
let Ok(parsed) =
|
|
serde_json::from_value::<CliConfig>(p.clone())
|
|
else {
|
|
return false;
|
|
};
|
|
&parsed.config_profile == profile
|
|
|| parsed
|
|
.config_aliases
|
|
.iter()
|
|
.any(|alias| alias == profile)
|
|
}) else {
|
|
panic!("No profile matching '{profile}' was found.");
|
|
};
|
|
let serde_json::Value::Object(profile_config) = profile_config
|
|
else {
|
|
panic!("Profile config is not Object type.");
|
|
};
|
|
config::merge_config(
|
|
unparsed_config,
|
|
profile_config.clone(),
|
|
env.komodo_cli_merge_nested_config,
|
|
env.komodo_cli_extend_config_arrays,
|
|
)
|
|
.unwrap_or(profile_config)
|
|
} else {
|
|
unparsed_config
|
|
};
|
|
let config = serde_json::from_value::<CliConfig>(
|
|
serde_json::Value::Object(unparsed_config),
|
|
)
|
|
.context("Failed to parse final config")
|
|
.unwrap();
|
|
let config_profile = if config.config_profile.is_empty() {
|
|
String::from("None")
|
|
} else {
|
|
config.config_profile
|
|
};
|
|
|
|
CliConfig {
|
|
config_profile,
|
|
config_aliases: config.config_aliases,
|
|
default_profile: config.default_profile,
|
|
table_borders: env
|
|
.komodo_cli_table_borders
|
|
.or(config.table_borders),
|
|
host: host
|
|
.or(env.komodo_cli_host)
|
|
.or(env.komodo_host)
|
|
.unwrap_or(config.host),
|
|
cli_key: key.or(env.komodo_cli_key).or(config.cli_key),
|
|
cli_secret: secret
|
|
.or(env.komodo_cli_secret)
|
|
.or(config.cli_secret),
|
|
backups_folder: backups_folder
|
|
.or(env.komodo_cli_backups_folder)
|
|
.unwrap_or(config.backups_folder),
|
|
max_backups: env
|
|
.komodo_cli_max_backups
|
|
.unwrap_or(config.max_backups),
|
|
database_target: DatabaseConfig {
|
|
uri: uri
|
|
.or(env.komodo_cli_database_target_uri)
|
|
.unwrap_or(config.database_target.uri),
|
|
address: address
|
|
.or(env.komodo_cli_database_target_address)
|
|
.unwrap_or(config.database_target.address),
|
|
username: username
|
|
.or(env.komodo_cli_database_target_username)
|
|
.unwrap_or(config.database_target.username),
|
|
password: password
|
|
.or(env.komodo_cli_database_target_password)
|
|
.unwrap_or(config.database_target.password),
|
|
db_name: db_name
|
|
.or(env.komodo_cli_database_target_db_name)
|
|
.unwrap_or(config.database_target.db_name),
|
|
app_name: config.database_target.app_name,
|
|
},
|
|
database: DatabaseConfig {
|
|
uri: maybe_read_item_from_file(
|
|
env.komodo_database_uri_file,
|
|
env.komodo_database_uri,
|
|
)
|
|
.unwrap_or(config.database.uri),
|
|
address: env
|
|
.komodo_database_address
|
|
.unwrap_or(config.database.address),
|
|
username: maybe_read_item_from_file(
|
|
env.komodo_database_username_file,
|
|
env.komodo_database_username,
|
|
)
|
|
.unwrap_or(config.database.username),
|
|
password: maybe_read_item_from_file(
|
|
env.komodo_database_password_file,
|
|
env.komodo_database_password,
|
|
)
|
|
.unwrap_or(config.database.password),
|
|
db_name: env
|
|
.komodo_database_db_name
|
|
.unwrap_or(config.database.db_name),
|
|
app_name: config.database.app_name,
|
|
},
|
|
cli_logging: LogConfig {
|
|
level: env
|
|
.komodo_cli_logging_level
|
|
.unwrap_or(config.cli_logging.level),
|
|
stdio: env
|
|
.komodo_cli_logging_stdio
|
|
.unwrap_or(config.cli_logging.stdio),
|
|
pretty: env
|
|
.komodo_cli_logging_pretty
|
|
.unwrap_or(config.cli_logging.pretty),
|
|
location: false,
|
|
ansi: env
|
|
.komodo_cli_logging_ansi
|
|
.unwrap_or(config.cli_logging.ansi),
|
|
otlp_endpoint: env
|
|
.komodo_cli_logging_otlp_endpoint
|
|
.unwrap_or(config.cli_logging.otlp_endpoint),
|
|
opentelemetry_service_name: env
|
|
.komodo_cli_logging_opentelemetry_service_name
|
|
.unwrap_or(config.cli_logging.opentelemetry_service_name),
|
|
opentelemetry_scope_name: env
|
|
.komodo_cli_logging_opentelemetry_scope_name
|
|
.unwrap_or(config.cli_logging.opentelemetry_scope_name),
|
|
},
|
|
profile: config.profile,
|
|
}
|
|
})
|
|
}
|