summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRina Fujino <18257209+rina23q@users.noreply.github.com>2022-04-25 16:17:54 +0200
committerRina Fujino <18257209+rina23q@users.noreply.github.com>2022-04-25 16:17:54 +0200
commit04e2131b7d5c3e10a7c12906240043f6286714cf (patch)
tree2952108b19f83a83f82a250fe084f2f0db7b5b75
parentd5bbc2597c053d30ab2ac7bdb37ed601336a7cd2 (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.lock2
-rw-r--r--configuration/debian/c8y_configuration_plugin/postinst8
-rw-r--r--configuration/init/systemd/c8y-configuration-plugin.service11
-rw-r--r--plugins/c8y_configuration_plugin/Cargo.toml9
-rw-r--r--plugins/c8y_configuration_plugin/src/config.rs16
-rw-r--r--plugins/c8y_configuration_plugin/src/download.rs10
-rw-r--r--plugins/c8y_configuration_plugin/src/main.rs61
7 files changed, 91 insertions, 26 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 6391babe..db7cfa9d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -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(())
+}