clients: handle config upgrade failure

This commit is contained in:
Jon Häggblad
2023-09-06 09:58:24 +02:00
parent e083bfcfe4
commit 1cf2b10e31
13 changed files with 104 additions and 42 deletions
@@ -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))
}
}
+3 -3
View File
@@ -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()?;
+3 -3
View File
@@ -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,
}
})
}
}
+3
View File
@@ -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
+1 -1
View File
@@ -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))
}
}