Skip to content

Commit

Permalink
Add profile support to the tedge cli and fix mosquitto configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
jarhodes314 committed Nov 25, 2024
1 parent 82df8e0 commit 8f9ab76
Show file tree
Hide file tree
Showing 21 changed files with 414 additions and 406 deletions.
12 changes: 6 additions & 6 deletions crates/common/tedge_config/src/system_services/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,22 @@ pub trait SystemServiceManager: Debug {
fn check_operational(&self) -> Result<(), SystemServiceError>;

/// Stops the specified system service.
fn stop_service(&self, service: SystemService) -> Result<(), SystemServiceError>;
fn stop_service(&self, service: SystemService<'_>) -> Result<(), SystemServiceError>;

/// Starts the specified system service.
fn start_service(&self, service: SystemService) -> Result<(), SystemServiceError>;
fn start_service(&self, service: SystemService<'_>) -> Result<(), SystemServiceError>;

/// Restarts the specified system service.
fn restart_service(&self, service: SystemService) -> Result<(), SystemServiceError>;
fn restart_service(&self, service: SystemService<'_>) -> Result<(), SystemServiceError>;

/// Enables the specified system service. This does not start the service, unless you reboot.
fn enable_service(&self, service: SystemService) -> Result<(), SystemServiceError>;
fn enable_service(&self, service: SystemService<'_>) -> Result<(), SystemServiceError>;

/// Disables the specified system service. This does not stop the service.
fn disable_service(&self, service: SystemService) -> Result<(), SystemServiceError>;
fn disable_service(&self, service: SystemService<'_>) -> Result<(), SystemServiceError>;

/// Queries status of the specified system service. "Running" here means the same as "active".
fn is_service_running(&self, service: SystemService) -> Result<bool, SystemServiceError>;
fn is_service_running(&self, service: SystemService<'_>) -> Result<bool, SystemServiceError>;
}

pub fn service_manager(
Expand Down
8 changes: 4 additions & 4 deletions crates/common/tedge_config/src/system_services/manager_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@ use anyhow::Context as _;

/// Extension trait for `SystemServiceManager`.
pub trait SystemServiceManagerExt {
fn start_and_enable_service(&self, service: SystemService) -> anyhow::Result<()>;
fn stop_and_disable_service(&self, service: SystemService) -> anyhow::Result<()>;
fn start_and_enable_service(&self, service: SystemService<'_>) -> anyhow::Result<()>;
fn stop_and_disable_service(&self, service: SystemService<'_>) -> anyhow::Result<()>;
}

impl SystemServiceManagerExt for &dyn SystemServiceManager {
fn start_and_enable_service(&self, service: SystemService) -> anyhow::Result<()> {
fn start_and_enable_service(&self, service: SystemService<'_>) -> anyhow::Result<()> {
self.start_service(service)
.with_context(|| format!("Failed to start {service}"))?;
self.enable_service(service)
.with_context(|| format!("Failed to enable {service}"))
}

fn stop_and_disable_service(&self, service: SystemService) -> anyhow::Result<()> {
fn stop_and_disable_service(&self, service: SystemService<'_>) -> anyhow::Result<()> {
self.stop_service(service)
.with_context(|| format!("Failed to stop {service}"))?;
self.disable_service(service)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,37 +47,37 @@ impl SystemServiceManager for GeneralServiceManager {
}
}

fn stop_service(&self, service: SystemService) -> Result<(), SystemServiceError> {
fn stop_service(&self, service: SystemService<'_>) -> Result<(), SystemServiceError> {
let exec_command = ServiceCommand::Stop(service).try_exec_command(self)?;
self.run_service_command_as_root(exec_command, self.config_path.as_str())?
.must_succeed()
}

fn start_service(&self, service: SystemService) -> Result<(), SystemServiceError> {
fn start_service(&self, service: SystemService<'_>) -> Result<(), SystemServiceError> {
let exec_command = ServiceCommand::Start(service).try_exec_command(self)?;
self.run_service_command_as_root(exec_command, self.config_path.as_str())?
.must_succeed()
}

fn restart_service(&self, service: SystemService) -> Result<(), SystemServiceError> {
fn restart_service(&self, service: SystemService<'_>) -> Result<(), SystemServiceError> {
let exec_command = ServiceCommand::Restart(service).try_exec_command(self)?;
self.run_service_command_as_root(exec_command, self.config_path.as_str())?
.must_succeed()
}

fn enable_service(&self, service: SystemService) -> Result<(), SystemServiceError> {
fn enable_service(&self, service: SystemService<'_>) -> Result<(), SystemServiceError> {
let exec_command = ServiceCommand::Enable(service).try_exec_command(self)?;
self.run_service_command_as_root(exec_command, self.config_path.as_str())?
.must_succeed()
}

fn disable_service(&self, service: SystemService) -> Result<(), SystemServiceError> {
fn disable_service(&self, service: SystemService<'_>) -> Result<(), SystemServiceError> {
let exec_command = ServiceCommand::Disable(service).try_exec_command(self)?;
self.run_service_command_as_root(exec_command, self.config_path.as_str())?
.must_succeed()
}

fn is_service_running(&self, service: SystemService) -> Result<bool, SystemServiceError> {
fn is_service_running(&self, service: SystemService<'_>) -> Result<bool, SystemServiceError> {
let exec_command = ServiceCommand::IsActive(service).try_exec_command(self)?;
self.run_service_command_as_root(exec_command, self.config_path.as_str())
.map(|status| status.success())
Expand Down Expand Up @@ -109,11 +109,11 @@ impl ExecCommand {
}
}

fn try_new_with_placeholder(
fn try_new_with_placeholder<'a>(
config: Vec<String>,
service_cmd: ServiceCommand,
service_cmd: ServiceCommand<'a>,
config_path: Utf8PathBuf,
service: SystemService,
service: SystemService<'a>,
) -> Result<Self, SystemServiceError> {
let replaced = replace_with_service_name(&config, service_cmd, &config_path, service)?;
Self::try_new(replaced, service_cmd, config_path)
Expand Down Expand Up @@ -141,11 +141,11 @@ impl fmt::Display for ExecCommand {
}
}

fn replace_with_service_name(
fn replace_with_service_name<'a>(
input_args: &[String],
service_cmd: ServiceCommand,
service_cmd: ServiceCommand<'a>,
config_path: impl Into<Utf8PathBuf>,
service: SystemService,
service: SystemService<'a>,
) -> Result<Vec<String>, SystemServiceError> {
if !input_args.iter().any(|s| s == "{}") {
return Err(SystemServiceError::SystemConfigInvalidSyntax {
Expand All @@ -158,27 +158,27 @@ fn replace_with_service_name(
let mut args = input_args.to_owned();
for item in args.iter_mut() {
if item == "{}" {
*item = SystemService::as_service_name(service).to_string();
*item = service.to_string();
}
}

Ok(args)
}

#[derive(Debug, Copy, Clone)]
enum ServiceCommand {
enum ServiceCommand<'a> {
CheckManager,
Stop(SystemService),
Start(SystemService),
Restart(SystemService),
Enable(SystemService),
Disable(SystemService),
IsActive(SystemService),
Stop(SystemService<'a>),
Start(SystemService<'a>),
Restart(SystemService<'a>),
Enable(SystemService<'a>),
Disable(SystemService<'a>),
IsActive(SystemService<'a>),
}

impl ServiceCommand {
impl<'a> ServiceCommand<'a> {
fn try_exec_command(
&self,
self,
service_manager: &GeneralServiceManager,
) -> Result<ExecCommand, SystemServiceError> {
let config_path = service_manager.config_path.clone();
Expand All @@ -190,45 +190,45 @@ impl ServiceCommand {
),
Self::Stop(service) => ExecCommand::try_new_with_placeholder(
service_manager.init_config.stop.clone(),
ServiceCommand::Stop(*service),
ServiceCommand::Stop(service),
config_path,
*service,
service,
),
Self::Restart(service) => ExecCommand::try_new_with_placeholder(
service_manager.init_config.restart.clone(),
ServiceCommand::Restart(*service),
ServiceCommand::Restart(service),
config_path,
*service,
service,
),
Self::Start(service) => ExecCommand::try_new_with_placeholder(
service_manager.init_config.start.clone(),
ServiceCommand::Enable(*service),
ServiceCommand::Enable(service),
config_path,
*service,
service,
),
Self::Enable(service) => ExecCommand::try_new_with_placeholder(
service_manager.init_config.enable.clone(),
ServiceCommand::Enable(*service),
ServiceCommand::Enable(service),
config_path,
*service,
service,
),
Self::Disable(service) => ExecCommand::try_new_with_placeholder(
service_manager.init_config.disable.clone(),
ServiceCommand::Disable(*service),
ServiceCommand::Disable(service),
config_path,
*service,
service,
),
Self::IsActive(service) => ExecCommand::try_new_with_placeholder(
service_manager.init_config.is_active.clone(),
ServiceCommand::IsActive(*service),
ServiceCommand::IsActive(service),
config_path,
*service,
service,
),
}
}
}

impl fmt::Display for ServiceCommand {
impl<'a> fmt::Display for ServiceCommand<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::CheckManager => write!(f, "is_available"),
Expand Down
29 changes: 21 additions & 8 deletions crates/common/tedge_config/src/system_services/services.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,38 @@
use std::fmt;

use tedge_config_macros::ProfileName;

/// An enumeration of all supported system services.
#[derive(Debug, Copy, Clone, strum_macros::Display, strum_macros::IntoStaticStr)]
pub enum SystemService {
#[derive(Debug, Copy, Clone, strum_macros::IntoStaticStr)]
pub enum SystemService<'a> {
#[strum(serialize = "mosquitto")]
/// Mosquitto broker
Mosquitto,
#[strum(serialize = "tedge-mapper-az")]
/// Azure TEdge mapper
TEdgeMapperAz,
TEdgeMapperAz(Option<&'a ProfileName>),
#[strum(serialize = "tedge-mapper-aws")]
/// AWS TEdge mapper
TEdgeMapperAws,
TEdgeMapperAws(Option<&'a ProfileName>),
#[strum(serialize = "tedge-mapper-c8y")]
/// Cumulocity TEdge mapper
TEdgeMapperC8y,
TEdgeMapperC8y(Option<&'a ProfileName>),
#[strum(serialize = "tedge-agent")]
/// TEdge SM agent
TEdgeSMAgent,
}

impl SystemService {
pub(crate) fn as_service_name(service: SystemService) -> &'static str {
service.into()
impl<'a> fmt::Display for SystemService<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Mosquitto => write!(f, "mosquitto"),
Self::TEdgeMapperAz(None) => write!(f, "tedge-mapper-az"),
Self::TEdgeMapperAz(Some(profile)) => write!(f, "tedge-mapper-az@{profile}"),
Self::TEdgeMapperAws(None) => write!(f, "tedge-mapper-aws"),
Self::TEdgeMapperAws(Some(profile)) => write!(f, "tedge-mapper-aws@{profile}"),
Self::TEdgeMapperC8y(None) => write!(f, "tedge-mapper-c8y"),
Self::TEdgeMapperC8y(Some(profile)) => write!(f, "tedge-mapper-c8y@{profile}"),
Self::TEdgeSMAgent => write!(f, "tedge-agent"),
}
}
}
21 changes: 17 additions & 4 deletions crates/core/tedge/src/bridge/aws.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use super::BridgeConfig;
use crate::bridge::config::BridgeLocation;
use camino::Utf8PathBuf;
use tedge_config::ProfileName;
use std::borrow::Cow;
use tedge_config::HostPort;
use tedge_config::TopicPrefix;
Expand All @@ -18,6 +19,7 @@ pub struct BridgeConfigAwsParams {
pub bridge_keyfile: Utf8PathBuf,
pub bridge_location: BridgeLocation,
pub topic_prefix: TopicPrefix,
pub profile_name: Option<ProfileName>,
}

impl From<BridgeConfigAwsParams> for BridgeConfig {
Expand All @@ -31,6 +33,7 @@ impl From<BridgeConfigAwsParams> for BridgeConfig {
bridge_keyfile,
bridge_location,
topic_prefix,
profile_name,
} = params;

let user_name = remote_clientid.to_string();
Expand All @@ -54,13 +57,21 @@ impl From<BridgeConfigAwsParams> for BridgeConfig {
Self {
cloud_name: "aws".into(),
config_file,
connection: "edge_to_aws".into(),
connection: if let Some(profile) = &profile_name {
format!("edge_to_aws@{profile}")
} else {
"edge_to_aws".into()
},
address: mqtt_host,
remote_username: Some(user_name),
remote_password: None,
bridge_root_cert_path,
remote_clientid,
local_clientid: "Aws".into(),
local_clientid: if let Some(profile) = &profile_name {
format!("Aws@{profile}")
} else {
"Aws".into()
},
bridge_certfile,
bridge_keyfile,
use_mapper: true,
Expand Down Expand Up @@ -103,6 +114,7 @@ fn test_bridge_config_from_aws_params() -> anyhow::Result<()> {
bridge_keyfile: "./test-private-key.pem".into(),
bridge_location: BridgeLocation::Mosquitto,
topic_prefix: "aws".try_into().unwrap(),
profile_name: None,
};

let bridge = BridgeConfig::from(params);
Expand Down Expand Up @@ -159,20 +171,21 @@ fn test_bridge_config_aws_custom_topic_prefix() -> anyhow::Result<()> {
bridge_keyfile: "./test-private-key.pem".into(),
bridge_location: BridgeLocation::Mosquitto,
topic_prefix: "custom".try_into().unwrap(),
profile_name: Some("profile".parse().unwrap()),
};

let bridge = BridgeConfig::from(params);

let expected = BridgeConfig {
cloud_name: "aws".into(),
config_file: "aws-bridge.conf".into(),
connection: "edge_to_aws".into(),
connection: "edge_to_aws@profile".into(),
address: HostPort::<MQTT_TLS_PORT>::try_from("test.test.io")?,
remote_username: Some("alpha".into()),
remote_password: None,
bridge_root_cert_path: Utf8PathBuf::from("./test_root.pem"),
remote_clientid: "alpha".into(),
local_clientid: "Aws".into(),
local_clientid: "Aws@profile".into(),
bridge_certfile: "./test-certificate.pem".into(),
bridge_keyfile: "./test-private-key.pem".into(),
use_mapper: true,
Expand Down
Loading

0 comments on commit 8f9ab76

Please sign in to comment.