wip
This commit is contained in:
Generated
+2
@@ -7612,8 +7612,10 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"time",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -159,6 +159,7 @@ schemars = "0.8.1"
|
||||
serde = "1.0.152"
|
||||
serde_json = "1.0.91"
|
||||
tap = "1.0.1"
|
||||
time = "0.3.30"
|
||||
thiserror = "1.0.48"
|
||||
tokio = "1.24.1"
|
||||
tokio-tungstenite = "0.20.1"
|
||||
|
||||
@@ -21,7 +21,7 @@ rand = {version = "0.6", features = ["std"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
time = { version = "0.3.6", features = ["parsing", "formatting"] }
|
||||
time = { workspace = true, features = ["parsing", "formatting"] }
|
||||
toml = "0.5.6"
|
||||
url = { workspace = true }
|
||||
tap = "1"
|
||||
|
||||
@@ -25,12 +25,12 @@ humantime-serde = "1.1.1"
|
||||
|
||||
# TO CHECK WHETHER STILL NEEDED:
|
||||
log = { workspace = true }
|
||||
time = { version = "0.3.6", features = ["parsing", "formatting"] }
|
||||
time = { workspace = true, features = ["parsing", "formatting"] }
|
||||
ts-rs = { workspace = true, optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
rand_chacha = "0.3"
|
||||
time = { version = "0.3.5", features = ["serde", "macros"] }
|
||||
time = { workspace = true, features = ["serde", "macros"] }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
Generated
+27
-10
@@ -551,6 +551,15 @@ dependencies = [
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3"
|
||||
dependencies = [
|
||||
"powerfmt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derivative"
|
||||
version = "2.2.0"
|
||||
@@ -1558,6 +1567,12 @@ version = "0.3.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
|
||||
|
||||
[[package]]
|
||||
name = "powerfmt"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.17"
|
||||
@@ -1870,9 +1885,9 @@ checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.160"
|
||||
version = "1.0.190"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c"
|
||||
checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
@@ -1888,9 +1903,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.160"
|
||||
version = "1.0.190"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df"
|
||||
checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -2085,11 +2100,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.20"
|
||||
version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890"
|
||||
checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5"
|
||||
dependencies = [
|
||||
"deranged",
|
||||
"itoa",
|
||||
"powerfmt",
|
||||
"serde",
|
||||
"time-core",
|
||||
"time-macros",
|
||||
@@ -2097,15 +2114,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "time-core"
|
||||
version = "0.1.0"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd"
|
||||
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
|
||||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.8"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd80a657e71da814b8e5d60d3374fc6d35045062245d80224748ae522dd76f36"
|
||||
checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20"
|
||||
dependencies = [
|
||||
"time-core",
|
||||
]
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
tap = "1.0"
|
||||
thiserror = { workspace = true }
|
||||
time = { version = "0.3.14", features = ["serde-human-readable", "parsing"] }
|
||||
time = { workspace = true, features = ["serde-human-readable", "parsing"] }
|
||||
tokio = { version = "1.24.1", features = [
|
||||
"rt-multi-thread",
|
||||
"macros",
|
||||
|
||||
Generated
+20
-12
@@ -1578,10 +1578,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.3.7"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7684a49fb1af197853ef7b2ee694bc1f5b4179556f1e5710e1760c5db6f5e929"
|
||||
checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3"
|
||||
dependencies = [
|
||||
"powerfmt",
|
||||
"serde",
|
||||
]
|
||||
|
||||
@@ -5291,6 +5292,12 @@ dependencies = [
|
||||
"universal-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "powerfmt"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.17"
|
||||
@@ -6214,9 +6221,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.183"
|
||||
version = "1.0.190"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c"
|
||||
checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
@@ -6241,9 +6248,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.183"
|
||||
version = "1.0.190"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816"
|
||||
checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -7394,15 +7401,16 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.25"
|
||||
version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0fdd63d58b18d663fbdf70e049f00a22c8e42be082203be7f26589213cd75ea"
|
||||
checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5"
|
||||
dependencies = [
|
||||
"deranged",
|
||||
"itoa 1.0.9",
|
||||
"js-sys",
|
||||
"libc",
|
||||
"num_threads",
|
||||
"powerfmt",
|
||||
"serde",
|
||||
"time-core",
|
||||
"time-macros",
|
||||
@@ -7410,15 +7418,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "time-core"
|
||||
version = "0.1.1"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb"
|
||||
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
|
||||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.11"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb71511c991639bb078fd5bf97757e03914361c48100d52878b8e52b46fb92cd"
|
||||
checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20"
|
||||
dependencies = [
|
||||
"time-core",
|
||||
]
|
||||
|
||||
@@ -21,6 +21,7 @@ lazy_static = { workspace = true }
|
||||
nix = { version = "0.27.1", features = ["signal"] }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = { workspace = true }
|
||||
time = { workspace = true, features = [ "serde-human-readable" ] }
|
||||
tokio = { workspace = true, features = ["rt", "macros", "signal", "process", "sync"] }
|
||||
thiserror = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::config::{default_config_filepath, Config, BIN_DIR};
|
||||
use crate::config::{default_config_filepath, Config, BIN_DIR, GENESIS_DIR};
|
||||
use crate::daemon::Daemon;
|
||||
use crate::env::Env;
|
||||
use crate::error::NymvisorError;
|
||||
use crate::upgrades::UpgradeInfo;
|
||||
use nym_bin_common::build_information::BinaryBuildInformationOwned;
|
||||
use nym_bin_common::logging::{setup_logging, setup_tracing_logger};
|
||||
use nym_bin_common::output_format::OutputFormat;
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::time::Duration;
|
||||
use time::OffsetDateTime;
|
||||
use tracing::{debug, error, info, trace, warn};
|
||||
use url::Url;
|
||||
|
||||
@@ -239,10 +241,10 @@ fn init_paths(config: &Config) -> Result<(), NymvisorError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn copy_genesis_binary(
|
||||
fn setup_genesis_binary(
|
||||
config: &Config,
|
||||
source_dir: &Path,
|
||||
daemon_info: &BinaryBuildInformationOwned,
|
||||
daemon_info: BinaryBuildInformationOwned,
|
||||
) -> Result<(), NymvisorError> {
|
||||
info!("setting up the genesis binary");
|
||||
let target = config.genesis_daemon_binary();
|
||||
@@ -262,6 +264,8 @@ fn copy_genesis_binary(
|
||||
};
|
||||
}
|
||||
|
||||
generate_and_save_genesis_upgrade_info(&config, daemon_info)?;
|
||||
|
||||
// TODO: setup initial upgrade-info.json file
|
||||
fs::copy(source_dir, &target).map_err(|source| NymvisorError::DaemonBinaryCopyFailure {
|
||||
source_path: source_dir.to_path_buf(),
|
||||
@@ -304,6 +308,25 @@ fn create_current_symlink(config: &Config) -> Result<(), NymvisorError> {
|
||||
})
|
||||
}
|
||||
|
||||
fn generate_and_save_genesis_upgrade_info(
|
||||
config: &Config,
|
||||
genesis_info: BinaryBuildInformationOwned,
|
||||
) -> Result<(), NymvisorError> {
|
||||
let info = UpgradeInfo {
|
||||
manual: true,
|
||||
name: GENESIS_DIR.to_string(),
|
||||
notes: "".to_string(),
|
||||
publish_date: None,
|
||||
version: genesis_info.build_version.clone(),
|
||||
platforms: Default::default(),
|
||||
upgrade_time: OffsetDateTime::UNIX_EPOCH,
|
||||
binary_details: Some(genesis_info),
|
||||
};
|
||||
let save_path = config.upgrade_info_filepath(&info.name);
|
||||
|
||||
info.save(save_path)
|
||||
}
|
||||
|
||||
fn save_config(config: Config, env: &Env) -> Result<(), NymvisorError> {
|
||||
let id = &config.nymvisor.id;
|
||||
let config_save_location = env
|
||||
@@ -327,15 +350,16 @@ fn save_config(config: Config, env: &Env) -> Result<(), NymvisorError> {
|
||||
}
|
||||
|
||||
/// Initialise the nymvisor by performing the following:
|
||||
/// - [✅] executing the `build-info` command on the daemon executable to check its validity and obtain its name
|
||||
/// - [✅] creating `<DAEMON_HOME>/nymvisor` folder if it doesn't yet exist
|
||||
/// - [✅] creating `<DAEMON_BACKUP_DATA_DIRECTORY>` folder if it doesn't yet exist
|
||||
/// - [✅] creating `<NYMVISOR_UPGRADE_DATA_DIRECTORY>` folder if it doesn't yet exist
|
||||
/// - [✅] creating `<NYMVISOR_UPGRADE_DATA_DIRECTORY>/<DAEMON_NAME>/genesis/bin` folder if it doesn't yet exist
|
||||
/// - [✅] creating `<NYMVISOR_UPGRADE_DATA_DIRECTORY>/<DAEMON_NAME>/upgrades` folder if it doesn't yet exist
|
||||
/// - [⚠️] copying the provided executable to `<NYMVISOR_UPGRADE_DATA_DIRECTORY>/<DAEMON_NAME>/genesis/bin/<DAEMON_NAME>`
|
||||
/// - [✅] creating a `<NYMVISOR_UPGRADE_DATA_DIRECTORY>/<DAEMON_NAME>/current` symlink pointing to `<NYMVISOR_UPGRADE_DATA_DIRECTORY>/<DAEMON_NAME>/genesis`
|
||||
/// - [✅] saving nymvisor's config file to `<NYMVISOR_CONFIG_PATH>` and creating the full directory structure.
|
||||
/// - executing the `build-info` command on the daemon executable to check its validity and obtain its name
|
||||
/// - creating `<DAEMON_HOME>/nymvisor` folder if it doesn't yet exist
|
||||
/// - creating `<DAEMON_BACKUP_DATA_DIRECTORY>` folder if it doesn't yet exist
|
||||
/// - creating `<NYMVISOR_UPGRADE_DATA_DIRECTORY>` folder if it doesn't yet exist
|
||||
/// - creating `<NYMVISOR_UPGRADE_DATA_DIRECTORY>/<DAEMON_NAME>/genesis/bin` folder if it doesn't yet exist
|
||||
/// - creating `<NYMVISOR_UPGRADE_DATA_DIRECTORY>/<DAEMON_NAME>/upgrades` folder if it doesn't yet exist
|
||||
/// - copying the provided executable to `<NYMVISOR_UPGRADE_DATA_DIRECTORY>/<DAEMON_NAME>/genesis/bin/<DAEMON_NAME>`
|
||||
/// - generating initial `<NYMVISOR_UPGRADE_DATA_DIRECTORY>/<DAEMON_NAME>/genesis/upgrade-info.json` file
|
||||
/// - creating a `<NYMVISOR_UPGRADE_DATA_DIRECTORY>/<DAEMON_NAME>/current` symlink pointing to `<NYMVISOR_UPGRADE_DATA_DIRECTORY>/<DAEMON_NAME>/genesis`
|
||||
/// - saving nymvisor's config file to `<NYMVISOR_CONFIG_PATH>` and creating the full directory structure.
|
||||
///
|
||||
/// note: it requires either passing `--daemon-home` flag or setting the `$DAEMON_HOME` environmental variable
|
||||
pub(crate) fn execute(args: Args) -> Result<(), NymvisorError> {
|
||||
@@ -356,7 +380,7 @@ pub(crate) fn execute(args: Args) -> Result<(), NymvisorError> {
|
||||
let config = try_build_config(&args, &env, &daemon_info)?;
|
||||
|
||||
init_paths(&config)?;
|
||||
copy_genesis_binary(&config, &args.daemon_binary, &daemon_info)?;
|
||||
setup_genesis_binary(&config, &args.daemon_binary, daemon_info)?;
|
||||
create_current_symlink(&config)?;
|
||||
save_config(config, &env)?;
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ use crate::env::Env;
|
||||
use crate::error::NymvisorError;
|
||||
use async_file_watcher::AsyncFileWatcher;
|
||||
use futures::channel::mpsc;
|
||||
use futures::future::{AbortHandle, Abortable};
|
||||
use futures::StreamExt;
|
||||
use nym_bin_common::logging::setup_tracing_logger;
|
||||
use std::sync::Arc;
|
||||
@@ -59,13 +60,17 @@ pub(crate) fn execute(args: Args) -> Result<(), NymvisorError> {
|
||||
events_sender,
|
||||
)?;
|
||||
|
||||
let handle2 = tokio::spawn(async move { watcher.watch().await });
|
||||
let (abort_handle, abort_registration) = AbortHandle::new_pair();
|
||||
|
||||
let handle2 =
|
||||
tokio::spawn(async move { Abortable::new(watcher.watch(), abort_registration).await });
|
||||
|
||||
let event = events_receiver.next().await;
|
||||
println!("watcher event: {event:?}");
|
||||
interrupt_notify.notify_one();
|
||||
|
||||
handle1.await;
|
||||
abort_handle.abort();
|
||||
handle2.await;
|
||||
|
||||
// println!("{:?}", status);
|
||||
|
||||
@@ -100,6 +100,7 @@ impl Display for Config {
|
||||
{:<35}{}
|
||||
{:<35}{}
|
||||
{:<35}{}
|
||||
{:<35}{}
|
||||
{:<35}{:?}
|
||||
{:<35}{}
|
||||
{:<35}{}
|
||||
@@ -109,6 +110,7 @@ impl Display for Config {
|
||||
{:<35}{}
|
||||
{:<35}{}
|
||||
{:<35}{}
|
||||
{:<35}{}
|
||||
{:<35}{:?}
|
||||
{:<35}{}
|
||||
"#,
|
||||
@@ -118,6 +120,8 @@ impl Display for Config {
|
||||
self.daemon.name,
|
||||
"daemon home:",
|
||||
self.daemon.home.display(),
|
||||
"upstream base upgrade url:",
|
||||
self.nymvisor.debug.upstream_base_upgrade_url,
|
||||
"disable nymvisor logs:",
|
||||
self.nymvisor.debug.disable_logs,
|
||||
"CUSTOM upgrade data directory",
|
||||
@@ -127,6 +131,13 @@ impl Display for Config {
|
||||
.as_ref()
|
||||
.map(|p| p.display().to_string())
|
||||
.unwrap_or_default(),
|
||||
"upstream absolute upgrade url:",
|
||||
self.daemon
|
||||
.debug
|
||||
.absolute_upstream_upgrade_url
|
||||
.as_ref()
|
||||
.map(|p| p.to_string())
|
||||
.unwrap_or_default(),
|
||||
"allow binaries download:",
|
||||
self.daemon.debug.allow_binaries_download,
|
||||
"enforce download checksum:",
|
||||
@@ -229,6 +240,7 @@ impl Config {
|
||||
}
|
||||
}
|
||||
|
||||
// e.g. $HOME/.nym/nymvisors/data/nym-api/
|
||||
pub fn upgrade_data_dir(&self) -> PathBuf {
|
||||
self.nymvisor
|
||||
.debug
|
||||
@@ -237,30 +249,48 @@ impl Config {
|
||||
.unwrap_or(default_global_data_directory().join(&self.daemon.name))
|
||||
}
|
||||
|
||||
// e.g. $HOME/.nym/nymvisors/data/nym-api/genesis
|
||||
pub fn genesis_daemon_dir(&self) -> PathBuf {
|
||||
self.upgrade_data_dir().join(GENESIS_DIR)
|
||||
}
|
||||
|
||||
// e.g. $HOME/.nym/nymvisors/data/nym-api/genesis/bin/nym-api
|
||||
pub fn genesis_daemon_binary(&self) -> PathBuf {
|
||||
self.genesis_daemon_dir()
|
||||
.join(BIN_DIR)
|
||||
.join(&self.daemon.name)
|
||||
}
|
||||
|
||||
// e.g. $HOME/.nym/nymvisors/data/nym-api/current
|
||||
pub fn current_daemon_dir(&self) -> PathBuf {
|
||||
self.upgrade_data_dir().join(CURRENT_DIR)
|
||||
}
|
||||
|
||||
// e.g. $HOME/.nym/nymvisors/data/nym-api/current/bin/nym-api
|
||||
pub fn current_daemon_binary(&self) -> PathBuf {
|
||||
self.current_daemon_dir()
|
||||
.join(BIN_DIR)
|
||||
.join(&self.daemon.name)
|
||||
}
|
||||
|
||||
// e.g. $HOME/.nym/nymvisors/data/nym-api/upgrades/<upgrade-name>/upgrade-info.json
|
||||
// or $HOME/.nym/nymvisors/data/nym-api/genesis/upgrade-info.json
|
||||
pub fn upgrade_info_filepath<S: AsRef<str>>(&self, upgrade_name: S) -> PathBuf {
|
||||
// special case for genesis
|
||||
let name = upgrade_name.as_ref();
|
||||
if name == GENESIS_DIR {
|
||||
self.genesis_daemon_dir().join(UPGRADE_INFO_FILENAME)
|
||||
} else {
|
||||
self.upgrades_dir().join(name).join(UPGRADE_INFO_FILENAME)
|
||||
}
|
||||
}
|
||||
|
||||
// e.g. $HOME/.nym/nymvisors/data/nym-api/upgrades/
|
||||
pub fn upgrades_dir(&self) -> PathBuf {
|
||||
self.upgrade_data_dir().join(UPGRADES_DIR)
|
||||
}
|
||||
|
||||
// e.g. $HOME/.nym/nymvisors/data/nym-api/upgrade-plan.json
|
||||
pub fn upgrade_plan_filepath(&self) -> PathBuf {
|
||||
self.upgrade_data_dir().join(UPGRADE_PLAN_FILENAME)
|
||||
}
|
||||
|
||||
@@ -33,6 +33,26 @@ pub(crate) enum NymvisorError {
|
||||
source: io::Error,
|
||||
},
|
||||
|
||||
#[error(
|
||||
"failed to load upgrade info for upgrade '{name}' using path '{}'. detailed message: {source}", path.display()
|
||||
)]
|
||||
UpgradeInfoLoadFailure {
|
||||
name: String,
|
||||
path: PathBuf,
|
||||
#[source]
|
||||
source: io::Error,
|
||||
},
|
||||
|
||||
#[error(
|
||||
"failed to save upgrade info for upgrade '{name}' using path '{}'. detailed message: {source}", path.display()
|
||||
)]
|
||||
UpgradeInfoSaveFailure {
|
||||
name: String,
|
||||
path: PathBuf,
|
||||
#[source]
|
||||
source: io::Error,
|
||||
},
|
||||
|
||||
#[error("failed to initialise the path '{}': {source}", path.display())]
|
||||
PathInitFailure {
|
||||
path: PathBuf,
|
||||
|
||||
@@ -8,7 +8,25 @@ pub(crate) struct DaemonLauncher {
|
||||
}
|
||||
|
||||
impl DaemonLauncher {
|
||||
pub(crate) fn run(args: Vec<String>) {
|
||||
pub(crate) fn new(config: Config) -> Self {
|
||||
todo!()
|
||||
}
|
||||
|
||||
// responsible for running until exit or until update is detected
|
||||
pub(crate) fn run(&self, args: Vec<String>) {
|
||||
/*
|
||||
|
||||
tokio select on:
|
||||
- daemon terminating
|
||||
- upgrade-plan.json changes
|
||||
- https://nymtech.net/.wellknown/<DAEMON_NAME>/update-info.json changes
|
||||
|
||||
|
||||
// todo: maybe move to a higher layer
|
||||
- signals received (to propagate them to daemon before terminating to prevent creating zombie processes)
|
||||
|
||||
*/
|
||||
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,167 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::error::NymvisorError;
|
||||
use nym_bin_common::build_information::BinaryBuildInformationOwned;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::fs::OpenOptions;
|
||||
use std::path::Path;
|
||||
use time::OffsetDateTime;
|
||||
|
||||
mod http_upstream;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub struct UpgradePlan {
|
||||
//
|
||||
pub current: UpgradeInfo,
|
||||
|
||||
pub next: Vec<UpgradeInfo>,
|
||||
}
|
||||
|
||||
impl UpgradePlan {
|
||||
pub(crate) fn update_on_disk(&self) -> Result<(), NymvisorError> {
|
||||
// 1. copy upgrade-plan.json to upgrade-plan.json.tmp
|
||||
// 2. update upgrade-plan.json.tmp
|
||||
// 3. move upgrade-plan.json.tmp to upgrade-plan.json
|
||||
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum DigestAlgorithm {
|
||||
Sha256,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub struct DownloadUrl {
|
||||
// TODO: get it from base64
|
||||
/// The checksum of the file behind the download url.
|
||||
pub checksum: Vec<u8>,
|
||||
|
||||
/// The algorithm used for computing the checksum
|
||||
pub checksum_algorithm: DigestAlgorithm,
|
||||
|
||||
/// Download url for this particular platform
|
||||
pub url: String,
|
||||
}
|
||||
|
||||
mod option_offsetdatetime {
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use time::OffsetDateTime;
|
||||
|
||||
pub fn serialize<S>(value: &Option<OffsetDateTime>, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
#[derive(Serialize)]
|
||||
struct Helper<'a>(#[serde(with = "time::serde::rfc3339")] &'a OffsetDateTime);
|
||||
|
||||
value.as_ref().map(Helper).serialize(serializer)
|
||||
}
|
||||
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<OffsetDateTime>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
#[derive(Deserialize)]
|
||||
struct Helper(#[serde(with = "time::serde::rfc3339")] OffsetDateTime);
|
||||
|
||||
let helper = Option::deserialize(deserializer)?;
|
||||
Ok(helper.map(|Helper(external)| external))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub struct UpgradeInfo {
|
||||
//
|
||||
/// Specifies whether this upgrade requires manual intervention and cannot be done automatically by the nymvisor.
|
||||
pub manual: bool,
|
||||
|
||||
/// Name of this upgrade, for example `2023.4-galaxy`
|
||||
pub name: String,
|
||||
|
||||
/// Additional information about this release
|
||||
pub notes: String,
|
||||
|
||||
/// Optional rfc3339 datetime of the publish date of the release,
|
||||
#[serde(with = "option_offsetdatetime")]
|
||||
pub publish_date: Option<OffsetDateTime>,
|
||||
|
||||
/// Version of this upgrade, for example `1.1.69`
|
||||
pub version: String,
|
||||
|
||||
/// Platform specific download urls, for example `linux-x86_64`
|
||||
pub platforms: HashMap<String, DownloadUrl>,
|
||||
|
||||
/// Time when the upgrade should happen.
|
||||
#[serde(with = "time::serde::rfc3339")]
|
||||
pub upgrade_time: OffsetDateTime,
|
||||
|
||||
/// Optional build information of the upgraded binary for additional verification
|
||||
pub binary_details: Option<BinaryBuildInformationOwned>,
|
||||
}
|
||||
|
||||
impl UpgradeInfo {
|
||||
pub(crate) fn save<P: AsRef<Path>>(&self, path: P) -> Result<(), NymvisorError> {
|
||||
let path = path.as_ref();
|
||||
let file = OpenOptions::new()
|
||||
.create(true)
|
||||
.write(true)
|
||||
.truncate(true)
|
||||
.open(path)
|
||||
.map_err(|source| NymvisorError::UpgradeInfoSaveFailure {
|
||||
name: self.name.clone(),
|
||||
path: path.to_path_buf(),
|
||||
source,
|
||||
})?;
|
||||
|
||||
// we're not using any non-standard serializer and thus the serialization should not ever fail
|
||||
#[allow(clippy::expect_used)]
|
||||
serde_json::to_writer_pretty(file, self)
|
||||
.expect("unexpected UpgradeInfo serialization failure");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn try_load<P: AsRef<Path>>(path: P) -> Result<Self, NymvisorError> {
|
||||
let file = std::fs::File::open(path)?;
|
||||
serde_json::from_reader(file).map_err(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub struct UpgradeHistory(Vec<UpgradeHistoryEntry>);
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub struct UpgradeHistoryEntry {
|
||||
performed_at: u64,
|
||||
#[serde(with = "time::serde::rfc3339")]
|
||||
performed_at: OffsetDateTime,
|
||||
info: UpgradeInfo,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn foo() {
|
||||
let a = UpgradeInfo {
|
||||
manual: false,
|
||||
name: "".to_string(),
|
||||
notes: "".to_string(),
|
||||
publish_date: None,
|
||||
version: "".to_string(),
|
||||
platforms: Default::default(),
|
||||
upgrade_time: OffsetDateTime::now_utc(),
|
||||
binary_details: None,
|
||||
};
|
||||
|
||||
let aa = serde_json::to_string_pretty(&a).unwrap();
|
||||
println!("{aa}")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user