defined env
This commit is contained in:
Generated
+3
@@ -7600,12 +7600,15 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap 4.4.7",
|
||||
"dotenvy",
|
||||
"humantime 2.1.0",
|
||||
"humantime-serde",
|
||||
"lazy_static",
|
||||
"nix 0.27.1",
|
||||
"nym-bin-common",
|
||||
"nym-config",
|
||||
"serde",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
@@ -8,7 +8,7 @@ edition = "2021"
|
||||
[dependencies]
|
||||
chrono = { version = "0.4.31", features = ["serde"] }
|
||||
clap = { workspace = true, features = ["cargo", "derive"] }
|
||||
dotenvy = "0.15.6"
|
||||
dotenvy = { workspace = true }
|
||||
humantime-serde = "1.0"
|
||||
isocountry = "0.3.2"
|
||||
itertools = "0.10.3"
|
||||
|
||||
@@ -10,7 +10,7 @@ bs58 = "0.4"
|
||||
clap = { workspace = true, features = ["derive"] }
|
||||
clap_complete = "4.0"
|
||||
clap_complete_fig = "4.0"
|
||||
dotenvy = "0.15.6"
|
||||
dotenvy = { workspace = true }
|
||||
log = { workspace = true }
|
||||
pretty_env_logger = "0.4"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
|
||||
@@ -13,11 +13,14 @@ license.workspace = true
|
||||
[dependencies]
|
||||
anyhow = { workspace = true }
|
||||
clap = { workspace = true, features = ["derive"] }
|
||||
dotenvy = { workspace = true }
|
||||
humantime = "2.1.0"
|
||||
humantime-serde = "1.1.1"
|
||||
lazy_static = { workspace = true }
|
||||
nix = "0.27.1"
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
tokio = { workspace = true, features = ["rt", "macros", "signal", "process"] }
|
||||
thiserror = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
|
||||
nym-bin-common = { path = "../../common/bin-common", features = ["output_format"] }
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::error::NymvisorError;
|
||||
use nym_bin_common::output_format::OutputFormat;
|
||||
|
||||
#[derive(clap::Args, Debug)]
|
||||
@@ -9,7 +10,7 @@ pub(crate) struct Args {
|
||||
output: OutputFormat,
|
||||
}
|
||||
|
||||
pub(crate) fn execute(args: Args) -> anyhow::Result<()> {
|
||||
pub(crate) fn execute(args: Args) -> Result<(), NymvisorError> {
|
||||
println!("add upgrade");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::error::NymvisorError;
|
||||
use nym_bin_common::bin_info_owned;
|
||||
use nym_bin_common::output_format::OutputFormat;
|
||||
|
||||
@@ -10,7 +11,7 @@ pub(crate) struct Args {
|
||||
output: OutputFormat,
|
||||
}
|
||||
|
||||
pub(crate) fn execute(args: Args) -> anyhow::Result<()> {
|
||||
pub(crate) fn execute(args: Args) -> Result<(), NymvisorError> {
|
||||
println!("{}", args.output.format(&bin_info_owned!()));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::error::NymvisorError;
|
||||
use nym_bin_common::output_format::OutputFormat;
|
||||
|
||||
#[derive(clap::Args, Debug)]
|
||||
@@ -9,7 +10,7 @@ pub(crate) struct Args {
|
||||
output: OutputFormat,
|
||||
}
|
||||
|
||||
pub(crate) fn execute(args: Args) -> anyhow::Result<()> {
|
||||
pub(crate) fn execute(args: Args) -> Result<(), NymvisorError> {
|
||||
println!("config");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::env::Env;
|
||||
use crate::error::NymvisorError;
|
||||
use nym_bin_common::output_format::OutputFormat;
|
||||
|
||||
#[derive(clap::Args, Debug)]
|
||||
@@ -9,7 +11,9 @@ pub(crate) struct Args {
|
||||
output: OutputFormat,
|
||||
}
|
||||
|
||||
pub(crate) fn execute(args: Args) -> anyhow::Result<()> {
|
||||
pub(crate) fn execute(args: Args) -> Result<(), NymvisorError> {
|
||||
let env = Env::try_read()?;
|
||||
|
||||
println!("init");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ mod config;
|
||||
mod init;
|
||||
mod run;
|
||||
|
||||
use crate::env::setup_env;
|
||||
use crate::error::NymvisorError;
|
||||
use clap::{Parser, Subcommand};
|
||||
use lazy_static::lazy_static;
|
||||
use nym_bin_common::bin_info;
|
||||
@@ -23,14 +25,18 @@ fn pretty_build_info_static() -> &'static str {
|
||||
#[derive(Parser, Debug)]
|
||||
#[clap(author = "Nymtech", version, long_version = pretty_build_info_static(), about)]
|
||||
pub(crate) struct Cli {
|
||||
// I doubt we're gonna need any global flags here, but I'm going to leave the the option open
|
||||
// so that'd be easier to add them later if needed
|
||||
/// Path pointing to an env file that configures the nymvisor and overrides any preconfigured values.
|
||||
#[clap(short, long)]
|
||||
pub(crate) config_env_file: Option<std::path::PathBuf>,
|
||||
|
||||
#[clap(subcommand)]
|
||||
command: Commands,
|
||||
}
|
||||
|
||||
impl Cli {
|
||||
pub(crate) fn execute(self) -> anyhow::Result<()> {
|
||||
pub(crate) fn execute(self) -> Result<(), NymvisorError> {
|
||||
setup_env(&self.config_env_file)?;
|
||||
|
||||
match self.command {
|
||||
Commands::Init(args) => init::execute(args),
|
||||
Commands::Run(args) => run::execute(args),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::error::NymvisorError;
|
||||
use tokio::runtime;
|
||||
|
||||
#[derive(clap::Args, Debug)]
|
||||
@@ -10,7 +11,7 @@ pub(crate) struct Args {
|
||||
daemon_args: Vec<String>,
|
||||
}
|
||||
|
||||
pub(crate) fn execute(args: Args) -> anyhow::Result<()> {
|
||||
pub(crate) fn execute(args: Args) -> Result<(), NymvisorError> {
|
||||
// TODO: experiment with the minimal runtime
|
||||
// look at futures::executor::LocalPool
|
||||
let rt = runtime::Builder::new_current_thread().enable_io().build()?;
|
||||
|
||||
@@ -123,6 +123,7 @@ impl Config {
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Nymvisor {
|
||||
/// ID specifies the human readable ID of this particular nymvisor instance.
|
||||
/// Can be overridden with $NYMVISOR_ID environmental variable.
|
||||
pub id: String,
|
||||
|
||||
/// Further optional configuration options associated with the nymvisor.
|
||||
@@ -134,10 +135,12 @@ pub struct Nymvisor {
|
||||
pub struct NymvisorDebug {
|
||||
/// If set to true, this will disable `nymvisor` logs (but not the underlying process)
|
||||
/// default: false
|
||||
/// Can be overridden with $NYMVISOR_DISABLE_LOGS environmental variable.
|
||||
pub disable_logs: bool,
|
||||
|
||||
/// Set custom directory for upgrade data - binaries and upgrade plans.
|
||||
/// If not set, the global nymvisors' data directory will be used instead.
|
||||
/// Can be overridden with $NYMVISOR_DATA_UPGRADE_DIRECTORY environmental variable.
|
||||
#[serde(deserialize_with = "de_maybe_path")]
|
||||
pub data_upgrade_directory: Option<PathBuf>,
|
||||
}
|
||||
@@ -156,11 +159,13 @@ impl Default for NymvisorDebug {
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Daemon {
|
||||
/// The name of the managed binary itself (e.g. nym-api, nym-mixnode, nym-gateway, etc.)
|
||||
/// Can be overridden with $DAEMON_NAME environmental variable.
|
||||
pub name: String,
|
||||
|
||||
/// The location where the `nymvisor/` directory is kept that contains the auxiliary files associated
|
||||
/// with the underlying daemon, such as any backups or current version information.
|
||||
/// (e.g. $HOME/.nym/nym-api/my-nym-api, $HOME/.nym/mixnodes/my-mixnode, etc.).
|
||||
/// Can be overridden with $DAEMON_HOME environmental variable.
|
||||
pub home: String,
|
||||
|
||||
/// Further optional configuration options associated with the daemon.
|
||||
@@ -172,26 +177,31 @@ pub struct Daemon {
|
||||
pub struct DaemonDebug {
|
||||
/// If set to true, this will enable auto-downloading of new binaries using the url provided in the `upgrade-info.json`
|
||||
/// default: true
|
||||
/// Can be overridden with $DAEMON_ALLOW_BINARIES_DOWNLOAD environmental variable.
|
||||
pub allow_binaries_download: bool,
|
||||
|
||||
/// If enabled nymvisor will require that a checksum is provided in the upgrade plan for the binary to be downloaded.
|
||||
/// If disabled, nymvisor will not require a checksum to be provided, but still check the checksum if one is provided.
|
||||
/// default: true
|
||||
/// Can be overridden with $DAEMON_ENFORCE_DOWNLOAD_CHECKSUM environmental variable.
|
||||
pub enforce_download_checksum: bool,
|
||||
|
||||
/// If enabled, nymvisor will restart the subprocess with the same command-line arguments and flags (but with the new binary) after a successful upgrade.
|
||||
/// Otherwise (if disabled), nymvisor will stop running after an upgrade and will require the system administrator to manually restart it.
|
||||
/// Note restart is only after the upgrade and does not auto-restart the subprocess after an error occurs.
|
||||
/// default: true
|
||||
/// Can be overridden with $DAEMON_RESTART_AFTER_UPGRADE environmental variable.
|
||||
pub restart_after_upgrade: bool,
|
||||
|
||||
/// If enabled, nymvisor will restart the subprocess with the same command-line arguments and flags after it has crashed
|
||||
/// default: false
|
||||
/// Can be overridden with $DAEMON_RESTART_ON_FAILURE environmental variable.
|
||||
pub restart_on_failure: bool,
|
||||
|
||||
/// If `restart_on_failure` is enabled, the following value defines the amount of time `nymvisor` shall wait before
|
||||
/// restarting the subprocess.
|
||||
/// default: 10s
|
||||
/// Can be overridden with $DAEMON_FAILURE_RESTART_DELAY environmental variable.
|
||||
// The default value is so relatively high as to prevent constant restart loops in case of some underlying issue.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub failure_restart_delay: Duration,
|
||||
@@ -199,11 +209,13 @@ pub struct DaemonDebug {
|
||||
/// Defines the maximum number of startup failures the subprocess can experience in a quick succession before
|
||||
/// no further restarts will be attempted and `nymvisor` will exit/
|
||||
/// default: 10
|
||||
/// Can be overridden with $DAEMON_MAX_STARTUP_FAILURES environmental variable.
|
||||
pub max_startup_failures: usize,
|
||||
|
||||
/// Defines the length of time during which the subprocess is still considered to be in the startup phase
|
||||
/// when its failures are going to be considered in `max_startup_failures`.
|
||||
/// default: 120s
|
||||
/// Can be overridden with $DAEMON_STARTUP_PERIOD_DURATION environmental variable.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub startup_period_duration: Duration,
|
||||
|
||||
@@ -211,15 +223,18 @@ pub struct DaemonDebug {
|
||||
/// (for either an upgrade or shutdown of the `nymvisor` itself)
|
||||
/// Once the time passes, a kill signal is going to be sent instead.
|
||||
/// default: 10s
|
||||
/// Can be overridden with $DAEMON_SHUTDOWN_GRACE_PERIOD environmental variable.
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub shutdown_grace_period: Duration,
|
||||
|
||||
/// Set custom backup directory for daemon data. If not set, the daemon's home directory will be used instead.
|
||||
/// Can be overridden with $DAEMON_DATA_BACKUP_DIRECTORYenvironmental variable.
|
||||
#[serde(deserialize_with = "de_maybe_path")]
|
||||
pub data_backup_directory: Option<PathBuf>,
|
||||
|
||||
/// If enabled, `nymvisor` will perform upgrades directly without performing any backups.
|
||||
/// default: false
|
||||
/// Can be overridden with $DAEMON_UNSAFE_SKIP_BACKUP environmental variable.
|
||||
pub unsafe_skip_backup: bool,
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::error::NymvisorError;
|
||||
use std::env::VarError;
|
||||
use std::path::PathBuf;
|
||||
use std::time::Duration;
|
||||
|
||||
const TRUTHY_BOOLS: &[&str] = &["true", "t", "1"];
|
||||
const FALSY_BOOLS: &[&str] = &["false", "f", "0"];
|
||||
|
||||
pub mod vars {
|
||||
pub const NYMVISOR_ID: &str = "NYMVISOR_ID";
|
||||
pub const NYMVISOR_CONFIG_PATH: &str = "NYMVISOR_CONFIG_PATH";
|
||||
pub const NYMVISOR_DATA_DIRECTORY: &str = "NYMVISOR_DATA_DIRECTORY";
|
||||
pub const NYMVISOR_DISABLE_LOGS: &str = "NYMVISOR_DISABLE_LOGS";
|
||||
pub const NYMVISOR_DATA_UPGRADE_DIRECTORY: &str = "NYMVISOR_DATA_UPGRADE_DIRECTORY";
|
||||
|
||||
pub const DAEMON_NAME: &str = "DAEMON_NAME";
|
||||
pub const DAEMON_HOME: &str = "DAEMON_HOME";
|
||||
pub const DAEMON_ALLOW_BINARIES_DOWNLOAD: &str = "DAEMON_ALLOW_BINARIES_DOWNLOAD";
|
||||
pub const DAEMON_ENFORCE_DOWNLOAD_CHECKSUM: &str = "DAEMON_ENFORCE_DOWNLOAD_CHECKSUM";
|
||||
pub const DAEMON_RESTART_AFTER_UPGRADE: &str = "DAEMON_RESTART_AFTER_UPGRADE";
|
||||
pub const DAEMON_RESTART_ON_FAILURE: &str = "DAEMON_RESTART_ON_FAILURE";
|
||||
pub const DAEMON_FAILURE_RESTART_DELAY: &str = "DAEMON_FAILURE_RESTART_DELAY";
|
||||
pub const DAEMON_MAX_STARTUP_FAILURES: &str = "DAEMON_MAX_STARTUP_FAILURES";
|
||||
pub const DAEMON_STARTUP_PERIOD_DURATION: &str = "DAEMON_STARTUP_PERIOD_DURATION";
|
||||
pub const DAEMON_SHUTDOWN_GRACE_PERIOD: &str = "DAEMON_SHUTDOWN_GRACE_PERIOD";
|
||||
pub const DAEMON_DATA_BACKUP_DIRECTORY: &str = "DAEMON_DATA_BACKUP_DIRECTORY";
|
||||
pub const DAEMON_UNSAFE_SKIP_BACKUP: &str = "DAEMON_UNSAFE_SKIP_BACKUP";
|
||||
}
|
||||
|
||||
pub(crate) fn setup_env(config_env_file: &Option<PathBuf>) -> Result<(), NymvisorError> {
|
||||
if let Some(env_file) = config_env_file {
|
||||
dotenvy::from_path_override(env_file).map_err(Into::into)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct Env {
|
||||
pub(crate) nymvisor_id: Option<String>,
|
||||
pub(crate) nymvisor_config_path: Option<PathBuf>,
|
||||
pub(crate) nymvisor_data_directory: Option<PathBuf>,
|
||||
pub(crate) nymvisor_disable_logs: Option<bool>,
|
||||
pub(crate) nymvisor_data_upgrade_directory: Option<PathBuf>,
|
||||
|
||||
pub(crate) daemon_name: Option<String>,
|
||||
pub(crate) daemon_home: Option<PathBuf>,
|
||||
pub(crate) daemon_allow_binaries_download: Option<bool>,
|
||||
pub(crate) daemon_enforce_download_checksum: Option<bool>,
|
||||
pub(crate) daemon_restart_after_upgrade: Option<bool>,
|
||||
pub(crate) daemon_restart_on_failure: Option<bool>,
|
||||
pub(crate) daemon_failure_restart_delay: Option<Duration>,
|
||||
pub(crate) daemon_max_startup_failures: Option<usize>,
|
||||
pub(crate) daemon_startup_period_duration: Option<Duration>,
|
||||
pub(crate) daemon_shutdown_grace_period: Option<Duration>,
|
||||
pub(crate) daemon_data_backup_directory: Option<PathBuf>,
|
||||
pub(crate) daemon_unsafe_skip_backup: Option<bool>,
|
||||
}
|
||||
|
||||
// TODO: all of those seem like they could be moved to some common crate if we ever needed similar functionality elsewhere
|
||||
fn read_string(var: &str) -> Result<Option<String>, NymvisorError> {
|
||||
match std::env::var(var) {
|
||||
Ok(val) => Ok(Some(val)),
|
||||
Err(VarError::NotPresent) => Ok(None),
|
||||
Err(VarError::NotUnicode(value)) => Err(NymvisorError::MalformedEnvVariable {
|
||||
variable: var.to_string(),
|
||||
value,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
fn read_bool(var: &str) -> Result<Option<bool>, NymvisorError> {
|
||||
read_string(var)?
|
||||
.map(|raw| {
|
||||
let normalised = raw.to_ascii_lowercase();
|
||||
if TRUTHY_BOOLS.contains(&&*normalised) {
|
||||
Ok(true)
|
||||
} else if FALSY_BOOLS.contains(&&*normalised) {
|
||||
Ok(false)
|
||||
} else {
|
||||
Err(NymvisorError::MalformedBoolEnvVariable {
|
||||
variable: var.to_string(),
|
||||
value: raw.to_string(),
|
||||
})
|
||||
}
|
||||
})
|
||||
.transpose()
|
||||
}
|
||||
|
||||
fn read_duration(var: &str) -> Result<Option<Duration>, NymvisorError> {
|
||||
read_string(var)?
|
||||
.map(|raw| {
|
||||
humantime::parse_duration(&raw).map_err(|source| {
|
||||
NymvisorError::MalformedDurationEnvVariable {
|
||||
variable: var.to_string(),
|
||||
value: raw.to_string(),
|
||||
source,
|
||||
}
|
||||
})
|
||||
})
|
||||
.transpose()
|
||||
}
|
||||
|
||||
fn read_pathbuf(var: &str) -> Result<Option<PathBuf>, NymvisorError> {
|
||||
Ok(read_string(var)?.map(PathBuf::from))
|
||||
}
|
||||
|
||||
fn read_usize(var: &str) -> Result<Option<usize>, NymvisorError> {
|
||||
read_string(var)?
|
||||
.map(|raw| {
|
||||
raw.parse()
|
||||
.map_err(|source| NymvisorError::MalformedNumberEnvVariable {
|
||||
variable: var.to_string(),
|
||||
value: raw.to_string(),
|
||||
source,
|
||||
})
|
||||
})
|
||||
.transpose()
|
||||
}
|
||||
|
||||
impl Env {
|
||||
// in general, if variable is missing from the environment that's fine.
|
||||
// however, if something is out there, it MUST BE valid
|
||||
pub(crate) fn try_read() -> Result<Self, NymvisorError> {
|
||||
Ok(Env {
|
||||
nymvisor_id: read_string(vars::NYMVISOR_ID)?,
|
||||
nymvisor_config_path: read_pathbuf(vars::NYMVISOR_CONFIG_PATH)?,
|
||||
nymvisor_data_directory: read_pathbuf(vars::NYMVISOR_DATA_DIRECTORY)?,
|
||||
nymvisor_disable_logs: read_bool(vars::NYMVISOR_DISABLE_LOGS)?,
|
||||
nymvisor_data_upgrade_directory: read_pathbuf(vars::NYMVISOR_DATA_UPGRADE_DIRECTORY)?,
|
||||
daemon_name: read_string(vars::DAEMON_NAME)?,
|
||||
daemon_home: read_pathbuf(vars::DAEMON_HOME)?,
|
||||
daemon_allow_binaries_download: read_bool(vars::DAEMON_ALLOW_BINARIES_DOWNLOAD)?,
|
||||
daemon_enforce_download_checksum: read_bool(vars::DAEMON_ENFORCE_DOWNLOAD_CHECKSUM)?,
|
||||
daemon_restart_after_upgrade: read_bool(vars::DAEMON_RESTART_AFTER_UPGRADE)?,
|
||||
daemon_restart_on_failure: read_bool(vars::DAEMON_RESTART_ON_FAILURE)?,
|
||||
daemon_failure_restart_delay: read_duration(vars::DAEMON_FAILURE_RESTART_DELAY)?,
|
||||
daemon_max_startup_failures: read_usize(vars::DAEMON_MAX_STARTUP_FAILURES)?,
|
||||
daemon_startup_period_duration: read_duration(vars::DAEMON_STARTUP_PERIOD_DURATION)?,
|
||||
daemon_shutdown_grace_period: read_duration(vars::DAEMON_SHUTDOWN_GRACE_PERIOD)?,
|
||||
daemon_data_backup_directory: read_pathbuf(vars::DAEMON_DATA_BACKUP_DIRECTORY)?,
|
||||
daemon_unsafe_skip_backup: read_bool(vars::DAEMON_UNSAFE_SKIP_BACKUP)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use std::ffi::OsString;
|
||||
use std::io;
|
||||
use std::num::ParseIntError;
|
||||
use std::path::PathBuf;
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub(crate) enum NymvisorError {
|
||||
#[error(
|
||||
"failed to load config file for id {id} using path '{}'. detailed message: {source}", path.display()
|
||||
)]
|
||||
ConfigLoadFailure {
|
||||
id: String,
|
||||
path: PathBuf,
|
||||
#[source]
|
||||
source: io::Error,
|
||||
},
|
||||
|
||||
#[error(
|
||||
"failed to save config file for id {id} using path '{}'. detailed message: {source}", path.display()
|
||||
)]
|
||||
ConfigSaveFailure {
|
||||
id: String,
|
||||
path: PathBuf,
|
||||
#[source]
|
||||
source: io::Error,
|
||||
},
|
||||
|
||||
#[error("the provided env file was malformed: {source}")]
|
||||
MalformedEnvFile {
|
||||
#[from]
|
||||
source: dotenvy::Error,
|
||||
},
|
||||
|
||||
#[error("the value provided for environmental variable '{variable}' was not valid unicode: {value:?}")]
|
||||
MalformedEnvVariable { variable: String, value: OsString },
|
||||
|
||||
#[error("the value provided for environmental boolean variable '{variable}': '{value}' is not a valid boolean")]
|
||||
MalformedBoolEnvVariable { variable: String, value: String },
|
||||
|
||||
#[error("the value provided for environmental duration variable '{variable}': '{value}' is not a valid duration: {source}")]
|
||||
MalformedDurationEnvVariable {
|
||||
variable: String,
|
||||
value: String,
|
||||
#[source]
|
||||
source: humantime::DurationError,
|
||||
},
|
||||
|
||||
#[error("the value provided for environmental numerical variable '{variable}': '{value}' is not a valid number: {source}")]
|
||||
MalformedNumberEnvVariable {
|
||||
variable: String,
|
||||
value: String,
|
||||
#[source]
|
||||
source: ParseIntError,
|
||||
},
|
||||
}
|
||||
@@ -6,10 +6,12 @@ use clap::Parser;
|
||||
|
||||
pub(crate) mod cli;
|
||||
pub(crate) mod config;
|
||||
pub(crate) mod env;
|
||||
pub(crate) mod error;
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
let args = Cli::parse();
|
||||
println!("{args:#?}");
|
||||
|
||||
args.execute()
|
||||
Ok(args.execute()?)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user