diff options
author | Rina Fujino <18257209+rina23q@users.noreply.github.com> | 2022-04-25 14:08:55 +0200 |
---|---|---|
committer | Rina Fujino <18257209+rina23q@users.noreply.github.com> | 2022-04-25 14:08:55 +0200 |
commit | d5bbc2597c053d30ab2ac7bdb37ed601336a7cd2 (patch) | |
tree | 0a0f43379e9d6487a2880bb2e9e24c227433e3f5 | |
parent | dd71f3084d688459aa1a31361891fb9b3e17c234 (diff) |
Add command line options
* --config-dir for tedge.toml
* --config-file for plugin config file
Signed-off-by: Rina Fujino <18257209+rina23q@users.noreply.github.com>
-rw-r--r-- | Cargo.lock | 1 | ||||
-rw-r--r-- | plugins/c8y_configuration_plugin/Cargo.toml | 3 | ||||
-rw-r--r-- | plugins/c8y_configuration_plugin/src/config.rs | 22 | ||||
-rw-r--r-- | plugins/c8y_configuration_plugin/src/main.rs | 76 |
4 files changed, 71 insertions, 31 deletions
@@ -395,6 +395,7 @@ dependencies = [ "assert_matches", "c8y_api", "c8y_smartrest", + "clap 3.1.6", "csv", "download", "mqtt_channel", diff --git a/plugins/c8y_configuration_plugin/Cargo.toml b/plugins/c8y_configuration_plugin/Cargo.toml index 818d1b42..9554a0ca 100644 --- a/plugins/c8y_configuration_plugin/Cargo.toml +++ b/plugins/c8y_configuration_plugin/Cargo.toml @@ -5,12 +5,13 @@ authors = ["thin-edge.io team <info@thin-edge.io>"] edition = "2021" rust-version = "1.58.1" license = "Apache-2.0" -description = "Thin.edge.io operation plugin for Cumulocity configuration management request" +description = "Thin-edge device configuration management for Cumulocity" [dependencies] anyhow = "1.0" c8y_api = { path = "../../crates/core/c8y_api" } c8y_smartrest = { path = "../../crates/core/c8y_smartrest" } +clap = { version = "3.0", features = ["cargo", "derive"] } csv = "1.1" download = { path = "../../crates/common/download" } mqtt_channel = { path = "../../crates/common/mqtt_channel" } diff --git a/plugins/c8y_configuration_plugin/src/config.rs b/plugins/c8y_configuration_plugin/src/config.rs index 4c1070ed..46cb366f 100644 --- a/plugins/c8y_configuration_plugin/src/config.rs +++ b/plugins/c8y_configuration_plugin/src/config.rs @@ -1,3 +1,4 @@ +use crate::DEFAULT_PLUGIN_CONFIG_FILE_PATH; use c8y_smartrest::topic::C8yTopic; use mqtt_channel::Message; use serde::Deserialize; @@ -5,8 +6,6 @@ use std::fs; use std::path::PathBuf; use tracing::{info, warn}; -pub const PLUGIN_CONFIG_FILE: &str = "c8y-configuration-plugin.toml"; - #[derive(Deserialize, Debug, PartialEq, Default)] #[serde(deny_unknown_fields)] pub struct PluginConfig { @@ -14,14 +13,15 @@ pub struct PluginConfig { } impl PluginConfig { - pub fn new(config_root: PathBuf) -> Self { - let config_path = config_root.join(PLUGIN_CONFIG_FILE); - let config_path_str = config_path.to_str().unwrap_or(PLUGIN_CONFIG_FILE); - Self::read_config(config_path.clone()).add_file(config_path_str.into()) + pub fn new(config_file_path: PathBuf) -> Self { + let config_file_path_str = config_file_path + .to_str() + .unwrap_or(DEFAULT_PLUGIN_CONFIG_FILE_PATH); + Self::read_config(config_file_path.clone()).add_file(config_file_path_str.into()) } fn read_config(path: PathBuf) -> Self { - let path_str = path.to_str().unwrap_or(PLUGIN_CONFIG_FILE); + let path_str = path.to_str().unwrap_or(DEFAULT_PLUGIN_CONFIG_FILE_PATH); info!("Reading the config file from {}", path_str); match fs::read_to_string(path.clone()) { Ok(contents) => match toml::from_str(contents.as_str()) { @@ -71,6 +71,8 @@ mod tests { use tempfile::TempDir; use test_case::test_case; + const PLUGIN_CONFIG_FILE: &str = "c8y-configuration-plugin.toml"; + #[test] fn deserialize_plugin_config() { let config: PluginConfig = toml::from_str( @@ -142,11 +144,9 @@ mod tests { fn read_plugin_config_file(file_content: &str, raw_config: PluginConfig) -> anyhow::Result<()> { let (_dir, config_root_path) = create_temp_plugin_config(file_content)?; let tmp_path_to_plugin_config = config_root_path.join(PLUGIN_CONFIG_FILE); - let tmp_path_to_plugin_config_str = tmp_path_to_plugin_config - .to_str() - .unwrap_or(PLUGIN_CONFIG_FILE); + let tmp_path_to_plugin_config_str = tmp_path_to_plugin_config.to_str().unwrap(); - let config = PluginConfig::new(config_root_path.clone()); + let config = PluginConfig::new(tmp_path_to_plugin_config.clone()); // The expected output should contain /tmp/<random>/c8y_configuration_plugin.toml let expected_config = raw_config.add_file(tmp_path_to_plugin_config_str.into()); diff --git a/plugins/c8y_configuration_plugin/src/main.rs b/plugins/c8y_configuration_plugin/src/main.rs index e9b4649b..29e6e929 100644 --- a/plugins/c8y_configuration_plugin/src/main.rs +++ b/plugins/c8y_configuration_plugin/src/main.rs @@ -10,24 +10,55 @@ use crate::upload::handle_config_upload_request; use anyhow::Result; use c8y_api::http_proxy::{C8YHttpProxy, JwtAuthHttpProxy}; use c8y_smartrest::smartrest_deserializer::{ - SmartRestConfigDownloadRequest, SmartRestRequestGeneric, + SmartRestConfigDownloadRequest, SmartRestConfigUploadRequest, SmartRestRequestGeneric, }; -use c8y_smartrest::{smartrest_deserializer::SmartRestConfigUploadRequest, topic::C8yTopic}; +use c8y_smartrest::topic::C8yTopic; +use clap::Parser; use mqtt_channel::{SinkExt, StreamExt}; use std::path::PathBuf; -use tedge_config::{get_tedge_config, ConfigSettingAccessor, MqttPortSetting}; +use tedge_config::{ + ConfigRepository, ConfigSettingAccessor, MqttPortSetting, TEdgeConfigLocation, + DEFAULT_TEDGE_CONFIG_PATH, +}; use tracing::{debug, error}; -const CONFIG_ROOT_PATH: &str = "/etc/tedge/c8y"; - -#[cfg(not(debug_assertions))] -const LOG_LEVEL_DEBUG: bool = false; - -#[cfg(debug_assertions)] -const LOG_LEVEL_DEBUG: bool = false; +const DEFAULT_PLUGIN_CONFIG_FILE_PATH: &str = "/etc/tedge/c8y/c8y-configuration-plugin.toml"; +const AFTER_HELP_TEXT: &str = r#"On start, `c8y_configuration_plugin` notifies the cloud tenant of the managed configuration files, listed in the `CONFIG_FILE`, sending this list with a `119` on `c8y/s/us`. +`c8y_configuration_plugin` subscribes then to `c8y/s/ds` listening for configuration operation requests (messages `524` and `526`). +notifying the Cumulocity tenant of their progress (messages `501`, `502` and `503`). + +The thin-edge `CONFIG_DIR` is used to find where: + * to store temporary files on download: `tedge config get tmp.path`, + * to log operation errors and progress: `tedge config get log.path`, + * to connect the MQTT bus: `tedge config get mqtt.port`."#; + +#[derive(Debug, clap::Parser)] +#[clap( +name = clap::crate_name!(), +version = clap::crate_version!(), +about = clap::crate_description!(), +after_help = AFTER_HELP_TEXT +)] +pub struct ConfigPluginOpt { + /// Turn-on the debug log level. + /// + /// If off only reports ERROR, WARN, and INFO + /// If on also reports DEBUG and TRACE + #[clap(long)] + pub debug: bool, + + #[clap(long = "config-dir", default_value = DEFAULT_TEDGE_CONFIG_PATH)] + pub config_dir: PathBuf, + + #[clap(long = "config-file", default_value = DEFAULT_PLUGIN_CONFIG_FILE_PATH)] + pub config_file: PathBuf, +} -async fn create_mqtt_client() -> Result<mqtt_channel::Connection, anyhow::Error> { - let tedge_config = get_tedge_config()?; +async fn create_mqtt_client( + tedge_config_location: &TEdgeConfigLocation, +) -> Result<mqtt_channel::Connection, anyhow::Error> { + let config_repository = tedge_config::TEdgeConfigRepository::new(tedge_config_location.clone()); + let tedge_config = config_repository.load()?; let mqtt_port = tedge_config.query(MqttPortSetting)?.into(); let mqtt_config = mqtt_channel::Config::default() .with_port(mqtt_port) @@ -39,22 +70,29 @@ async fn create_mqtt_client() -> Result<mqtt_channel::Connection, anyhow::Error> Ok(mqtt_client) } -pub async fn create_http_client() -> Result<JwtAuthHttpProxy, anyhow::Error> { - let config = get_tedge_config()?; - let mut http_proxy = JwtAuthHttpProxy::try_new(&config).await?; +pub async fn create_http_client( + tedge_config_location: &TEdgeConfigLocation, +) -> Result<JwtAuthHttpProxy, anyhow::Error> { + let config_repository = tedge_config::TEdgeConfigRepository::new(tedge_config_location.clone()); + let tedge_config = config_repository.load()?; + let mut http_proxy = JwtAuthHttpProxy::try_new(&tedge_config).await?; let () = http_proxy.init().await?; Ok(http_proxy) } #[tokio::main] async fn main() -> Result<(), anyhow::Error> { - tedge_utils::logging::initialise_tracing_subscriber(LOG_LEVEL_DEBUG); + let config_plugin_opt = ConfigPluginOpt::parse(); + tedge_utils::logging::initialise_tracing_subscriber(config_plugin_opt.debug); + + let tedge_config_location = + tedge_config::TEdgeConfigLocation::from_custom_root(config_plugin_opt.config_dir); // Create required clients - let mut mqtt_client = create_mqtt_client().await?; - let mut http_client = create_http_client().await?; + let mut mqtt_client = create_mqtt_client(&tedge_config_location).await?; + let mut http_client = create_http_client(&tedge_config_location).await?; - let plugin_config = PluginConfig::new(PathBuf::from(CONFIG_ROOT_PATH)); + let plugin_config = PluginConfig::new(config_plugin_opt.config_file); // Publish supported configuration types let msg = plugin_config.to_message()?; |