diff options
author | Lukasz Woznicki <75632179+makr11st@users.noreply.github.com> | 2021-11-24 20:54:56 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-24 20:54:56 +0000 |
commit | a4ffeccf60090e4456755bc53a6e3b8c8038e855 (patch) | |
tree | 9583f187114913a92866571920dd3bb205bd50a3 /tedge_config | |
parent | 8217e80670e76dbf9168780f5e0545355a39f8f3 (diff) |
Restructure directories of the workspace (#559)
* Restructure directories of the workspace
* Rename c8y_translator_lib to c8y_translator
* Update comment on how to get dummy plugin path
Signed-off-by: Lukasz Woznicki <lukasz.woznicki@softwareag.com>
Diffstat (limited to 'tedge_config')
-rw-r--r-- | tedge_config/Cargo.toml | 18 | ||||
-rw-r--r-- | tedge_config/src/config_setting.rs | 75 | ||||
-rw-r--r-- | tedge_config/src/error.rs | 20 | ||||
-rw-r--r-- | tedge_config/src/lib.rs | 15 | ||||
-rw-r--r-- | tedge_config/src/models/connect_url.rs | 86 | ||||
-rw-r--r-- | tedge_config/src/models/file_path.rs | 46 | ||||
-rw-r--r-- | tedge_config/src/models/flag.rs | 89 | ||||
-rw-r--r-- | tedge_config/src/models/mod.rs | 5 | ||||
-rw-r--r-- | tedge_config/src/models/port.rs | 56 | ||||
-rw-r--r-- | tedge_config/src/settings.rs | 264 | ||||
-rw-r--r-- | tedge_config/src/tedge_config.rs | 455 | ||||
-rw-r--r-- | tedge_config/src/tedge_config_defaults.rs | 84 | ||||
-rw-r--r-- | tedge_config/src/tedge_config_dto.rs | 90 | ||||
-rw-r--r-- | tedge_config/src/tedge_config_location.rs | 108 | ||||
-rw-r--r-- | tedge_config/src/tedge_config_repository.rs | 103 | ||||
-rw-r--r-- | tedge_config/tests/test_tedge_config.rs | 867 |
16 files changed, 0 insertions, 2381 deletions
diff --git a/tedge_config/Cargo.toml b/tedge_config/Cargo.toml deleted file mode 100644 index b49eb292..00000000 --- a/tedge_config/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "tedge_config" -version = "0.4.3" -authors = ["thin-edge.io team <info@thin-edge.io>"] -edition = "2018" - -[dependencies] -certificate = { path = "../common/certificate" } -serde = { version = "1.0", features = ["derive"] } -tedge_utils = { path = "../common/tedge_utils" } -tempfile = "3.2" -thiserror = "1.0" -toml = "0.5" -url = "2.2" - -[dev-dependencies] -assert_matches = "1.4" -tempfile = "3.2" diff --git a/tedge_config/src/config_setting.rs b/tedge_config/src/config_setting.rs deleted file mode 100644 index aa68d66a..00000000 --- a/tedge_config/src/config_setting.rs +++ /dev/null @@ -1,75 +0,0 @@ -pub trait ConfigSetting { - /// This is something like `device.id`. - const KEY: &'static str; - - const DESCRIPTION: &'static str; - - /// The underlying value type of the configuration setting. - type Value; -} - -pub trait ConfigSettingAccessor<T: ConfigSetting> { - /// Read a configuration setting - fn query(&self, setting: T) -> ConfigSettingResult<T::Value>; - - fn query_optional(&self, setting: T) -> ConfigSettingResult<Option<T::Value>> { - match self.query(setting) { - Ok(value) => Ok(Some(value)), - Err(ConfigSettingError::ConfigNotSet { .. }) => Ok(None), - Err(err) => Err(err), - } - } - - /// Update a configuration setting - fn update(&mut self, _setting: T, _value: T::Value) -> ConfigSettingResult<()>; - - /// Unset a configuration setting / reset to default - fn unset(&mut self, _setting: T) -> ConfigSettingResult<()>; -} - -/// Extension trait that provides methods to query a setting as a String or -/// update a setting provided a String value. -pub trait ConfigSettingAccessorStringExt<T: ConfigSetting>: ConfigSettingAccessor<T> { - /// Read a configuration setting and convert it into a String. - fn query_string(&self, setting: T) -> ConfigSettingResult<String>; - - fn query_string_optional(&self, setting: T) -> ConfigSettingResult<Option<String>> { - match self.query_string(setting) { - Ok(value) => Ok(Some(value)), - Err(ConfigSettingError::ConfigNotSet { .. }) => Ok(None), - Err(err) => Err(err), - } - } - - /// Update a configuration setting from a String value - fn update_string(&mut self, setting: T, value: String) -> ConfigSettingResult<()>; -} - -pub type ConfigSettingResult<T> = Result<T, ConfigSettingError>; - -#[derive(thiserror::Error, Debug)] -pub enum ConfigSettingError { - #[error( - r#"A value for `{key}` is missing. - A value can be set with `tedge config set {key} <value>`"# - )] - ConfigNotSet { key: &'static str }, - - #[error("Readonly setting: {message}")] - ReadonlySetting { message: &'static str }, - - #[error("Conversion from String failed")] - ConversionFromStringFailed, - - #[error("Conversion into String failed")] - ConversionIntoStringFailed, - - #[error("Derivation for `{key}` failed: {cause}")] - DerivationFailed { key: &'static str, cause: String }, - - #[error("Config value {key}, cannot be configured: {message} ")] - SettingIsNotConfigurable { - key: &'static str, - message: &'static str, - }, -} diff --git a/tedge_config/src/error.rs b/tedge_config/src/error.rs deleted file mode 100644 index f1e23642..00000000 --- a/tedge_config/src/error.rs +++ /dev/null @@ -1,20 +0,0 @@ -#[derive(thiserror::Error, Debug)] -pub enum TEdgeConfigError { - #[error("TOML parse error")] - FromTOMLParse(#[from] toml::de::Error), - - #[error("TOML serialization error")] - FromInvalidTOML(#[from] toml::ser::Error), - - #[error("I/O error")] - FromIo(#[from] std::io::Error), - - #[error(transparent)] - FromConfigSetting(#[from] crate::ConfigSettingError), - - #[error(transparent)] - FromInvalidConfigUrl(#[from] crate::models::InvalidConnectUrl), - - #[error("Config file not found: {0}")] - ConfigFileNotFound(std::path::PathBuf), -} diff --git a/tedge_config/src/lib.rs b/tedge_config/src/lib.rs deleted file mode 100644 index 2efe321c..00000000 --- a/tedge_config/src/lib.rs +++ /dev/null @@ -1,15 +0,0 @@ -mod config_setting; -mod error; -mod models; -mod settings; -mod tedge_config; -mod tedge_config_defaults; -mod tedge_config_dto; -mod tedge_config_location; -mod tedge_config_repository; - -use self::tedge_config_dto::*; -pub use self::{config_setting::*, error::*, models::*, settings::*}; -pub use self::{ - tedge_config::*, tedge_config_defaults::*, tedge_config_location::*, tedge_config_repository::*, -}; diff --git a/tedge_config/src/models/connect_url.rs b/tedge_config/src/models/connect_url.rs deleted file mode 100644 index 79f15629..00000000 --- a/tedge_config/src/models/connect_url.rs +++ /dev/null @@ -1,86 +0,0 @@ -use std::convert::TryFrom; -use url::Host; - -#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Eq, PartialEq)] -#[serde(try_from = "String", into = "String")] -pub struct ConnectUrl { - input: String, - host: Host, -} - -#[derive(thiserror::Error, Debug)] -#[error( - "Provided URL: '{input}' contains scheme or port. - Provided URL should contain only domain, eg: 'subdomain.cumulocity.com'." -)] -pub struct InvalidConnectUrl { - input: String, - error: url::ParseError, -} - -impl TryFrom<String> for ConnectUrl { - type Error = InvalidConnectUrl; - - fn try_from(input: String) -> Result<Self, Self::Error> { - match Host::parse(&input) { - Ok(host) => Ok(Self { input, host }), - Err(error) => Err(InvalidConnectUrl { input, error }), - } - } -} - -impl TryFrom<&str> for ConnectUrl { - type Error = InvalidConnectUrl; - - fn try_from(input: &str) -> Result<Self, Self::Error> { - ConnectUrl::try_from(input.to_string()) - } -} - -impl ConnectUrl { - pub fn as_str(&self) -> &str { - self.input.as_str() - } -} - -impl From<ConnectUrl> for String { - fn from(val: ConnectUrl) -> Self { - val.input - } -} - -impl From<ConnectUrl> for Host { - fn from(val: ConnectUrl) -> Self { - val.host - } -} - -#[test] -fn connect_url_from_string_should_return_err_provided_address_with_port() { - let input = "test.address.com:8883"; - - assert!(ConnectUrl::try_from(input).is_err()); -} - -#[test] -fn connect_url_from_string_should_return_err_provided_address_with_scheme_http() { - let input = "http://test.address.com"; - - assert!(ConnectUrl::try_from(input).is_err()); -} - -#[test] -fn connect_url_from_string_should_return_err_provided_address_with_port_and_http() { - let input = "http://test.address.com:8883"; - - assert!(ConnectUrl::try_from(input).is_err()); -} - -#[test] -fn connect_url_from_string_should_return_string() -> Result<(), crate::TEdgeConfigError> { - let input = "test.address.com"; - let expected = "test.address.com"; - - assert_eq!(&ConnectUrl::try_from(input)?.as_str(), &expected); - Ok(()) -} diff --git a/tedge_config/src/models/file_path.rs b/tedge_config/src/models/file_path.rs deleted file mode 100644 index 29f8a415..00000000 --- a/tedge_config/src/models/file_path.rs +++ /dev/null @@ -1,46 +0,0 @@ -use std::convert::TryInto; -use std::path::{Path, PathBuf}; - -/// Represents a path to a file or directory. -/// -/// We need this newtype in order to implement `TryInto<String>`. -/// `PathBuf` does not implement `TryInto<String>`. -#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Eq, PartialEq)] -#[serde(transparent)] -pub struct FilePath(PathBuf); - -#[derive(thiserror::Error, Debug)] -#[error("FilePath to String conversion failed: {0:?}")] -pub struct FilePathToStringConversionFailure(std::ffi::OsString); - -impl<T> From<T> for FilePath -where - PathBuf: From<T>, -{ - fn from(input: T) -> Self { - Self(PathBuf::from(input)) - } -} - -impl TryInto<String> for FilePath { - type Error = FilePathToStringConversionFailure; - - fn try_into(self) -> Result<String, FilePathToStringConversionFailure> { - self.0 - .into_os_string() - .into_string() - .map_err(FilePathToStringConversionFailure) - } -} - -impl AsRef<Path> for FilePath { - fn as_ref(&self) -> &Path { - self.0.as_ref() - } -} - -impl std::fmt::Display for FilePath { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.0.display()) - } -} diff --git a/tedge_config/src/models/flag.rs b/tedge_config/src/models/flag.rs deleted file mode 100644 index 3144a677..00000000 --- a/tedge_config/src/models/flag.rs +++ /dev/null @@ -1,89 +0,0 @@ -use std::convert::TryFrom; - -/// Represents a boolean type. -/// -/// We need this newtype in order to implement `TryFrom<String>` and `TryInto<String>`. -/// The `config_key!` macro uses query_string() and update_string(). -/// Therefore, boolean needs to be converted from/to String. -#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Eq, PartialEq)] -#[serde(transparent)] -pub struct Flag(pub bool); - -#[derive(thiserror::Error, Debug)] -#[error("Failed to parse flag: {input}. Supported values are: true, false")] -pub struct InvalidFlag { - input: String, -} - -impl TryFrom<String> for Flag { - type Error = InvalidFlag; - - fn try_from(input: String) -> Result<Self, Self::Error> { - match input.as_str() { - "true" => Ok(Flag(true)), - "false" => Ok(Flag(false)), - _ => Err(InvalidFlag { input }), - } - } -} - -impl From<Flag> for bool { - fn from(value: Flag) -> Self { - value.0 - } -} - -impl From<Flag> for String { - fn from(value: Flag) -> Self { - match value { - Flag(true) => "true".to_string(), - Flag(false) => "false".to_string(), - } - } -} - -impl Flag { - pub fn is_set(&self) -> bool { - self.0 - } -} - -#[cfg(test)] -mod tests { - use super::*; - use std::convert::TryInto; - - #[test] - fn convert_string_true_to_bool_true() { - let input = "true".to_string(); - let output: bool = Flag::try_from(input).unwrap().into(); - assert!(output); - } - - #[test] - fn convert_string_false_to_bool_false() { - let input = "false".to_string(); - let output: bool = Flag::try_from(input).unwrap().into(); - assert!(!output); - } - - #[test] - fn return_error_for_unexpected_string_input() { - let input = "unknown".to_string(); - assert!(Flag::try_from(input).is_err()); - } - - #[test] - fn convert_bool_true_to_string_true() { - let input = true; - let output: String = Flag::try_into(Flag(input)).unwrap(); - assert_eq!(output, "true"); - } - - #[test] - fn convert_bool_false_to_string_false() { - let input = false; - let output: String = Flag::try_into(Flag(input)).unwrap(); - assert_eq!(output, "false"); - } -} diff --git a/tedge_config/src/models/mod.rs b/tedge_config/src/models/mod.rs deleted file mode 100644 index e74f756c..00000000 --- a/tedge_config/src/models/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod connect_url; -pub mod file_path; -pub mod flag; -pub mod port; -pub use self::{connect_url::*, file_path::*, flag::*, port::*}; diff --git a/tedge_config/src/models/port.rs b/tedge_config/src/models/port.rs deleted file mode 100644 index cb7e1c70..00000000 --- a/tedge_config/src/models/port.rs +++ /dev/null @@ -1,56 +0,0 @@ -use std::convert::{TryFrom, TryInto}; - -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub struct Port(pub u16); - -#[derive(thiserror::Error, Debug)] -#[error("Invalid port number: '{input}'.")] -pub struct InvalidPortNumber { - input: String, -} - -impl TryFrom<String> for Port { - type Error = InvalidPortNumber; - - fn try_from(input: String) -> Result<Self, Self::Error> { - input - .as_str() - .parse::<u16>() - .map_err(|_| InvalidPortNumber { input }) - .map(Port) - } -} - -impl TryInto<String> for Port { - type Error = std::convert::Infallible; - - fn try_into(self) -> Result<String, Self::Error> { - Ok(format!("{}", self.0)) - } -} - -impl From<Port> for u16 { - fn from(val: Port) -> Self { - val.0 - } -} - -#[cfg(test)] -use assert_matches::*; -#[test] -fn conversion_from_valid_port_succeeds() { - assert_matches!(Port::try_from("1234".to_string()), Ok(Port(1234))); -} - -#[test] -fn conversion_from_longer_integer_fails() { - assert_matches!( - Port::try_from("66000".to_string()), - Err(InvalidPortNumber { .. }) - ); -} - -#[test] -fn conversion_from_port_to_string() { - assert_matches!(TryInto::<String>::try_into(Port(1234)), Ok(port_str) if port_str == "1234"); -} diff --git a/tedge_config/src/settings.rs b/tedge_config/src/settings.rs deleted file mode 100644 index b1a312e2..00000000 --- a/tedge_config/src/settings.rs +++ /dev/null @@ -1,264 +0,0 @@ -use crate::{config_setting::*, models::*}; - -/// -/// Identifier of the device within the fleet. It must be globally -/// unique and the same one used in the device certificate. -/// NOTE: This setting is derived from the device certificate and therefore is read only. -/// -/// Example: Raspberrypi-4d18303a-6d3a-11eb-b1a6-175f6bb72665") -/// -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub struct DeviceIdSetting; - -impl ConfigSetting for DeviceIdSetting { - const KEY: &'static str = "device.id"; - - const DESCRIPTION: &'static str = concat!( - "Identifier of the device within the fleet. It must be ", - "globally unique and is derived from the device certificate. ", - "Example: Raspberrypi-4d18303a-6d3a-11eb-b1a6-175f6bb72665", - "NOTE: This setting is derived from the device certificate and therefore is read only." - ); - - type Value = String; -} - -/// -/// Path to the private key file. Example: /home/user/.tedge/tedge-private-key.pem -/// -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub struct DeviceKeyPathSetting; - -impl ConfigSetting for DeviceKeyPathSetting { - const KEY: &'static str = "device.key.path"; - - const DESCRIPTION: &'static str = - "Path to the private key file. Example: /home/user/.tedge/tedge-private-key.pem"; - - type Value = FilePath; -} - -/// -/// Path to the certificate file. -/// -/// Example: /home/user/.tedge/tedge-certificate.crt -/// -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub struct DeviceCertPathSetting; - -impl ConfigSetting for DeviceCertPathSetting { - const KEY: &'static str = "device.cert.path"; - - const DESCRIPTION: &'static str = - "Path to the certificate file. Example: /home/user/.tedge/tedge-certificate.crt"; - - type Value = FilePath; -} - -/// -/// Tenant endpoint URL of Cumulocity tenant. -/// -/// Example: your-tenant.cumulocity.com -/// -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub struct C8yUrlSetting; - -impl ConfigSetting for C8yUrlSetting { - const KEY: &'static str = "c8y.url"; - - const DESCRIPTION: &'static str = - "Tenant endpoint URL of Cumulocity tenant. Example: your-tenant.cumulocity.com"; - type Value = ConnectUrl; -} - -/// -/// Path where Cumulocity root certificate(s) are located. -/// -/// Example: /home/user/.tedge/c8y-trusted-root-certificates.pem -/// -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub struct C8yRootCertPathSetting; - -impl ConfigSetting for C8yRootCertPathSetting { - const KEY: &'static str = "c8y.root.cert.path"; - - const DESCRIPTION: &'static str = concat!( - "Path where Cumulocity root certificate(s) are located. ", - "Example: /home/user/.tedge/c8y-trusted-root-certificates.pem" - ); - - type Value = FilePath; -} - -/// -/// Tenant endpoint URL of Azure IoT tenant. -/// -/// Example: MyAzure.azure-devices.net -/// -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub struct AzureUrlSetting; - -impl ConfigSetting for AzureUrlSetting { - const KEY: &'static str = "az.url"; - - const DESCRIPTION: &'static str = concat!( - "Tenant endpoint URL of Azure IoT tenant. ", - "Example: MyAzure.azure-devices.net" - ); - - type Value = ConnectUrl; -} - -/// -/// Path where Azure IoT root certificate(s) are located. -/// -/// Example: /home/user/.tedge/azure-trusted-root-certificates.pem -/// -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub struct AzureRootCertPathSetting; - -impl ConfigSetting for AzureRootCertPathSetting { - const KEY: &'static str = "az.root.cert.path"; - - const DESCRIPTION: &'static str = concat!( - "Path where Azure IoT root certificate(s) are located. ", - "Example: /home/user/.tedge/azure-trusted-root-certificates.pem" - ); - - type Value = FilePath; -} - -/// -/// Boolean whether Azure mapper should add timestamp if timestamp is not added in the incoming payload. -/// -/// Example: true -/// -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub struct AzureMapperTimestamp; - -impl ConfigSetting for AzureMapperTimestamp { - const KEY: &'static str = "az.mapper.timestamp"; - - const DESCRIPTION: &'static str = concat!( - "Boolean whether Azure mapper should add timestamp or not. ", - "Example: true" - ); - - type Value = Flag; -} - -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub struct MqttPortSetting; - -impl ConfigSetting for MqttPortSetting { - const KEY: &'static str = "mqtt.port"; - - const DESCRIPTION: &'static str = concat!( - "Mqtt broker port, which is used by the local mqtt clients to publish or subscribe. ", - "Example: 1883" - ); - - type Value = Port; -} - -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub struct MqttExternalPortSetting; - -impl ConfigSetting for MqttExternalPortSetting { - const KEY: &'static str = "mqtt.external.port"; - - const DESCRIPTION: &'static str = concat!( - "Mqtt broker port, which is used by the external mqtt clients to publish or subscribe. ", - "Example: 8883" - ); - - type Value = Port; -} - -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub struct MqttExternalBindAddressSetting; - -impl ConfigSetting for MqttExternalBindAddressSetting { - const KEY: &'static str = "mqtt.external.bind_address"; - - const DESCRIPTION: &'static str = concat!( - "IP address / hostname, which the mqtt broker limits incoming connections on. ", - "Example: 0.0.0.0" - ); - - type Value = String; -} - -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub struct MqttExternalBindInterfaceSetting; - -impl ConfigSetting for MqttExternalBindInterfaceSetting { - const KEY: &'static str = "mqtt.external.bind_interface"; - - const DESCRIPTION: &'static str = concat!( - "Name of network interface, which the mqtt broker limits incoming connections on. ", - "Example: wlan0" - ); - - type Value = String; -} - -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub struct MqttExternalCAPathSetting; - -impl ConfigSetting for MqttExternalCAPathSetting { - const KEY: &'static str = "mqtt.external.capath"; - - const DESCRIPTION: &'static str = concat!( - "Path to a file containing the PEM encoded CA certificates ", - "that are trusted when checking incoming client certificates. ", - "Example: /etc/ssl/certs", - "Note: If the capath is not set, then no certificates are required for the external connections." - ); - - type Value = FilePath; -} - -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub struct MqttExternalCertfileSetting; - -impl ConfigSetting for MqttExternalCertfileSetting { - const KEY: &'static str = "mqtt.external.certfile"; - - const DESCRIPTION: &'static str = concat!( - "Path to the certificate file, which is used by external MQTT listener", - "Example: /etc/tedge/device-certs/tedge-certificate.pem", - "Note: This setting shall be used together with `mqtt.external.keyfile` for external connections." - ); - - type Value = FilePath; -} - -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub struct MqttExternalKeyfileSetting; - -impl ConfigSetting for MqttExternalKeyfileSetting { - const KEY: &'static str = "mqtt.external.keyfile"; - - const DESCRIPTION: &'static str = concat!( - "Path to the private key file, which is used by external MQTT listener", - "Example: /etc/tedge/device-certs/tedge-private-key.pem", - "Note: This setting shall be used together with `mqtt.external.certfile` for external connections." - ); - - type Value = FilePath; -} - -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub struct SoftwarePluginDefaultSetting; - -impl ConfigSetting for SoftwarePluginDefaultSetting { - const KEY: &'static str = "software.plugin.default"; - - const DESCRIPTION: &'static str = concat!( - "The default software plugin to be used for software management on the device", - "Example: apt" - ); - - type Value = String; -} diff --git a/tedge_config/src/tedge_config.rs b/tedge_config/src/tedge_config.rs deleted file mode 100644 index b4e88ce9..00000000 --- a/tedge_config/src/tedge_config.rs +++ /dev/null @@ -1,455 +0,0 @@ -use crate::*; -use certificate::{CertificateError, PemCertificate}; -use std::convert::{TryFrom, TryInto}; - -/// Represents the complete configuration of a thin edge device. -/// This configuration is a wrapper over the device specific configurations -/// as well as the IoT cloud provider specific configurations. -/// -#[derive(Debug)] -pub struct TEdgeConfig { - pub(crate) data: TEdgeConfigDto, - pub(crate) config_location: TEdgeConfigLocation, - pub(crate) config_defaults: TEdgeConfigDefaults, -} - -impl ConfigSettingAccessor<DeviceIdSetting> for TEdgeConfig { - fn query(&self, _setting: DeviceIdSetting) -> ConfigSettingResult<String> { - let cert_path = self.query(DeviceCertPathSetting)?; - let pem = PemCertificate::from_pem_file(cert_path) - .map_err(|err| cert_error_into_config_error(DeviceIdSetting::KEY, err))?; - let device_id = pem - .subject_common_name() - .map_err(|err| cert_error_into_config_error(DeviceIdSetting::KEY, err))?; - Ok(device_id) - } - - fn update(&mut self, _setting: DeviceIdSetting, _value: String) -> ConfigSettingResult<()> { - Err(device_id_read_only_error()) - } - - fn unset(&mut self, _setting: DeviceIdSetting) -> ConfigSettingResult<()> { - Err(device_id_read_only_error()) - } -} - -fn device_id_read_only_error() -> ConfigSettingError { - ConfigSettingError::ReadonlySetting { - message: concat!( - "The device id is read from the device certificate and cannot be set directly.\n", - "To set 'device.id' to some <id>, you can use `tedge cert create --device-id <id>`.", - ), - } -} - -fn cert_error_into_config_error(key: &'static str, err: CertificateError) -> ConfigSettingError { - match &err { - CertificateError::IoError(io_err) => match io_err.kind() { - std::io::ErrorKind::NotFound => ConfigSettingError::SettingIsNotConfigurable { key, - message: concat!( - "The device id is read from the device certificate.\n", - "To set 'device.id' to some <id>, you can use `tedge cert create --device-id <id>`.", - ), - }, - _ => ConfigSettingError::DerivationFailed { - key, - cause: format!("{}", err), - }, - }, - _ => ConfigSettingError::DerivationFailed { - key, - cause: format!("{}", err), - }, - } -} - -impl ConfigSettingAccessor<AzureUrlSetting> for TEdgeConfig { - fn query(&self, _setting: AzureUrlSetting) -> ConfigSettingResult<ConnectUrl> { - self.data - .az - .url - .clone() - .ok_or(ConfigSettingError::ConfigNotSet { - key: AzureUrlSetting::KEY, - }) - } - - fn update(&mut self, _setting: AzureUrlSetting, value: ConnectUrl) -> ConfigSettingResult<()> { - self.data.az.url = Some(value); - Ok(()) - } - - fn unset(&mut self, _setting: AzureUrlSetting) -> ConfigSettingResult<()> { - self.data.az.url = None; - Ok(()) - } -} - -impl ConfigSettingAccessor<C8yUrlSetting> for TEdgeConfig { - fn query(&self, _setting: C8yUrlSetting) -> ConfigSettingResult<ConnectUrl> { - self.data - .c8y - .url - .clone() - .ok_or(ConfigSettingError::ConfigNotSet { - key: C8yUrlSetting::KEY, - }) - } - - fn update(&mut self, _setting: C8yUrlSetting, value: ConnectUrl) -> ConfigSettingResult<()> { - self.data.c8y.url = Some(value); - Ok(()) - } - - fn unset(&mut self, _setting: C8yUrlSetting) -> ConfigSettingResult<()> { - self.data.c8y.url = None; - Ok(()) - } -} - -impl ConfigSettingAccessor<DeviceCertPathSetting> for TEdgeConfig { - fn query(&self, _setting: DeviceCertPathSetting) -> ConfigSettingResult<FilePath> { - Ok(self - .data - .device - .cert_path - .clone() - .unwrap_or_else(|| self.config_defaults.default_device_cert_path.clone())) - } - - fn update( - &mut self, - _setting: DeviceCertPathSetting, - value: FilePath, - ) -> ConfigSettingResult<()> { - self.data.device.cert_path = Some(value); - Ok(()) - } - - fn unset(&mut self, _setting: DeviceCertPathSetting) -> ConfigSettingResult<()> { - self.data.device.cert_path = None; - Ok(()) - } -} - -impl ConfigSettingAccessor<DeviceKeyPathSetting> for TEdgeConfig { - fn query(&self, _setting |