summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLukasz Woznicki <75632179+makr11st@users.noreply.github.com>2022-05-17 13:30:05 +0100
committerGitHub <noreply@github.com>2022-05-17 13:30:05 +0100
commit2a8d917cbb377395cfeb4abcf34580541df80ace (patch)
treebc4ac1d65d227e30abe914cdb349af715edaf38d
parentba49c8bdd3ca4e7ad5249a89ac90d2aad9479dfb (diff)
parentf71bb3194f045110d1b5c41491caae5536a73e50 (diff)
Merge pull request #1142 from makr11st/feature/1051_smartrest_templates
[1051] Add support for smartrest templates to config
-rw-r--r--crates/common/tedge_config/src/models/mod.rs4
-rw-r--r--crates/common/tedge_config/src/models/templates_set.rs57
-rw-r--r--crates/common/tedge_config/src/settings.rs19
-rw-r--r--crates/common/tedge_config/src/tedge_config.rs26
-rw-r--r--crates/common/tedge_config/src/tedge_config_dto.rs3
-rw-r--r--crates/core/tedge/src/cli/config/config_key.rs1
-rw-r--r--crates/core/tedge/src/cli/connect/bridge_config_c8y.rs90
-rw-r--r--crates/core/tedge/src/cli/connect/command.rs1
8 files changed, 169 insertions, 32 deletions
diff --git a/crates/common/tedge_config/src/models/mod.rs b/crates/common/tedge_config/src/models/mod.rs
index 4044168d..37871da7 100644
--- a/crates/common/tedge_config/src/models/mod.rs
+++ b/crates/common/tedge_config/src/models/mod.rs
@@ -3,4 +3,6 @@ pub mod file_path;
pub mod flag;
pub mod ipaddress;
pub mod port;
-pub use self::{connect_url::*, file_path::*, flag::*, ipaddress::*, port::*};
+pub mod templates_set;
+
+pub use self::{connect_url::*, file_path::*, flag::*, ipaddress::*, port::*, templates_set::*};
diff --git a/crates/common/tedge_config/src/models/templates_set.rs b/crates/common/tedge_config/src/models/templates_set.rs
new file mode 100644
index 00000000..da9d32f6
--- /dev/null
+++ b/crates/common/tedge_config/src/models/templates_set.rs
@@ -0,0 +1,57 @@
+use std::convert::TryInto;
+
+/// Represents a set of smartrest templates.
+///
+/// New type to add conversion methods and deduplicate provided templates.
+#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Eq, PartialEq)]
+#[serde(transparent)]
+pub struct TemplatesSet(pub Vec<String>);
+
+#[derive(thiserror::Error, Debug)]
+#[error("TemplateSet to String conversion failed: {0:?}")]
+pub struct TemplatesSetToStringConversionFailure(String);
+
+impl TryFrom<Vec<String>> for TemplatesSet {
+ type Error = TemplatesSetToStringConversionFailure;
+
+ fn try_from(value: Vec<String>) -> Result<Self, Self::Error> {
+ Ok(TemplatesSet(value))
+ }
+}
+
+impl TryFrom<Vec<&str>> for TemplatesSet {
+ type Error = TemplatesSetToStringConversionFailure;
+
+ fn try_from(value: Vec<&str>) -> Result<Self, Self::Error> {
+ Ok(TemplatesSet(
+ value.into_iter().map(|s| s.into()).collect::<Vec<String>>(),
+ ))
+ }
+}
+
+impl TryInto<Vec<String>> for TemplatesSet {
+ type Error = TemplatesSetToStringConversionFailure;
+
+ fn try_into(self) -> Result<Vec<String>, TemplatesSetToStringConversionFailure> {
+ Ok(self.0)
+ }
+}
+
+impl From<TemplatesSet> for String {
+ fn from(val: TemplatesSet) -> Self {
+ val.to_string()
+ }
+}
+
+impl From<String> for TemplatesSet {
+ fn from(val: String) -> Self {
+ let strings = val.split(',').map(|ss| ss.into()).collect();
+ TemplatesSet(strings)
+ }
+}
+
+impl std::fmt::Display for TemplatesSet {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(f, "{:?}", self.0)
+ }
+}
diff --git a/crates/common/tedge_config/src/settings.rs b/crates/common/tedge_config/src/settings.rs
index fb018408..bca85b1a 100644
--- a/crates/common/tedge_config/src/settings.rs
+++ b/crates/common/tedge_config/src/settings.rs
@@ -102,6 +102,25 @@ impl ConfigSetting for C8yRootCertPathSetting {
}
///
+/// Smartrest templates to subsribe to.
+///
+/// Example: template1,template2
+///
+#[derive(Debug)]
+pub struct C8ySmartRestTemplates;
+
+impl ConfigSetting for C8ySmartRestTemplates {
+ const KEY: &'static str = "c8y.smartrest.templates";
+
+ const DESCRIPTION: &'static str = concat!(
+ "Set of SmartRest templates for the device ",
+ "Example: template1,template2"
+ );
+
+ type Value = TemplatesSet;
+}
+
+///
/// Tenant endpoint URL of Azure IoT tenant.
///
/// Example: MyAzure.azure-devices.net
diff --git a/crates/common/tedge_config/src/tedge_config.rs b/crates/common/tedge_config/src/tedge_config.rs
index f37ea0e3..9952b2d1 100644
--- a/crates/common/tedge_config/src/tedge_config.rs
+++ b/crates/common/tedge_config/src/tedge_config.rs
@@ -138,6 +138,32 @@ impl ConfigSettingAccessor<C8yUrlSetting> for TEdgeConfig {
}
}
+impl ConfigSettingAccessor<C8ySmartRestTemplates> for TEdgeConfig {
+ fn query(&self, _setting: C8ySmartRestTemplates) -> ConfigSettingResult<TemplatesSet> {
+ self.data
+ .c8y
+ .smartrest_templates
+ .clone()
+ .ok_or(ConfigSettingError::ConfigNotSet {
+ key: C8ySmartRestTemplates::KEY,
+ })
+ }
+
+ fn update(
+ &mut self,
+ _setting: C8ySmartRestTemplates,
+ value: TemplatesSet,
+ ) -> ConfigSettingResult<()> {
+ self.data.c8y.smartrest_templates = Some(value);
+ Ok(())
+ }
+
+ fn unset(&mut self, _setting: C8ySmartRestTemplates) -> ConfigSettingResult<()> {
+ self.data.c8y.smartrest_templates = None;
+ Ok(())
+ }
+}
+
impl ConfigSettingAccessor<DeviceCertPathSetting> for TEdgeConfig {
fn query(&self, _setting: DeviceCertPathSetting) -> ConfigSettingResult<FilePath> {
Ok(self
diff --git a/crates/common/tedge_config/src/tedge_config_dto.rs b/crates/common/tedge_config/src/tedge_config_dto.rs
index 28cbfcbd..75b576b6 100644
--- a/crates/common/tedge_config/src/tedge_config_dto.rs
+++ b/crates/common/tedge_config/src/tedge_config_dto.rs
@@ -72,6 +72,9 @@ pub(crate) struct CumulocityConfigDto {
/// Boolean whether Azure mapper adds timestamp or not.
pub(crate) mapper_timestamp: Option<bool>,
+
+ /// Set of c8y templates used for subscriptions.
+ pub(crate) smartrest_templates: Option<TemplatesSet>,
}
#[derive(Debug, Default, Deserialize, Serialize)]
diff --git a/crates/core/tedge/src/cli/config/config_key.rs b/crates/core/tedge/src/cli/config/config_key.rs
index 96227269..161f0e4c 100644
--- a/crates/core/tedge/src/cli/config/config_key.rs
+++ b/crates/core/tedge/src/cli/config/config_key.rs
@@ -45,6 +45,7 @@ impl ConfigKey {
config_key!(DeviceCertPathSetting),
config_key!(C8yUrlSetting),
config_key!(C8yRootCertPathSetting),
+ config_key!(C8ySmartRestTemplates),
config_key!(AzureUrlSetting),
config_key!(AzureRootCertPathSetting),
config_key!(AzureMapperTimestamp),
diff --git a/crates/core/tedge/src/cli/connect/bridge_config_c8y.rs b/crates/core/tedge/src/cli/connect/bridge_config_c8y.rs
index 90fdab7e..31330598 100644
--- a/crates/core/tedge/src/cli/connect/bridge_config_c8y.rs
+++ b/crates/core/tedge/src/cli/connect/bridge_config_c8y.rs
@@ -1,5 +1,5 @@
use crate::cli::connect::BridgeConfig;
-use tedge_config::{ConnectUrl, FilePath};
+use tedge_config::{ConnectUrl, FilePath, TemplatesSet};
#[derive(Debug, PartialEq)]
pub struct BridgeConfigC8yParams {
@@ -10,6 +10,7 @@ pub struct BridgeConfigC8yParams {
pub bridge_root_cert_path: FilePath,
pub bridge_certfile: FilePath,
pub bridge_keyfile: FilePath,
+ pub smartrest_templates: TemplatesSet,
}
impl From<BridgeConfigC8yParams> for BridgeConfig {
@@ -22,9 +23,57 @@ impl From<BridgeConfigC8yParams> for BridgeConfig {
remote_clientid,
bridge_certfile,
bridge_keyfile,
+ smartrest_templates,
} = params;
let address = format!("{}:{}", connect_url.as_str(), mqtt_tls_port);
+ let mut topics: Vec<String> = vec![
+ // Registration
+ r#"s/dcr in 2 c8y/ """#.into(),
+ r#"s/ucr out 2 c8y/ """#.into(),
+ // Templates
+ r#"s/dt in 2 c8y/ """#.into(),
+ r#"s/ut/# out 2 c8y/ """#.into(),
+ // Static templates
+ r#"s/us/# out 2 c8y/ """#.into(),
+ r#"t/us/# out 2 c8y/ """#.into(),
+ r#"q/us/# out 2 c8y/ """#.into(),
+ r#"c/us/# out 2 c8y/ """#.into(),
+ r#"s/ds in 2 c8y/ """#.into(),
+ // Debug
+ r#"s/e in 0 c8y/ """#.into(),
+ // SmartRest2
+ r#"s/uc/# out 2 c8y/ """#.into(),
+ r#"t/uc/# out 2 c8y/ """#.into(),
+ r#"q/uc/# out 2 c8y/ """#.into(),
+ r#"c/uc/# out 2 c8y/ """#.into(),
+ r#"s/dc/# in 2 c8y/ """#.into(),
+ // c8y JSON
+ r#"inventory/managedObjects/update/# out 2 c8y/ """#.into(),
+ r#"measurement/measurements/create out 2 c8y/ """#.into(),
+ r#"event/events/create out 2 c8y/ """#.into(),
+ r#"error in 2 c8y/ """#.into(),
+ // c8y JWT token retrieval
+ r#"s/uat/# out 2 c8y/ """#.into(),
+ r#"s/dat/# in 2 c8y/ """#.into(),
+ ];
+
+ let templates_set = smartrest_templates
+ .0
+ .iter()
+ .flat_map(|s| {
+ // Smartrest templates should be deserialized as:
+ // c8y/s/uc/template-1 (in from localhost), s/uc/template-1
+ // c8y/s/dc/template-1 (out to localhost), s/dc/template-1
+ [
+ format!(r#"s/uc/{s} out 2 c8y/ """#),
+ format!(r#"s/dc/{s} in 2 c8y/ """#),
+ ]
+ .into_iter()
+ })
+ .collect::<Vec<String>>();
+ topics.extend(templates_set);
+
Self {
cloud_name: "c8y".into(),
config_file,
@@ -45,36 +94,7 @@ impl From<BridgeConfigC8yParams> for BridgeConfig {
notifications_local_only: true,
notification_topic: "tedge/health/mosquitto-c8y-bridge".into(),
bridge_attempt_unsubscribe: false,
- topics: vec![
- // Registration
- r#"s/dcr in 2 c8y/ """#.into(),
- r#"s/ucr out 2 c8y/ """#.into(),
- // Templates
- r#"s/dt in 2 c8y/ """#.into(),
- r#"s/ut/# out 2 c8y/ """#.into(),
- // Static templates
- r#"s/us/# out 2 c8y/ """#.into(),
- r#"t/us/# out 2 c8y/ """#.into(),
- r#"q/us/# out 2 c8y/ """#.into(),
- r#"c/us/# out 2 c8y/ """#.into(),
- r#"s/ds in 2 c8y/ """#.into(),
- // Debug
- r#"s/e in 0 c8y/ """#.into(),
- // SmartRest2
- r#"s/uc/# out 2 c8y/ """#.into(),
- r#"t/uc/# out 2 c8y/ """#.into(),
- r#"q/uc/# out 2 c8y/ """#.into(),
- r#"c/uc/# out 2 c8y/ """#.into(),
- r#"s/dc/# in 2 c8y/ """#.into(),
- // c8y JSON
- r#"inventory/managedObjects/update/# out 2 c8y/ """#.into(),
- r#"measurement/measurements/create out 2 c8y/ """#.into(),
- r#"event/events/create out 2 c8y/ """#.into(),
- r#"error in 2 c8y/ """#.into(),
- // c8y JWT token retrieval
- r#"s/uat/# out 2 c8y/ """#.into(),
- r#"s/dat/# in 2 c8y/ """#.into(),
- ],
+ topics,
}
}
}
@@ -90,6 +110,7 @@ fn test_bridge_config_from_c8y_params() -> anyhow::Result<()> {
bridge_root_cert_path: "./test_root.pem".into(),
bridge_certfile: "./test-certificate.pem".into(),
bridge_keyfile: "./test-private-key.pem".into(),
+ smartrest_templates: TemplatesSet::try_from(vec!["abc", "def"])?,
};
let bridge = BridgeConfig::from(params);
@@ -136,6 +157,13 @@ fn test_bridge_config_from_c8y_params() -> anyhow::Result<()> {
// c8y JWT token retrieval
r#"s/uat/# out 2 c8y/ """#.into(),
r#"s/dat/# in 2 c8y/ """#.into(),
+ // Smartrest templates should be deserialized as:
+ // s/uc/template-1 (in from localhost), s/uc/template-1
+ // s/dc/template-1 (out to localhost), s/dc/template-1
+ r#"s/uc/abc out 2 c8y/ """#.into(),
+ r#"s/dc/abc in 2 c8y/ """#.into(),
+ r#"s/uc/def out 2 c8y/ """#.into(),
+ r#"s/dc/def in 2 c8y/ """#.into(),
],
try_private: false,
start_type: "automatic".into(),
diff --git a/crates/core/tedge/src/cli/connect/command.rs b/crates/core/tedge/src/cli/connect/command.rs
index 30682ddd..7da926d0 100644
--- a/crates/core/tedge/src/cli/connect/command.rs
+++ b/crates/core/tedge/src/cli/connect/command.rs
@@ -203,6 +203,7 @@ impl ConnectCommand {
remote_clientid: config.query(DeviceIdSetting)?,
bridge_certfile: config.query(DeviceCertPathSetting)?,
bridge_keyfile: config.query(DeviceKeyPathSetting)?,
+ smartrest_templates: config.query(C8ySmartRestTemplates)?,
};
Ok(BridgeConfig::from(params))