summaryrefslogtreecommitdiffstats
path: root/crates/core
diff options
context:
space:
mode:
Diffstat (limited to 'crates/core')
-rw-r--r--crates/core/c8y_api/Cargo.toml1
-rw-r--r--crates/core/c8y_api/src/http_proxy.rs6
-rw-r--r--crates/core/c8y_smartrest/src/event.rs42
-rw-r--r--crates/core/c8y_smartrest/src/operations.rs8
-rw-r--r--crates/core/c8y_smartrest/src/smartrest_deserializer.rs25
-rw-r--r--crates/core/c8y_smartrest/src/topic.rs2
-rw-r--r--crates/core/plugin_sm/Cargo.toml1
-rw-r--r--crates/core/plugin_sm/src/plugin_manager.rs12
-rw-r--r--crates/core/plugin_sm/tests/plugin.rs2
-rw-r--r--crates/core/tedge/Cargo.toml2
-rw-r--r--crates/core/tedge/src/cli/certificate/cli.rs10
-rw-r--r--crates/core/tedge/src/cli/certificate/upload.rs10
-rw-r--r--crates/core/tedge/src/cli/config/cli.rs7
-rw-r--r--crates/core/tedge/src/cli/connect/cli.rs7
-rw-r--r--crates/core/tedge/src/cli/connect/command.rs2
-rw-r--r--crates/core/tedge/src/cli/disconnect/cli.rs3
-rw-r--r--crates/core/tedge/src/cli/disconnect/disconnect_bridge.rs2
-rw-r--r--crates/core/tedge/src/cli/mod.rs16
-rw-r--r--crates/core/tedge/src/cli/mqtt/cli.rs11
-rw-r--r--crates/core/tedge/src/command.rs2
-rw-r--r--crates/core/tedge/src/main.rs4
-rw-r--r--crates/core/tedge/src/system_services/services.rs4
-rw-r--r--crates/core/tedge_agent/Cargo.toml2
-rw-r--r--crates/core/tedge_agent/src/main.rs14
-rw-r--r--crates/core/tedge_mapper/Cargo.toml3
-rw-r--r--crates/core/tedge_mapper/src/az/converter.rs (renamed from crates/core/tedge_mapper/src/az_converter.rs)63
-rw-r--r--crates/core/tedge_mapper/src/az/mapper.rs (renamed from crates/core/tedge_mapper/src/az_mapper.rs)9
-rw-r--r--crates/core/tedge_mapper/src/az/mod.rs2
-rw-r--r--crates/core/tedge_mapper/src/c8y/converter.rs678
-rw-r--r--crates/core/tedge_mapper/src/c8y/error.rs (renamed from crates/core/tedge_mapper/src/sm_c8y_mapper/error.rs)22
-rw-r--r--crates/core/tedge_mapper/src/c8y/fragments.rs (renamed from crates/core/tedge_mapper/src/c8y_fragments.rs)5
-rw-r--r--crates/core/tedge_mapper/src/c8y/mapper.rs93
-rw-r--r--crates/core/tedge_mapper/src/c8y/mod.rs8
-rw-r--r--crates/core/tedge_mapper/src/c8y/tests.rs781
-rw-r--r--crates/core/tedge_mapper/src/c8y/topic.rs128
-rw-r--r--crates/core/tedge_mapper/src/c8y_converter.rs624
-rw-r--r--crates/core/tedge_mapper/src/c8y_mapper.rs45
-rw-r--r--crates/core/tedge_mapper/src/collectd/batcher.rs (renamed from crates/core/tedge_mapper/src/collectd_mapper/batcher.rs)5
-rw-r--r--crates/core/tedge_mapper/src/collectd/collectd.rs (renamed from crates/core/tedge_mapper/src/collectd_mapper/collectd.rs)19
-rw-r--r--crates/core/tedge_mapper/src/collectd/error.rs (renamed from crates/core/tedge_mapper/src/collectd_mapper/error.rs)3
-rw-r--r--crates/core/tedge_mapper/src/collectd/mapper.rs (renamed from crates/core/tedge_mapper/src/collectd_mapper/mapper.rs)4
-rw-r--r--crates/core/tedge_mapper/src/collectd/mod.rs (renamed from crates/core/tedge_mapper/src/collectd_mapper/mod.rs)0
-rw-r--r--crates/core/tedge_mapper/src/collectd/monitor.rs (renamed from crates/core/tedge_mapper/src/collectd_mapper/monitor.rs)8
-rw-r--r--crates/core/tedge_mapper/src/core/component.rs (renamed from crates/core/tedge_mapper/src/component.rs)0
-rw-r--r--crates/core/tedge_mapper/src/core/converter.rs (renamed from crates/core/tedge_mapper/src/converter.rs)32
-rw-r--r--crates/core/tedge_mapper/src/core/error.rs (renamed from crates/core/tedge_mapper/src/error.rs)19
-rw-r--r--crates/core/tedge_mapper/src/core/mapper.rs (renamed from crates/core/tedge_mapper/src/mapper.rs)17
-rw-r--r--crates/core/tedge_mapper/src/core/mod.rs5
-rw-r--r--crates/core/tedge_mapper/src/core/size_threshold.rs (renamed from crates/core/tedge_mapper/src/size_threshold.rs)1
-rw-r--r--crates/core/tedge_mapper/src/main.rs58
-rw-r--r--crates/core/tedge_mapper/src/operations.rs215
-rw-r--r--crates/core/tedge_mapper/src/sm_c8y_mapper/mapper.rs425
-rw-r--r--crates/core/tedge_mapper/src/sm_c8y_mapper/mod.rs4
-rw-r--r--crates/core/tedge_mapper/src/sm_c8y_mapper/tests.rs457
-rw-r--r--crates/core/tedge_mapper/src/tests.rs233
-rw-r--r--crates/core/thin_edge_json/src/event.rs10
56 files changed, 1922 insertions, 2249 deletions
diff --git a/crates/core/c8y_api/Cargo.toml b/crates/core/c8y_api/Cargo.toml
index fe5da026..cf4a45c7 100644
--- a/crates/core/c8y_api/Cargo.toml
+++ b/crates/core/c8y_api/Cargo.toml
@@ -11,7 +11,6 @@ rust-version = "1.58.1"
agent_interface = { path = "../agent_interface"}
async-trait = "0.1"
c8y_smartrest = { path = "../c8y_smartrest" }
-chrono = "0.4"
clock = { path = "../../common/clock" }
csv = "1.1"
download = { path = "../../common/download" }
diff --git a/crates/core/c8y_api/src/http_proxy.rs b/crates/core/c8y_api/src/http_proxy.rs
index dfd3c811..9f853043 100644
--- a/crates/core/c8y_api/src/http_proxy.rs
+++ b/crates/core/c8y_api/src/http_proxy.rs
@@ -1,9 +1,9 @@
use crate::json_c8y::{
C8yCreateEvent, C8yManagedObject, C8yUpdateSoftwareListResponse, InternalIdResponse,
};
+
use async_trait::async_trait;
use c8y_smartrest::{error::SMCumulocityMapperError, smartrest_deserializer::SmartRestJwtResponse};
-use chrono::{DateTime, Local};
use mqtt_channel::{Connection, PubChannel, StreamExt, Topic, TopicFilter};
use reqwest::Url;
use std::time::Duration;
@@ -20,7 +20,7 @@ const RETRY_TIMEOUT_SECS: u64 = 60;
/// An HttpProxy handles http requests to C8y on behalf of the device.
#[async_trait]
-pub trait C8YHttpProxy {
+pub trait C8YHttpProxy: Send + Sync {
async fn init(&mut self) -> Result<(), SMCumulocityMapperError>;
fn url_is_in_my_tenant_domain(&self, url: &str) -> bool;
@@ -155,7 +155,6 @@ impl JwtAuthHttpProxy {
pub async fn try_new(
tedge_config: &TEdgeConfig,
- session_name: &str,
) -> Result<JwtAuthHttpProxy, SMCumulocityMapperError> {
let c8y_host = tedge_config.query_string(C8yUrlSetting)?;
let device_id = tedge_config.query_string(DeviceIdSetting)?;
@@ -166,7 +165,6 @@ impl JwtAuthHttpProxy {
let mqtt_config = mqtt_channel::Config::default()
.with_port(mqtt_port)
.with_clean_session(true)
- .with_session_name(session_name)
.with_subscriptions(topic);
let mut mqtt_con = Connection::new(&mqtt_config).await?;
diff --git a/crates/core/c8y_smartrest/src/event.rs b/crates/core/c8y_smartrest/src/event.rs
index ad0ee5e3..bf114dba 100644
--- a/crates/core/c8y_smartrest/src/event.rs
+++ b/crates/core/c8y_smartrest/src/event.rs
@@ -7,15 +7,19 @@ const CREATE_EVENT_SMARTREST_CODE: u16 = 400;
/// Converts from thin-edge event to C8Y event SmartREST message
pub fn serialize_event(event: ThinEdgeEvent) -> Result<String, SmartRestSerializerError> {
+ let current_timestamp = OffsetDateTime::now_utc();
match event.data {
- None => Ok(format!("{CREATE_EVENT_SMARTREST_CODE},{}", event.name)),
+ None => Ok(format!(
+ "{CREATE_EVENT_SMARTREST_CODE},{},{},{}",
+ event.name,
+ event.name,
+ current_timestamp.format(&Rfc3339)?
+ )),
Some(event_data) => {
- let current_timestamp = OffsetDateTime::now_utc();
-
let smartrest_message = format!(
"{CREATE_EVENT_SMARTREST_CODE},{},\"{}\",{}",
- event.name,
- event_data.message.unwrap_or_default(),
+ event.name.clone(),
+ event_data.message.unwrap_or(event.name),
event_data.time.map_or_else(
|| current_timestamp.format(&Rfc3339),
|timestamp| timestamp.format(&Rfc3339)
@@ -56,7 +60,7 @@ mod tests {
time: Some(datetime!(2021-04-23 19:00:00 +05:00)),
}),
},
- "400,click_event,\"\",2021-04-23T19:00:00+05:00"
+ "400,click_event,\"click_event\",2021-04-23T19:00:00+05:00"
;"event translation without message"
)]
#[test_case(
@@ -105,7 +109,31 @@ mod tests {
let smartrest_event: SmartRestEvent = result.expect("One entry expected")?;
assert_eq!(smartrest_event.code, 400);
assert_eq!(smartrest_event.name, "empty_event".to_string());
- assert_eq!(smartrest_event.message, None);
+ assert_eq!(smartrest_event.message, Some("empty_event".to_string()));
+ assert_matches!(smartrest_event.time, Some(_));
+
+ Ok(())
+ }
+
+ #[test]
+ fn event_translation_empty_payload() -> Result<()> {
+ let event = ThinEdgeEvent {
+ name: "empty_event".into(),
+ data: None,
+ };
+
+ let smartrest_message = serialize_event(event)?;
+ let mut reader = csv::ReaderBuilder::new()
+ .has_headers(false)
+ .from_reader(smartrest_message.as_bytes());
+ let mut iter = reader.deserialize();
+ let result = iter.next();
+
+ assert!(result.is_some());
+ let smartrest_event: SmartRestEvent = result.expect("One entry expected")?;
+ assert_eq!(smartrest_event.code, 400);
+ assert_eq!(smartrest_event.name, "empty_event".to_string());
+ assert_eq!(smartrest_event.message, Some("empty_event".to_string()));
assert_matches!(smartrest_event.time, Some(_));
Ok(())
diff --git a/crates/core/c8y_smartrest/src/operations.rs b/crates/core/c8y_smartrest/src/operations.rs
index b3909aac..7fec5cd7 100644
--- a/crates/core/c8y_smartrest/src/operations.rs
+++ b/crates/core/c8y_smartrest/src/operations.rs
@@ -49,14 +49,16 @@ pub struct Operations {
operations_by_trigger: HashMap<String, usize>,
}
-impl Operations {
- pub fn new() -> Self {
+impl Default for Operations {
+ fn default() -> Self {
Self {
operations: vec![],
operations_by_trigger: HashMap::new(),
}
}
+}
+impl Operations {
pub fn add(&mut self, operation: Operation) {
if let Some(detail) = operation.exec() {
if let Some(on_message) = &detail.on_message {
@@ -93,7 +95,7 @@ impl Operations {
}
fn get_operations(dir: impl AsRef<Path>, cloud_name: &str) -> Result<Operations, OperationsError> {
- let mut operations = Operations::new();
+ let mut operations = Operations::default();
let path = dir.as_ref().join(&cloud_name);
let dir_entries = fs::read_dir(&path)?
diff --git a/crates/core/c8y_smartrest/src/smartrest_deserializer.rs b/crates/core/c8y_smartrest/src/smartrest_deserializer.rs
index 37e57cb4..714a5bba 100644
--- a/crates/core/c8y_smartrest/src/smartrest_deserializer.rs
+++ b/crates/core/c8y_smartrest/src/smartrest_deserializer.rs
@@ -5,7 +5,7 @@ use download::DownloadInfo;
use serde::de::Error;
use serde::{Deserialize, Deserializer, Serialize};
use std::convert::{TryFrom, TryInto};
-use std::path::PathBuf;
+use std::path::Path;
use time::{format_description, OffsetDateTime};
#[derive(Debug)]
@@ -304,7 +304,7 @@ impl SmartRestJwtResponse {
/// let path_bufdate_time = get_datetime_from_file_path(&path).unwrap();
/// ```
pub fn get_datetime_from_file_path(
- log_path: &PathBuf,
+ log_path: &Path,
) -> Result<OffsetDateTime, SMCumulocityMapperError> {
if let Some(stem_string) = log_path.file_stem().and_then(|s| s.to_str()) {
// a typical file stem looks like this: software-list-2021-10-27T10:29:58Z.
@@ -321,8 +321,8 @@ pub fn get_datetime_from_file_path(
match log_path.to_str() {
Some(path) => Err(SMCumulocityMapperError::InvalidDateInFileName(
path.to_string(),
- ))?,
- None => Err(SMCumulocityMapperError::InvalidUtf8Path)?,
+ )),
+ None => Err(SMCumulocityMapperError::InvalidUtf8Path),
}
}
@@ -332,8 +332,7 @@ mod tests {
use agent_interface::*;
use assert_json_diff::*;
use serde_json::json;
- use std::fs::File;
- use std::io::Write;
+ use std::path::PathBuf;
use std::str::FromStr;
use test_case::test_case;
@@ -634,18 +633,4 @@ mod tests {
let path_buf_datetime = get_datetime_from_file_path(&path_buf);
assert!(path_buf_datetime.is_err());
}
-
- fn parse_file_names_from_log_content(log_content: &str) -> [&str; 5] {
- let mut files: Vec<&str> = vec![];
- for line in log_content.lines() {
- if line.contains("filename: ") {
- let filename: &str = line.split("filename: ").last().unwrap();
- files.push(filename);
- }
- }
- match files.try_into() {
- Ok(arr) => arr,
- Err(_) => panic!("Could not convert to Array &str, size 5"),
- }
- }
}
diff --git a/crates/core/c8y_smartrest/src/topic.rs b/crates/core/c8y_smartrest/src/topic.rs
index 2c6c96b0..7df4f5af 100644
--- a/crates/core/c8y_smartrest/src/topic.rs
+++ b/crates/core/c8y_smartrest/src/topic.rs
@@ -20,7 +20,7 @@ impl C8yTopic {
}
pub fn to_topic(&self) -> Result<Topic, MqttError> {
- Ok(Topic::new(self.as_str())?)
+ Topic::new(self.as_str())
}
}
diff --git a/crates/core/plugin_sm/Cargo.toml b/crates/core/plugin_sm/Cargo.toml
index 20a2fc1d..4924b113 100644
--- a/crates/core/plugin_sm/Cargo.toml
+++ b/crates/core/plugin_sm/Cargo.toml
@@ -21,7 +21,6 @@ url = "2.2"
[dev-dependencies]
anyhow = "1.0"
assert_matches = "1.5"
-structopt = "0.3"
serial_test = "0.5.1"
tempfile = "3.2"
test-case = "1.2.1"
diff --git a/crates/core/plugin_sm/src/plugin_manager.rs b/crates/core/plugin_sm/src/plugin_manager.rs
index 2cb8a3f6..0c541280 100644
--- a/crates/core/plugin_sm/src/plugin_manager.rs
+++ b/crates/core/plugin_sm/src/plugin_manager.rs
@@ -12,7 +12,6 @@ use std::{
path::PathBuf,
process::{Command, Stdio},
};
-use tedge_utils::paths::pathbuf_to_string;
use tracing::{error, info, warn};
/// The main responsibility of a `Plugins` implementation is to retrieve the appropriate plugin for a given software module.
@@ -141,17 +140,14 @@ impl ExternalPlugins {
.status()
{
Ok(code) if code.success() => {
- info!(
- "Plugin activated: {}",
- pathbuf_to_string(path.clone()).unwrap()
- );
+ info!("Plugin activated: {}", path.display());
}
// If the file is not executable or returned non 0 status code we assume it is not a valid and skip further processing.
Ok(_) => {
error!(
"File {} in plugin directory does not support list operation and may not be a valid plugin, skipping.",
- pathbuf_to_string(path.clone()).unwrap()
+ path.display()
);
continue;
}
@@ -160,7 +156,7 @@ impl ExternalPlugins {
error!(
"File {} Permission Denied, is the file an executable?\n
The file will not be registered as a plugin.",
- pathbuf_to_string(path.clone()).unwrap()
+ path.display()
);
continue;
}
@@ -169,7 +165,7 @@ impl ExternalPlugins {
error!(
"An error occurred while trying to run: {}: {}\n
The file will not be registered as a plugin.",
- pathbuf_to_string(path.clone()).unwrap(),
+ path.display(),
err
);
continue;
diff --git a/crates/core/plugin_sm/tests/plugin.rs b/crates/core/plugin_sm/tests/plugin.rs
index 5e1573b8..e9c985f2 100644
--- a/crates/core/plugin_sm/tests/plugin.rs
+++ b/crates/core/plugin_sm/tests/plugin.rs
@@ -335,7 +335,7 @@ mod tests {
.await;
// Expect Ok as plugin should exit with code 0. If Ok, there is no response to assert.
- assert_matches!(res, Err(SoftwareError::UpdateListNotSupported(_)));
+ assert!(res.is_ok());
}
// Test validating if the plugin will fall back to `install` and `remove` options if the `update-list` option is not supported
diff --git a/crates/core/tedge/Cargo.toml b/crates/core/tedge/Cargo.toml
index 2180b35c..f19a91e7 100644
--- a/crates/core/tedge/Cargo.toml
+++ b/crates/core/tedge/Cargo.toml
@@ -16,6 +16,7 @@ maintainer-scripts = "../../../configuration/debian/tedge"
anyhow = "1.0"
base64 = "0.13"
certificate = { path = "../../common/certificate" }
+clap = { version = "3", features = ["cargo", "derive"] }
futures = "0.3"
hyper = { version = "0.14", default-features = false }
reqwest = { version = "0.11", default-features = false, features = ["blocking", "json", "rustls-tls", "stream"] }
@@ -25,7 +26,6 @@ rustls = "0.20.2"
rustls_0_19 = {package = "rustls", version = "0.19.0" }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
-structopt = "0.3"
tedge_config = { path = "../../common/tedge_config" }
tedge_users = { path = "../../common/tedge_users" }
tedge_utils = { path = "../../common/tedge_utils" }
diff --git a/crates/core/tedge/src/cli/certificate/cli.rs b/crates/core/tedge/src/cli/certificate/cli.rs
index 7ef78fb5..a3e9db64 100644
--- a/crates/core/tedge/src/cli/certificate/cli.rs
+++ b/crates/core/tedge/src/cli/certificate/cli.rs
@@ -3,15 +3,14 @@ use super::{create::CreateCertCmd, remove::RemoveCertCmd, show::ShowCertCmd, upl
use crate::command::{BuildCommand, BuildContext, Command};
use crate::ConfigError;
-use structopt::StructOpt;
use tedge_config::*;
-#[derive(StructOpt, Debug)]
+#[derive(clap::Subcommand, Debug)]
pub enum TEdgeCertCli {
/// Create a self-signed device certificate
Create {
/// The device identifier to be used as the common name for the certificate
- #[structopt(long = "device-id")]
+ #[clap(long = "device-id")]
id: String,
},
@@ -22,6 +21,7 @@ pub enum TEdgeCertCli {
Remove,
/// Upload root certificate
+ #[clap(subcommand)]
Upload(UploadCertCli),
}
@@ -73,13 +73,13 @@ impl BuildCommand for TEdgeCertCli {
}
}
-#[derive(StructOpt, Debug)]
+#[derive(clap::Subcommand, Debug)]
pub enum UploadCertCli {
/// Upload root certificate to Cumulocity
///
/// The command will upload root certificate to Cumulocity.
C8y {
- #[structopt(long = "user")]
+ #[clap(long = "user")]
/// Provided username should be a Cumulocity user with tenant management permissions.
/// The password is req