diff options
author | Rina Fujino <18257209+rina23q@users.noreply.github.com> | 2022-04-25 16:17:54 +0200 |
---|---|---|
committer | Rina Fujino <18257209+rina23q@users.noreply.github.com> | 2022-04-25 16:17:54 +0200 |
commit | 04e2131b7d5c3e10a7c12906240043f6286714cf (patch) | |
tree | 2952108b19f83a83f82a250fe084f2f0db7b5b75 | |
parent | d5bbc2597c053d30ab2ac7bdb37ed601336a7cd2 (diff) |
Add packaging scripts
* Add --init option to deploy the operation files
* Add debian packaging information to Cargo.toml
* Add systemd service file
* Add postinst script
* Small refactoring
Signed-off-by: Rina Fujino <18257209+rina23q@users.noreply.github.com>
-rw-r--r-- | Cargo.lock | 2 | ||||
-rw-r--r-- | configuration/debian/c8y_configuration_plugin/postinst | 8 | ||||
-rw-r--r-- | configuration/init/systemd/c8y-configuration-plugin.service | 11 | ||||
-rw-r--r-- | plugins/c8y_configuration_plugin/Cargo.toml | 9 | ||||
-rw-r--r-- | plugins/c8y_configuration_plugin/src/config.rs | 16 | ||||
-rw-r--r-- | plugins/c8y_configuration_plugin/src/download.rs | 10 | ||||
-rw-r--r-- | plugins/c8y_configuration_plugin/src/main.rs | 61 |
7 files changed, 91 insertions, 26 deletions
@@ -389,7 +389,7 @@ dependencies = [ [[package]] name = "c8y_configuration_plugin" -version = "0.6.1" +version = "0.6.2" dependencies = [ "anyhow", "assert_matches", diff --git a/configuration/debian/c8y_configuration_plugin/postinst b/configuration/debian/c8y_configuration_plugin/postinst new file mode 100644 index 00000000..94e1b10e --- /dev/null +++ b/configuration/debian/c8y_configuration_plugin/postinst @@ -0,0 +1,8 @@ +#!/bin/sh + +set -e + +### Create supported operation files +c8y_configuration_plugin --init + +#DEBHELPER# diff --git a/configuration/init/systemd/c8y-configuration-plugin.service b/configuration/init/systemd/c8y-configuration-plugin.service new file mode 100644 index 00000000..356f77a1 --- /dev/null +++ b/configuration/init/systemd/c8y-configuration-plugin.service @@ -0,0 +1,11 @@ +[Unit] +Description=Thin-edge device configuration management for Cumulocity +After=syslog.target network.target mosquitto.service + +[Service] +ExecStart=/usr/bin/c8y_configuration_plugin +Restart=on-failure +RestartPreventExitStatus=255 + +[Install] +WantedBy=multi-user.target diff --git a/plugins/c8y_configuration_plugin/Cargo.toml b/plugins/c8y_configuration_plugin/Cargo.toml index 9554a0ca..c4faeb6a 100644 --- a/plugins/c8y_configuration_plugin/Cargo.toml +++ b/plugins/c8y_configuration_plugin/Cargo.toml @@ -1,12 +1,19 @@ [package] name = "c8y_configuration_plugin" -version = "0.6.1" +version = "0.6.2" authors = ["thin-edge.io team <info@thin-edge.io>"] edition = "2021" rust-version = "1.58.1" license = "Apache-2.0" description = "Thin-edge device configuration management for Cumulocity" +[package.metadata.deb] +maintainer-scripts = "../../configuration/debian/c8y_configuration_plugin" +assets = [ + ["../../configuration/init/systemd/c8y-configuration-plugin.service", "/lib/systemd/system/c8y-configuration-plugin.service", "644"], + ["target/release/c8y_configuration_plugin", "/usr/bin/c8y_configuration_plugin", "755"], +] + [dependencies] anyhow = "1.0" c8y_api = { path = "../../crates/core/c8y_api" } diff --git a/plugins/c8y_configuration_plugin/src/config.rs b/plugins/c8y_configuration_plugin/src/config.rs index 46cb366f..ae0fb1bf 100644 --- a/plugins/c8y_configuration_plugin/src/config.rs +++ b/plugins/c8y_configuration_plugin/src/config.rs @@ -1,4 +1,3 @@ -use crate::DEFAULT_PLUGIN_CONFIG_FILE_PATH; use c8y_smartrest::topic::C8yTopic; use mqtt_channel::Message; use serde::Deserialize; @@ -14,16 +13,14 @@ pub struct PluginConfig { impl PluginConfig { 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()) + let config_file_path_str = config_file_path.as_path().display().to_string(); + Self::read_config(config_file_path).add_file(config_file_path_str) } fn read_config(path: PathBuf) -> Self { - let path_str = path.to_str().unwrap_or(DEFAULT_PLUGIN_CONFIG_FILE_PATH); + let path_str = path.as_path().display().to_string(); info!("Reading the config file from {}", path_str); - match fs::read_to_string(path.clone()) { + match fs::read_to_string(path) { Ok(contents) => match toml::from_str(contents.as_str()) { Ok(config) => config, _ => { @@ -144,12 +141,13 @@ 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(); + let tmp_path_to_plugin_config_str = + tmp_path_to_plugin_config.as_path().display().to_string(); 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()); + let expected_config = raw_config.add_file(tmp_path_to_plugin_config_str); assert_eq!(config, expected_config); diff --git a/plugins/c8y_configuration_plugin/src/download.rs b/plugins/c8y_configuration_plugin/src/download.rs index c6838ad8..d85c163f 100644 --- a/plugins/c8y_configuration_plugin/src/download.rs +++ b/plugins/c8y_configuration_plugin/src/download.rs @@ -16,13 +16,14 @@ use serde_json::json; use std::fs; use std::os::unix::fs::PermissionsExt; use std::path::{Path, PathBuf}; -use tedge_config::{get_tedge_config, ConfigSettingAccessor, TmpPathDefaultSetting}; +use tedge_config::{ConfigSettingAccessor, TEdgeConfig, TmpPathDefaultSetting}; const BROADCASTING_TOPIC: &str = "filemanagement/changes"; pub async fn handle_config_download_request( plugin_config: &PluginConfig, smartrest_request: SmartRestConfigDownloadRequest, + tedge_config: &TEdgeConfig, mqtt_client: &mut Connection, http_client: &mut JwtAuthHttpProxy, ) -> Result<(), anyhow::Error> { @@ -32,7 +33,7 @@ pub async fn handle_config_download_request( // Add validation if the config_type exists in let changed_file = smartrest_request.config_type.clone(); - match download_config_file(plugin_config, smartrest_request, http_client).await { + match download_config_file(plugin_config, smartrest_request, tedge_config, http_client).await { Ok(_) => { let successful_message = GetDownloadConfigFileMessage::successful(None)?; let () = mqtt_client.published.send(successful_message).await?; @@ -52,11 +53,12 @@ pub async fn handle_config_download_request( async fn download_config_file( plugin_config: &PluginConfig, smartrest_request: SmartRestConfigDownloadRequest, + tedge_config: &TEdgeConfig, http_client: &mut JwtAuthHttpProxy, ) -> Result<(), anyhow::Error> { // Convert smartrest request to config download request struct let mut config_download_request = - ConfigDownloadRequest::try_new(smartrest_request, plugin_config)?; + ConfigDownloadRequest::try_new(smartrest_request, plugin_config, tedge_config)?; // Confirm that the file has write access before any http request attempt let () = config_download_request.has_write_access()?; @@ -91,6 +93,7 @@ impl ConfigDownloadRequest { fn try_new( request: SmartRestConfigDownloadRequest, plugin_config: &PluginConfig, + tedge_config: &TEdgeConfig, ) -> Result<Self, ConfigDownloadError> { // Check if the requested config type is in the plugin config list if !plugin_config.files.contains(&request.config_type) { @@ -100,7 +103,6 @@ impl ConfigDownloadRequest { } let destination_path = PathBuf::from(request.config_type); - let tedge_config = get_tedge_config()?; let tmp_dir = tedge_config.query(TmpPathDefaultSetting)?.into(); let file_name = Self::get_filename(destination_path.clone())?; diff --git a/plugins/c8y_configuration_plugin/src/main.rs b/plugins/c8y_configuration_plugin/src/main.rs index 29e6e929..5dc667bc 100644 --- a/plugins/c8y_configuration_plugin/src/main.rs +++ b/plugins/c8y_configuration_plugin/src/main.rs @@ -17,10 +17,11 @@ use clap::Parser; use mqtt_channel::{SinkExt, StreamExt}; use std::path::PathBuf; use tedge_config::{ - ConfigRepository, ConfigSettingAccessor, MqttPortSetting, TEdgeConfigLocation, + ConfigRepository, ConfigSettingAccessor, MqttPortSetting, TEdgeConfig, DEFAULT_TEDGE_CONFIG_PATH, }; -use tracing::{debug, error}; +use tedge_utils::file::{create_directory_with_user_group, create_file_with_user_group}; +use tracing::{debug, error, info}; 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`. @@ -47,6 +48,10 @@ pub struct ConfigPluginOpt { #[clap(long)] pub debug: bool, + /// Create supported operation files + #[clap(short, long)] + pub init: bool, + #[clap(long = "config-dir", default_value = DEFAULT_TEDGE_CONFIG_PATH)] pub config_dir: PathBuf, @@ -55,10 +60,8 @@ pub struct ConfigPluginOpt { } async fn create_mqtt_client( - tedge_config_location: &TEdgeConfigLocation, + tedge_config: &TEdgeConfig, ) -> 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) @@ -71,11 +74,9 @@ async fn create_mqtt_client( } pub async fn create_http_client( - tedge_config_location: &TEdgeConfigLocation, + tedge_config: &TEdgeConfig, ) -> 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 mut http_proxy = JwtAuthHttpProxy::try_new(tedge_config).await?; let () = http_proxy.init().await?; Ok(http_proxy) } @@ -85,12 +86,20 @@ async fn main() -> Result<(), anyhow::Error> { let config_plugin_opt = ConfigPluginOpt::parse(); tedge_utils::logging::initialise_tracing_subscriber(config_plugin_opt.debug); + if config_plugin_opt.init { + init(config_plugin_opt.config_dir)?; + return Ok(()); + } + + // Load tedge config from the provided location let tedge_config_location = tedge_config::TEdgeConfigLocation::from_custom_root(config_plugin_opt.config_dir); + let config_repository = tedge_config::TEdgeConfigRepository::new(tedge_config_location.clone()); + let tedge_config = config_repository.load()?; // Create required clients - let mut mqtt_client = create_mqtt_client(&tedge_config_location).await?; - let mut http_client = create_http_client(&tedge_config_location).await?; + let mut mqtt_client = create_mqtt_client(&tedge_config).await?; + let mut http_client = create_http_client(&tedge_config).await?; let plugin_config = PluginConfig::new(config_plugin_opt.config_file); @@ -110,6 +119,7 @@ async fn main() -> Result<(), anyhow::Error> { handle_config_download_request( &plugin_config, config_download_request, + &tedge_config, &mut mqtt_client, &mut http_client, ) @@ -144,3 +154,32 @@ async fn main() -> Result<(), anyhow::Error> { Ok(()) } + +fn init(cfg_dir: PathBuf) -> Result<(), anyhow::Error> { + info!("Creating supported operation files"); + let config_dir = cfg_dir.as_path().display().to_string(); + let () = create_operation_files(config_dir.as_str())?; + Ok(()) +} + +fn create_operation_files(config_dir: &str) -> Result<(), anyhow::Error> { + create_directory_with_user_group( + &format!("{config_dir}/operations/c8y"), + "tedge", + "tedge", + 0o775, + )?; + create_file_with_user_group( + &format!("{config_dir}/operations/c8y/c8y_UploadConfigFile"), + "tedge", + "tedge", + 0o644, + )?; + create_file_with_user_group( + &format!("{config_dir}/operations/c8y/c8y_DownloadConfigFile"), + "tedge", + "tedge", + 0o644, + )?; + Ok(()) +} |