clients: handle config upgrade failure
This commit is contained in:
@@ -1,8 +1,13 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::client::config::persistence::ClientPaths;
|
||||
use crate::client::config::{default_config_filepath, Config, Socket, SocketType};
|
||||
use crate::{
|
||||
client::config::{
|
||||
default_config_filepath, persistence::ClientPaths, Config, Socket, SocketType,
|
||||
},
|
||||
error::ClientError,
|
||||
};
|
||||
|
||||
use nym_bin_common::logging::LoggingSettings;
|
||||
use nym_client_core::config::disk_persistence::old_v1_1_20_2::CommonClientPathsV1_1_20_2;
|
||||
use nym_client_core::config::old_config_v1_1_20_2::ConfigV1_1_20_2 as BaseConfigV1_1_20_2;
|
||||
@@ -43,18 +48,18 @@ impl ConfigV1_1_20_2 {
|
||||
|
||||
// in this upgrade, gateway endpoint configuration was moved out of the config file,
|
||||
// so its returned to be stored elsewhere.
|
||||
pub fn upgrade(self) -> (Config, GatewayEndpointConfig) {
|
||||
pub fn upgrade(self) -> Result<(Config, GatewayEndpointConfig), ClientError> {
|
||||
let gateway_details = self.base.client.gateway_endpoint.clone().into();
|
||||
let config = Config {
|
||||
base: self.base.into(),
|
||||
socket: self.socket.into(),
|
||||
storage_paths: ClientPaths {
|
||||
common_paths: self.storage_paths.common_paths.upgrade_default(),
|
||||
common_paths: self.storage_paths.common_paths.upgrade_default()?,
|
||||
},
|
||||
logging: self.logging,
|
||||
};
|
||||
|
||||
(config, gateway_details)
|
||||
Ok((config, gateway_details))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -157,7 +157,7 @@ fn try_upgrade_v1_1_13_config(id: &str) -> Result<bool, ClientError> {
|
||||
|
||||
let updated_step1: ConfigV1_1_20 = old_config.into();
|
||||
let updated_step2: ConfigV1_1_20_2 = updated_step1.into();
|
||||
let (updated, gateway_config) = updated_step2.upgrade();
|
||||
let (updated, gateway_config) = updated_step2.upgrade()?;
|
||||
persist_gateway_details(&updated, gateway_config)?;
|
||||
|
||||
updated.save_to_default_location()?;
|
||||
@@ -177,7 +177,7 @@ fn try_upgrade_v1_1_20_config(id: &str) -> Result<bool, ClientError> {
|
||||
info!("It is going to get updated to the current specification.");
|
||||
|
||||
let updated_step1: ConfigV1_1_20_2 = old_config.into();
|
||||
let (updated, gateway_config) = updated_step1.upgrade();
|
||||
let (updated, gateway_config) = updated_step1.upgrade()?;
|
||||
persist_gateway_details(&updated, gateway_config)?;
|
||||
|
||||
updated.save_to_default_location()?;
|
||||
@@ -194,7 +194,7 @@ fn try_upgrade_v1_1_20_2_config(id: &str) -> Result<bool, ClientError> {
|
||||
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, gateway_config) = old_config.upgrade();
|
||||
let (updated, gateway_config) = old_config.upgrade()?;
|
||||
persist_gateway_details(&updated, gateway_config)?;
|
||||
|
||||
updated.save_to_default_location()?;
|
||||
|
||||
@@ -199,7 +199,7 @@ fn try_upgrade_v1_1_13_config(id: &str) -> Result<bool, Socks5ClientError> {
|
||||
|
||||
let updated_step1: ConfigV1_1_20 = old_config.into();
|
||||
let updated_step2: ConfigV1_1_20_2 = updated_step1.into();
|
||||
let (updated, gateway_config) = updated_step2.upgrade();
|
||||
let (updated, gateway_config) = updated_step2.upgrade()?;
|
||||
persist_gateway_details(&updated, gateway_config)?;
|
||||
|
||||
updated.save_to_default_location()?;
|
||||
@@ -219,7 +219,7 @@ fn try_upgrade_v1_1_20_config(id: &str) -> Result<bool, Socks5ClientError> {
|
||||
info!("It is going to get updated to the current specification.");
|
||||
|
||||
let updated_step1: ConfigV1_1_20_2 = old_config.into();
|
||||
let (updated, gateway_config) = updated_step1.upgrade();
|
||||
let (updated, gateway_config) = updated_step1.upgrade()?;
|
||||
persist_gateway_details(&updated, gateway_config)?;
|
||||
|
||||
updated.save_to_default_location()?;
|
||||
@@ -236,7 +236,7 @@ fn try_upgrade_v1_1_20_2_config(id: &str) -> Result<bool, Socks5ClientError> {
|
||||
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, gateway_config) = old_config.upgrade();
|
||||
let (updated, gateway_config) = old_config.upgrade()?;
|
||||
persist_gateway_details(&updated, gateway_config)?;
|
||||
|
||||
updated.save_to_default_location()?;
|
||||
|
||||
@@ -1,17 +1,21 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::config::persistence::SocksClientPaths;
|
||||
use crate::config::{default_config_filepath, Config};
|
||||
use crate::{
|
||||
config::{default_config_filepath, persistence::SocksClientPaths, Config},
|
||||
error::Socks5ClientError,
|
||||
};
|
||||
|
||||
use nym_bin_common::logging::LoggingSettings;
|
||||
use nym_client_core::config::disk_persistence::old_v1_1_20_2::CommonClientPathsV1_1_20_2;
|
||||
use nym_client_core::config::GatewayEndpointConfig;
|
||||
use nym_config::read_config_from_toml_file;
|
||||
pub use nym_socks5_client_core::config::old_config_v1_1_20_2::ConfigV1_1_20_2 as CoreConfigV1_1_20_2;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::io;
|
||||
use std::path::Path;
|
||||
|
||||
pub use nym_socks5_client_core::config::old_config_v1_1_20_2::ConfigV1_1_20_2 as CoreConfigV1_1_20_2;
|
||||
|
||||
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone)]
|
||||
pub struct SocksClientPathsV1_1_20_2 {
|
||||
#[serde(flatten)]
|
||||
@@ -39,16 +43,16 @@ impl ConfigV1_1_20_2 {
|
||||
|
||||
// in this upgrade, gateway endpoint configuration was moved out of the config file,
|
||||
// so its returned to be stored elsewhere.
|
||||
pub fn upgrade(self) -> (Config, GatewayEndpointConfig) {
|
||||
pub fn upgrade(self) -> Result<(Config, GatewayEndpointConfig), Socks5ClientError> {
|
||||
let gateway_details = self.core.base.client.gateway_endpoint.clone().into();
|
||||
let config = Config {
|
||||
core: self.core.into(),
|
||||
storage_paths: SocksClientPaths {
|
||||
common_paths: self.storage_paths.common_paths.upgrade_default(),
|
||||
common_paths: self.storage_paths.common_paths.upgrade_default()?,
|
||||
},
|
||||
logging: self.logging,
|
||||
};
|
||||
|
||||
(config, gateway_details)
|
||||
Ok((config, gateway_details))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
use crate::config::disk_persistence::keys_paths::ClientKeysPaths;
|
||||
use crate::config::disk_persistence::{CommonClientPaths, DEFAULT_GATEWAY_DETAILS_FILENAME};
|
||||
use crate::error::ClientCoreError;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::PathBuf;
|
||||
|
||||
@@ -15,16 +16,17 @@ pub struct CommonClientPathsV1_1_20_2 {
|
||||
}
|
||||
|
||||
impl CommonClientPathsV1_1_20_2 {
|
||||
pub fn upgrade_default(self) -> CommonClientPaths {
|
||||
let data_dir = self
|
||||
.reply_surb_database
|
||||
.parent()
|
||||
.expect("client paths upgrade failure");
|
||||
CommonClientPaths {
|
||||
pub fn upgrade_default(self) -> Result<CommonClientPaths, ClientCoreError> {
|
||||
let data_dir = self.reply_surb_database.parent().ok_or_else(|| {
|
||||
ClientCoreError::UnableToUpgradeConfigFile {
|
||||
new_version: "1.1.20-2".to_string(),
|
||||
}
|
||||
})?;
|
||||
Ok(CommonClientPaths {
|
||||
keys: self.keys,
|
||||
gateway_details: data_dir.join(DEFAULT_GATEWAY_DETAILS_FILENAME),
|
||||
credentials_database: self.credentials_database,
|
||||
reply_surb_database: self.reply_surb_database,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,6 +119,9 @@ pub enum ClientCoreError {
|
||||
|
||||
#[error("the provided gateway details (for gateway {gateway_id}) do not correspond to the shared keys")]
|
||||
MismatchedGatewayDetails { gateway_id: String },
|
||||
|
||||
#[error("unable to upgrade config file to `{new_version}`")]
|
||||
UnableToUpgradeConfigFile { new_version: String },
|
||||
}
|
||||
|
||||
/// Set of messages that the client can send to listeners via the task manager
|
||||
|
||||
Generated
+1
-1
@@ -3992,7 +3992,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nym-connect"
|
||||
version = "1.1.19"
|
||||
version = "1.1.20"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bip39",
|
||||
|
||||
@@ -137,6 +137,20 @@ fn init_paths(id: &str) -> io::Result<()> {
|
||||
fs::create_dir_all(default_config_directory(id))
|
||||
}
|
||||
|
||||
fn try_extract_version_for_upgrade_failure(err: BackendError) -> Option<String> {
|
||||
if let BackendError::ClientCoreError { source } = err {
|
||||
if let nym_client_core::error::ClientCoreError::UnableToUpgradeConfigFile { new_version } =
|
||||
source
|
||||
{
|
||||
Some(new_version)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn init_socks5_config(provider_address: String, chosen_gateway_id: String) -> Result<()> {
|
||||
log::trace!("Initialising client...");
|
||||
|
||||
@@ -145,10 +159,29 @@ pub async fn init_socks5_config(provider_address: String, chosen_gateway_id: Str
|
||||
let _validated = identity::PublicKey::from_base58_string(&chosen_gateway_id)
|
||||
.map_err(|_| BackendError::UnableToParseGateway)?;
|
||||
|
||||
let already_init = if default_config_filepath(&id).exists() {
|
||||
let config_path = default_config_filepath(&id);
|
||||
let already_init = if config_path.exists() {
|
||||
// in case we're using old config, try to upgrade it
|
||||
// (if we're using the current version, it's a no-op)
|
||||
try_upgrade_config(&id)?;
|
||||
if let Err(err) = try_upgrade_config(&id) {
|
||||
log::error!(
|
||||
"Failed to upgrade config file {}: {:?}",
|
||||
config_path.display(),
|
||||
err
|
||||
);
|
||||
if let Some(failed_at_version) = try_extract_version_for_upgrade_failure(err) {
|
||||
return Err(
|
||||
BackendError::CouldNotUpgradeExistingConfigurationFileAtVersion {
|
||||
file: config_path,
|
||||
failed_at_version,
|
||||
},
|
||||
);
|
||||
} else {
|
||||
return Err(BackendError::CouldNotUpgradeExistingConfigurationFile {
|
||||
file: config_path,
|
||||
});
|
||||
}
|
||||
};
|
||||
eprintln!("SOCKS5 client \"{id}\" was already initialised before");
|
||||
true
|
||||
} else {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
use crate::config::persistence::NymConnectPaths;
|
||||
use crate::config::{default_config_filepath, Config};
|
||||
use crate::error::Result;
|
||||
use nym_bin_common::logging::LoggingSettings;
|
||||
use nym_client_core::config::disk_persistence::old_v1_1_20_2::CommonClientPathsV1_1_20_2;
|
||||
use nym_client_core::config::GatewayEndpointConfig;
|
||||
@@ -39,16 +40,16 @@ impl ConfigV1_1_20_2 {
|
||||
|
||||
// in this upgrade, gateway endpoint configuration was moved out of the config file,
|
||||
// so its returned to be stored elsewhere.
|
||||
pub fn upgrade(self) -> (Config, GatewayEndpointConfig) {
|
||||
pub fn upgrade(self) -> Result<(Config, GatewayEndpointConfig)> {
|
||||
let gateway_details = self.core.base.client.gateway_endpoint.clone().into();
|
||||
let config = Config {
|
||||
core: self.core.into(),
|
||||
storage_paths: NymConnectPaths {
|
||||
common_paths: self.storage_paths.common_paths.upgrade_default(),
|
||||
common_paths: self.storage_paths.common_paths.upgrade_default()?,
|
||||
},
|
||||
// logging: self.logging,
|
||||
};
|
||||
|
||||
(config, gateway_details)
|
||||
Ok((config, gateway_details))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ use crate::{
|
||||
},
|
||||
error::{BackendError, Result},
|
||||
};
|
||||
use log::info;
|
||||
use log::{debug, info};
|
||||
use nym_client_core::{
|
||||
client::{
|
||||
base_client::storage::gateway_details::{OnDiskGatewayDetails, PersistedGatewayDetails},
|
||||
@@ -52,7 +52,7 @@ fn try_upgrade_v1_1_13_config(id: &str) -> Result<bool> {
|
||||
|
||||
let updated_step1: ConfigV1_1_20 = old_config.into();
|
||||
let updated_step2: ConfigV1_1_20_2 = updated_step1.into();
|
||||
let (updated, gateway_config) = updated_step2.upgrade();
|
||||
let (updated, gateway_config) = updated_step2.upgrade()?;
|
||||
persist_gateway_details(&updated, gateway_config)?;
|
||||
|
||||
updated.save_to_default_location()?;
|
||||
@@ -72,7 +72,7 @@ fn try_upgrade_v1_1_20_config(id: &str) -> Result<bool> {
|
||||
info!("It is going to get updated to the current specification.");
|
||||
|
||||
let updated_step1: ConfigV1_1_20_2 = old_config.into();
|
||||
let (updated, gateway_config) = updated_step1.upgrade();
|
||||
let (updated, gateway_config) = updated_step1.upgrade()?;
|
||||
persist_gateway_details(&updated, gateway_config)?;
|
||||
|
||||
updated.save_to_default_location()?;
|
||||
@@ -89,7 +89,7 @@ fn try_upgrade_v1_1_20_2_config(id: &str) -> Result<bool> {
|
||||
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, gateway_config) = old_config.upgrade();
|
||||
let (updated, gateway_config) = old_config.upgrade()?;
|
||||
persist_gateway_details(&updated, gateway_config)?;
|
||||
|
||||
updated.save_to_default_location()?;
|
||||
@@ -97,6 +97,7 @@ fn try_upgrade_v1_1_20_2_config(id: &str) -> Result<bool> {
|
||||
}
|
||||
|
||||
pub fn try_upgrade_config(id: &str) -> Result<()> {
|
||||
debug!("Attempting to upgrade config file for \"{id}\"");
|
||||
if try_upgrade_v1_1_13_config(id)? {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@@ -81,6 +81,13 @@ pub enum BackendError {
|
||||
CouldNotGetConfigFilename,
|
||||
#[error("could not load existing gateway configuration")]
|
||||
CouldNotLoadExistingGatewayConfiguration(std::io::Error),
|
||||
#[error("could not upgrade `{file}` to latest version")]
|
||||
CouldNotUpgradeExistingConfigurationFile { file: std::path::PathBuf },
|
||||
#[error("could not upgrade `{file}` to latest version (failed at {failed_at_version})")]
|
||||
CouldNotUpgradeExistingConfigurationFileAtVersion {
|
||||
file: std::path::PathBuf,
|
||||
failed_at_version: String,
|
||||
},
|
||||
|
||||
#[error("no gateways found in directory")]
|
||||
NoGatewaysFoundInDirectory,
|
||||
|
||||
@@ -179,7 +179,7 @@ fn try_upgrade_v1_1_13_config(id: &str) -> Result<bool, NetworkRequesterError> {
|
||||
|
||||
let updated_step1: ConfigV1_1_20 = old_config.into();
|
||||
let updated_step2: ConfigV1_1_20_2 = updated_step1.into();
|
||||
let (updated, gateway_config) = updated_step2.upgrade();
|
||||
let (updated, gateway_config) = updated_step2.upgrade()?;
|
||||
persist_gateway_details(&updated, gateway_config)?;
|
||||
|
||||
updated.save_to_default_location()?;
|
||||
@@ -201,7 +201,7 @@ fn try_upgrade_v1_1_20_config(id: &str) -> Result<bool, NetworkRequesterError> {
|
||||
info!("It is going to get updated to the current specification.");
|
||||
|
||||
let updated_step1: ConfigV1_1_20_2 = old_config.into();
|
||||
let (updated, gateway_config) = updated_step1.upgrade();
|
||||
let (updated, gateway_config) = updated_step1.upgrade()?;
|
||||
persist_gateway_details(&updated, gateway_config)?;
|
||||
|
||||
updated.save_to_default_location()?;
|
||||
@@ -220,7 +220,7 @@ fn try_upgrade_v1_1_20_2_config(id: &str) -> Result<bool, NetworkRequesterError>
|
||||
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, gateway_config) = old_config.upgrade();
|
||||
let (updated, gateway_config) = old_config.upgrade()?;
|
||||
persist_gateway_details(&updated, gateway_config)?;
|
||||
|
||||
updated.save_to_default_location()?;
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::config::persistence::NetworkRequesterPaths;
|
||||
use crate::config::{default_config_filepath, Config, Debug, NetworkRequester};
|
||||
use crate::{
|
||||
config::{
|
||||
default_config_filepath, persistence::NetworkRequesterPaths, Config, Debug,
|
||||
NetworkRequester,
|
||||
},
|
||||
error::NetworkRequesterError,
|
||||
};
|
||||
|
||||
use log::trace;
|
||||
use nym_bin_common::logging::LoggingSettings;
|
||||
use nym_client_core::config::disk_persistence::old_v1_1_20_2::CommonClientPathsV1_1_20_2;
|
||||
@@ -58,7 +64,7 @@ impl ConfigV1_1_20_2 {
|
||||
|
||||
// in this upgrade, gateway endpoint configuration was moved out of the config file,
|
||||
// so its returned to be stored elsewhere.
|
||||
pub fn upgrade(self) -> (Config, GatewayEndpointConfig) {
|
||||
pub fn upgrade(self) -> Result<(Config, GatewayEndpointConfig), NetworkRequesterError> {
|
||||
trace!("Upgrading from v1.1.20_2");
|
||||
let gateway_details = self.base.client.gateway_endpoint.clone().into();
|
||||
let nr_description = self
|
||||
@@ -72,7 +78,7 @@ impl ConfigV1_1_20_2 {
|
||||
let config = Config {
|
||||
base: self.base.into(),
|
||||
storage_paths: NetworkRequesterPaths {
|
||||
common_paths: self.storage_paths.common_paths.upgrade_default(),
|
||||
common_paths: self.storage_paths.common_paths.upgrade_default()?,
|
||||
allowed_list_location: self.storage_paths.allowed_list_location,
|
||||
unknown_list_location: self.storage_paths.unknown_list_location,
|
||||
nr_description,
|
||||
@@ -82,7 +88,7 @@ impl ConfigV1_1_20_2 {
|
||||
network_requester: self.network_requester.into(),
|
||||
};
|
||||
|
||||
(config, gateway_details)
|
||||
Ok((config, gateway_details))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user