allow gateways to migrate configs of embedded NR/IPR

This commit is contained in:
Jędrzej Stuczyński
2024-03-26 11:26:49 +00:00
parent 36f84ca18f
commit ebd1eeb38d
13 changed files with 251 additions and 184 deletions
+1 -1
View File
@@ -265,7 +265,7 @@ pub async fn execute(args: Init) -> anyhow::Result<()> {
);
eprintln!("Gateway configuration completed.\n\n\n");
output.to_stdout(&node_details(&config)?);
output.to_stdout(&node_details(&config).await?);
Ok(())
}
+1 -1
View File
@@ -18,7 +18,7 @@ pub struct NodeDetails {
pub async fn execute(args: NodeDetails) -> anyhow::Result<()> {
let config = try_load_current_config(&args.id)?;
args.output.to_stdout(&node_details(&config)?);
args.output.to_stdout(&node_details(&config).await?);
Ok(())
}
+1 -1
View File
@@ -248,7 +248,7 @@ pub async fn execute(args: Run) -> anyhow::Result<()> {
show_binding_warning(config.gateway.listening_address);
}
let node_details = node_details(&config)?;
let node_details = node_details(&config).await?;
let gateway =
crate::node::create_gateway(config, Some(nr_opts), Some(ip_opts), custom_mixnet).await?;
eprintln!(
+33 -5
View File
@@ -23,7 +23,9 @@ fn display_path<P: AsRef<Path>>(path: P) -> String {
path.as_ref().display().to_string()
}
pub(crate) fn node_details(config: &Config) -> Result<GatewayNodeDetailsResponse, GatewayError> {
pub(crate) async fn node_details(
config: &Config,
) -> Result<GatewayNodeDetailsResponse, GatewayError> {
let gateway_identity_public_key: identity::PublicKey = load_public_key(
&config.storage_paths.keys.public_identity_key_file,
"gateway identity",
@@ -36,7 +38,7 @@ pub(crate) fn node_details(config: &Config) -> Result<GatewayNodeDetailsResponse
let network_requester =
if let Some(nr_cfg_path) = &config.storage_paths.network_requester_config {
let cfg = load_network_requester_config(&config.gateway.id, nr_cfg_path)?;
let cfg = load_network_requester_config(&config.gateway.id, nr_cfg_path).await?;
let nr_identity_public_key: identity::PublicKey = load_public_key(
&cfg.storage_paths.common_paths.keys.public_identity_key_file,
@@ -75,7 +77,7 @@ pub(crate) fn node_details(config: &Config) -> Result<GatewayNodeDetailsResponse
let ip_packet_router = if let Some(nr_cfg_path) = &config.storage_paths.ip_packet_router_config
{
let cfg = load_ip_packet_router_config(&config.gateway.id, nr_cfg_path)?;
let cfg = load_ip_packet_router_config(&config.gateway.id, nr_cfg_path).await?;
let nr_identity_public_key: identity::PublicKey = load_public_key(
&cfg.storage_paths.common_paths.keys.public_identity_key_file,
@@ -120,7 +122,33 @@ pub(crate) fn node_details(config: &Config) -> Result<GatewayNodeDetailsResponse
})
}
pub(crate) fn load_network_requester_config<P: AsRef<Path>>(
pub(crate) async fn load_network_requester_config<P: AsRef<Path>>(
id: &str,
path: P,
) -> Result<nym_network_requester::Config, GatewayError> {
let path = path.as_ref();
if let Ok(cfg) = read_network_requester_config(id, path) {
return Ok(cfg);
}
nym_network_requester::config::helpers::try_upgrade_config(path).await?;
read_network_requester_config(id, path)
}
pub(crate) async fn load_ip_packet_router_config<P: AsRef<Path>>(
id: &str,
path: P,
) -> Result<nym_ip_packet_router::Config, GatewayError> {
let path = path.as_ref();
if let Ok(cfg) = read_ip_packet_router_config(id, path) {
return Ok(cfg);
}
nym_ip_packet_router::config::helpers::try_upgrade_config(path).await?;
read_ip_packet_router_config(id, path)
}
fn read_network_requester_config<P: AsRef<Path>>(
id: &str,
path: P,
) -> Result<nym_network_requester::Config, GatewayError> {
@@ -134,7 +162,7 @@ pub(crate) fn load_network_requester_config<P: AsRef<Path>>(
})
}
pub(crate) fn load_ip_packet_router_config<P: AsRef<Path>>(
fn read_ip_packet_router_config<P: AsRef<Path>>(
id: &str,
path: P,
) -> Result<nym_ip_packet_router::Config, GatewayError> {
+2 -2
View File
@@ -62,7 +62,7 @@ pub(crate) async fn create_gateway(
// don't attempt to read config if NR is disabled
let network_requester_config = if config.network_requester.enabled {
if let Some(path) = &config.storage_paths.network_requester_config {
let cfg = load_network_requester_config(&config.gateway.id, path)?;
let cfg = load_network_requester_config(&config.gateway.id, path).await?;
Some(override_network_requester_config(cfg, nr_config_override))
} else {
// if NR is enabled, the config path must be specified
@@ -75,7 +75,7 @@ pub(crate) async fn create_gateway(
// don't attempt to read config if NR is disabled
let ip_packet_router_config = if config.ip_packet_router.enabled {
if let Some(path) = &config.storage_paths.ip_packet_router_config {
let cfg = load_ip_packet_router_config(&config.gateway.id, path)?;
let cfg = load_ip_packet_router_config(&config.gateway.id, path).await?;
Some(override_ip_packet_router_config(cfg, ip_config_override))
} else {
// if IPR is enabled, the config path must be specified
@@ -1,11 +1,10 @@
use clap::{CommandFactory, Parser, Subcommand};
use log::{error, info, trace};
use log::error;
use nym_bin_common::completions::{fig_generate, ArgShell};
use nym_bin_common::{bin_info, version_checker};
use nym_client_core::cli_helpers::client_import_credential::CommonClientImportCredentialArgs;
use nym_client_core::cli_helpers::CliClient;
use nym_client_core::client::base_client::storage::migration_helpers::v1_1_33;
use nym_ip_packet_router::config::old_config_v1::ConfigV1;
use nym_ip_packet_router::config::helpers::try_upgrade_config;
use nym_ip_packet_router::config::{BaseClientConfig, Config};
use nym_ip_packet_router::error::IpPacketRouterError;
use std::sync::OnceLock;
@@ -136,40 +135,6 @@ pub(crate) async fn execute(args: Cli) -> Result<(), IpPacketRouterError> {
Ok(())
}
async fn try_upgrade_v1_config(id: &str) -> Result<bool, IpPacketRouterError> {
// explicitly load it as v1 (which is incompatible with the current one)
let Ok(old_config) = ConfigV1::read_from_default_path(id) else {
// if we failed to load it, there might have been nothing to upgrade
// or maybe it was an even older file. in either way. just ignore it and carry on with our day
return Ok(false);
};
info!("It seems the client is using v1 config template.");
info!("It is going to get updated to the current specification.");
let old_paths = old_config.storage_paths.clone();
let updated = old_config.try_upgrade()?;
v1_1_33::migrate_gateway_details(
&old_paths.common_paths,
&updated.storage_paths.common_paths,
None,
)
.await?;
updated.save_to_default_location()?;
Ok(true)
}
async fn try_upgrade_config(id: &str) -> Result<(), IpPacketRouterError> {
trace!("Attempting to upgrade config");
if try_upgrade_v1_config(id).await? {
return Ok(());
}
Ok(())
}
async fn try_load_current_config(id: &str) -> Result<Config, IpPacketRouterError> {
// try to load the config as is
if let Ok(cfg) = Config::read_from_default_path(id) {
@@ -0,0 +1,48 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::config::default_config_filepath;
use crate::config::old_config_v1::ConfigV1;
use crate::error::IpPacketRouterError;
use log::{info, trace};
use nym_client_core::client::base_client::storage::migration_helpers::v1_1_33;
use std::path::Path;
async fn try_upgrade_v1_config<P: AsRef<Path>>(
config_path: P,
) -> Result<bool, IpPacketRouterError> {
// explicitly load it as v1 (which is incompatible with the current one)
let Ok(old_config) = ConfigV1::read_from_toml_file(config_path) else {
// if we failed to load it, there might have been nothing to upgrade
// or maybe it was an even older file. in either way. just ignore it and carry on with our day
return Ok(false);
};
info!("It seems the client is using v1 config template.");
info!("It is going to get updated to the current specification.");
let old_paths = old_config.storage_paths.clone();
let updated = old_config.try_upgrade()?;
v1_1_33::migrate_gateway_details(
&old_paths.common_paths,
&updated.storage_paths.common_paths,
None,
)
.await?;
updated.save_to_default_location()?;
Ok(true)
}
pub async fn try_upgrade_config<P: AsRef<Path>>(config_path: P) -> Result<(), IpPacketRouterError> {
trace!("Attempting to upgrade config");
if try_upgrade_v1_config(config_path).await? {
return Ok(());
}
Ok(())
}
pub async fn try_upgrade_config_by_id(id: &str) -> Result<(), IpPacketRouterError> {
try_upgrade_config(default_config_filepath(id)).await
}
@@ -20,6 +20,7 @@ use crate::config::persistence::IpPacketRouterPaths;
use self::template::CONFIG_TEMPLATE;
pub mod helpers;
pub mod old_config_v1;
mod persistence;
mod template;
@@ -1,22 +1,18 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: GPL-3.0-only
use crate::config::old_config_v1_1_13::OldConfigV1_1_13;
use crate::config::old_config_v1_1_20::ConfigV1_1_20;
use crate::config::old_config_v1_1_20_2::ConfigV1_1_20_2;
use crate::config::old_config_v1_1_33::ConfigV1_1_33;
use crate::config::helpers::try_upgrade_config_by_id;
use crate::{
config::{BaseClientConfig, Config},
error::NetworkRequesterError,
};
use clap::{CommandFactory, Parser, Subcommand};
use log::{error, info, trace};
use log::error;
use nym_bin_common::bin_info;
use nym_bin_common::completions::{fig_generate, ArgShell};
use nym_bin_common::version_checker;
use nym_client_core::cli_helpers::client_import_credential::CommonClientImportCredentialArgs;
use nym_client_core::cli_helpers::CliClient;
use nym_client_core::client::base_client::storage::migration_helpers::v1_1_33;
use nym_config::OptionalSet;
use std::sync::OnceLock;
@@ -36,7 +32,7 @@ impl CliClient for CliNetworkRequesterClient {
type Config = Config;
async fn try_upgrade_outdated_config(id: &str) -> Result<(), Self::Error> {
try_upgrade_config(id).await
try_upgrade_config_by_id(id).await
}
async fn try_load_current_config(id: &str) -> Result<Self::Config, Self::Error> {
@@ -190,135 +186,6 @@ pub(crate) async fn execute(args: Cli) -> Result<(), NetworkRequesterError> {
Ok(())
}
async fn try_upgrade_v1_1_13_config(id: &str) -> Result<bool, NetworkRequesterError> {
trace!("Trying to load as v1.1.13 config");
use nym_config::legacy_helpers::nym_config::MigrationNymConfig;
// explicitly load it as v1.1.13 (which is incompatible with the next step, i.e. 1.1.19)
let Ok(old_config) = OldConfigV1_1_13::load_from_file(id) else {
// if we failed to load it, there might have been nothing to upgrade
// or maybe it was an even older file. in either way. just ignore it and carry on with our day
return Ok(false);
};
info!("It seems the client is using <= v1.1.13 config template.");
info!("It is going to get updated to the current specification.");
let updated_step1: ConfigV1_1_20 = old_config.into();
let updated_step2: ConfigV1_1_20_2 = updated_step1.into();
let (updated_step3, gateway_config) = updated_step2.upgrade()?;
let old_paths = updated_step3.storage_paths.clone();
let updated = updated_step3.try_upgrade()?;
v1_1_33::migrate_gateway_details(
&old_paths.common_paths,
&updated.storage_paths.common_paths,
Some(gateway_config),
)
.await?;
updated.save_to_default_location()?;
Ok(true)
}
async fn try_upgrade_v1_1_20_config(id: &str) -> Result<bool, NetworkRequesterError> {
trace!("Trying to load as v1.1.20 config");
use nym_config::legacy_helpers::nym_config::MigrationNymConfig;
// explicitly load it as v1.1.20 (which is incompatible with the current one, i.e. +1.1.21)
let Ok(old_config) = ConfigV1_1_20::load_from_file(id) else {
// if we failed to load it, there might have been nothing to upgrade
// or maybe it was an even older file. in either way. just ignore it and carry on with our day
return Ok(false);
};
info!("It seems the client is using <= v1.1.20 config template.");
info!("It is going to get updated to the current specification.");
let updated_step1: ConfigV1_1_20_2 = old_config.into();
let (updated_step2, gateway_config) = updated_step1.upgrade()?;
let old_paths = updated_step2.storage_paths.clone();
let updated = updated_step2.try_upgrade()?;
v1_1_33::migrate_gateway_details(
&old_paths.common_paths,
&updated.storage_paths.common_paths,
Some(gateway_config),
)
.await?;
updated.save_to_default_location()?;
Ok(true)
}
async fn try_upgrade_v1_1_20_2_config(id: &str) -> Result<bool, NetworkRequesterError> {
trace!("Trying to load as v1.1.20_2 config");
// explicitly load it as v1.1.20_2 (which is incompatible with the current one, i.e. +1.1.21)
let Ok(old_config) = ConfigV1_1_20_2::read_from_default_path(id) else {
// if we failed to load it, there might have been nothing to upgrade
// or maybe it was an even older file. in either way. just ignore it and carry on with our day
return Ok(false);
};
info!("It seems the client is using <= v1.1.20_2 config template.");
info!("It is going to get updated to the current specification.");
let (updated_step1, gateway_config) = old_config.upgrade()?;
let old_paths = updated_step1.storage_paths.clone();
let updated = updated_step1.try_upgrade()?;
v1_1_33::migrate_gateway_details(
&old_paths.common_paths,
&updated.storage_paths.common_paths,
Some(gateway_config),
)
.await?;
updated.save_to_default_location()?;
Ok(true)
}
async fn try_upgrade_v1_1_33_config(id: &str) -> Result<bool, NetworkRequesterError> {
// explicitly load it as v1.1.33 (which is incompatible with the current one, i.e. +1.1.34)
let Ok(old_config) = ConfigV1_1_33::read_from_default_path(id) else {
// if we failed to load it, there might have been nothing to upgrade
// or maybe it was an even older file. in either way. just ignore it and carry on with our day
return Ok(false);
};
info!("It seems the client is using <= v1.1.33 config template.");
info!("It is going to get updated to the current specification.");
let old_paths = old_config.storage_paths.clone();
let updated = old_config.try_upgrade()?;
v1_1_33::migrate_gateway_details(
&old_paths.common_paths,
&updated.storage_paths.common_paths,
None,
)
.await?;
updated.save_to_default_location()?;
Ok(true)
}
async fn try_upgrade_config(id: &str) -> Result<(), NetworkRequesterError> {
trace!("Attempting to upgrade config");
if try_upgrade_v1_1_13_config(id).await? {
return Ok(());
}
if try_upgrade_v1_1_20_config(id).await? {
return Ok(());
}
if try_upgrade_v1_1_20_2_config(id).await? {
return Ok(());
}
if try_upgrade_v1_1_33_config(id).await? {
return Ok(());
}
Ok(())
}
async fn try_load_current_config(id: &str) -> Result<Config, NetworkRequesterError> {
// try to load the config as is
if let Ok(cfg) = Config::read_from_default_path(id) {
@@ -330,7 +197,7 @@ async fn try_load_current_config(id: &str) -> Result<Config, NetworkRequesterErr
}
// we couldn't load it - try upgrading it from older revisions
try_upgrade_config(id).await?;
try_upgrade_config_by_id(id).await?;
let config = match Config::read_from_default_path(id) {
Ok(cfg) => cfg,
@@ -0,0 +1,155 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::config::default_config_filepath;
use crate::config::old_config_v1_1_13::OldConfigV1_1_13;
use crate::config::old_config_v1_1_20::ConfigV1_1_20;
use crate::config::old_config_v1_1_20_2::ConfigV1_1_20_2;
use crate::config::old_config_v1_1_33::ConfigV1_1_33;
use crate::error::NetworkRequesterError;
use log::{info, trace};
use nym_client_core::client::base_client::storage::migration_helpers::v1_1_33;
use std::path::Path;
async fn try_upgrade_v1_1_13_config<P: AsRef<Path>>(
config_path: P,
) -> Result<bool, NetworkRequesterError> {
trace!("Trying to load as v1.1.13 config");
use nym_config::legacy_helpers::nym_config::MigrationNymConfig;
// explicitly load it as v1.1.13 (which is incompatible with the next step, i.e. 1.1.19)
let Ok(old_config) = OldConfigV1_1_13::load_from_filepath(config_path) else {
// if we failed to load it, there might have been nothing to upgrade
// or maybe it was an even older file. in either way. just ignore it and carry on with our day
return Ok(false);
};
info!("It seems the client is using <= v1.1.13 config template.");
info!("It is going to get updated to the current specification.");
let updated_step1: ConfigV1_1_20 = old_config.into();
let updated_step2: ConfigV1_1_20_2 = updated_step1.into();
let (updated_step3, gateway_config) = updated_step2.upgrade()?;
let old_paths = updated_step3.storage_paths.clone();
let updated = updated_step3.try_upgrade()?;
v1_1_33::migrate_gateway_details(
&old_paths.common_paths,
&updated.storage_paths.common_paths,
Some(gateway_config),
)
.await?;
updated.save_to_default_location()?;
Ok(true)
}
async fn try_upgrade_v1_1_20_config<P: AsRef<Path>>(
config_path: P,
) -> Result<bool, NetworkRequesterError> {
trace!("Trying to load as v1.1.20 config");
use nym_config::legacy_helpers::nym_config::MigrationNymConfig;
// explicitly load it as v1.1.20 (which is incompatible with the current one, i.e. +1.1.21)
let Ok(old_config) = ConfigV1_1_20::load_from_filepath(config_path) else {
// if we failed to load it, there might have been nothing to upgrade
// or maybe it was an even older file. in either way. just ignore it and carry on with our day
return Ok(false);
};
info!("It seems the client is using <= v1.1.20 config template.");
info!("It is going to get updated to the current specification.");
let updated_step1: ConfigV1_1_20_2 = old_config.into();
let (updated_step2, gateway_config) = updated_step1.upgrade()?;
let old_paths = updated_step2.storage_paths.clone();
let updated = updated_step2.try_upgrade()?;
v1_1_33::migrate_gateway_details(
&old_paths.common_paths,
&updated.storage_paths.common_paths,
Some(gateway_config),
)
.await?;
updated.save_to_default_location()?;
Ok(true)
}
async fn try_upgrade_v1_1_20_2_config<P: AsRef<Path>>(
config_path: P,
) -> Result<bool, NetworkRequesterError> {
trace!("Trying to load as v1.1.20_2 config");
// explicitly load it as v1.1.20_2 (which is incompatible with the current one, i.e. +1.1.21)
let Ok(old_config) = ConfigV1_1_20_2::read_from_toml_file(config_path) else {
// if we failed to load it, there might have been nothing to upgrade
// or maybe it was an even older file. in either way. just ignore it and carry on with our day
return Ok(false);
};
info!("It seems the client is using <= v1.1.20_2 config template.");
info!("It is going to get updated to the current specification.");
let (updated_step1, gateway_config) = old_config.upgrade()?;
let old_paths = updated_step1.storage_paths.clone();
let updated = updated_step1.try_upgrade()?;
v1_1_33::migrate_gateway_details(
&old_paths.common_paths,
&updated.storage_paths.common_paths,
Some(gateway_config),
)
.await?;
updated.save_to_default_location()?;
Ok(true)
}
async fn try_upgrade_v1_1_33_config<P: AsRef<Path>>(
config_path: P,
) -> Result<bool, NetworkRequesterError> {
// explicitly load it as v1.1.33 (which is incompatible with the current one, i.e. +1.1.34)
let Ok(old_config) = ConfigV1_1_33::read_from_toml_file(config_path) else {
// if we failed to load it, there might have been nothing to upgrade
// or maybe it was an even older file. in either way. just ignore it and carry on with our day
return Ok(false);
};
info!("It seems the client is using <= v1.1.33 config template.");
info!("It is going to get updated to the current specification.");
let old_paths = old_config.storage_paths.clone();
let updated = old_config.try_upgrade()?;
v1_1_33::migrate_gateway_details(
&old_paths.common_paths,
&updated.storage_paths.common_paths,
None,
)
.await?;
updated.save_to_default_location()?;
Ok(true)
}
pub async fn try_upgrade_config<P: AsRef<Path>>(
config_path: P,
) -> Result<(), NetworkRequesterError> {
trace!("Attempting to upgrade config");
if try_upgrade_v1_1_13_config(config_path.as_ref()).await? {
return Ok(());
}
if try_upgrade_v1_1_20_config(config_path.as_ref()).await? {
return Ok(());
}
if try_upgrade_v1_1_20_2_config(config_path.as_ref()).await? {
return Ok(());
}
if try_upgrade_v1_1_33_config(config_path).await? {
return Ok(());
}
Ok(())
}
pub async fn try_upgrade_config_by_id(id: &str) -> Result<(), NetworkRequesterError> {
try_upgrade_config(default_config_filepath(id)).await
}
@@ -23,6 +23,7 @@ use url::Url;
pub use nym_client_core::config::Config as BaseClientConfig;
pub mod helpers;
pub mod old_config_v1_1_13;
pub mod old_config_v1_1_20;
pub mod old_config_v1_1_20_2;
@@ -55,6 +55,7 @@ impl ConfigV1_1_20_2 {
read_config_from_toml_file(path)
}
#[allow(dead_code)]
pub fn read_from_default_path<P: AsRef<Path>>(id: P) -> io::Result<Self> {
Self::read_from_toml_file(default_config_filepath(id))
}
@@ -54,6 +54,7 @@ impl ConfigV1_1_33 {
read_config_from_toml_file(path)
}
#[allow(dead_code)]
pub fn read_from_default_path<P: AsRef<Path>>(id: P) -> io::Result<Self> {
Self::read_from_toml_file(default_config_filepath(id))
}