diff options
author | initard <solo@softwareag.com> | 2022-03-21 23:15:14 +0000 |
---|---|---|
committer | initard <solo@softwareag.com> | 2022-03-24 17:03:14 +0000 |
commit | 0303c0608d1ad919c09b56f8084a74def6564818 (patch) | |
tree | 8546947879f50383f396bfd37abe6439c405f8aa /crates/core/tedge_mapper/src/c8y/converter.rs | |
parent | 648597d8b2b52ed397fe9d11f920dc83481b5b16 (diff) |
fixing panic when wrong command set in template #983
- tedge-mapper was previously leaving operations hanging dead in the
cloud if the wrong command path was set inside the template file
in /etc/tedge/operations/<cloud>/operation_name
- this will fix handles the error, (removing the unwrap)
- it also ensures that operation status is updated to executing and
then to failed.
- added test to check if execute_operations is blocked or not
Signed-off-by: initard <solo@softwareag.com>
Diffstat (limited to 'crates/core/tedge_mapper/src/c8y/converter.rs')
-rw-r--r-- | crates/core/tedge_mapper/src/c8y/converter.rs | 67 |
1 files changed, 50 insertions, 17 deletions
diff --git a/crates/core/tedge_mapper/src/c8y/converter.rs b/crates/core/tedge_mapper/src/c8y/converter.rs index bc61b78b..1ae5b4dc 100644 --- a/crates/core/tedge_mapper/src/c8y/converter.rs +++ b/crates/core/tedge_mapper/src/c8y/converter.rs @@ -288,7 +288,11 @@ async fn parse_c8y_topics( Err( ref err @ CumulocityMapperError::FromSmartRestDeserializer( SmartRestDeserializerError::InvalidParameter { ref operation, .. }, - ), + ) + | ref err @ CumulocityMapperError::ExecuteFailed { + operation_name: ref operation, + .. + }, ) => { let topic = C8yTopic::SmartRestResponse.to_topic()?; let msg1 = Message::new(&topic, format!("501,{operation}")); @@ -296,7 +300,6 @@ async fn parse_c8y_topics( error!("{err}"); Ok(vec![msg1, msg2]) } - Err(err) => { error!("{err}"); Ok(vec![]) @@ -576,24 +579,37 @@ async fn validate_and_publish_software_list( Ok(vec![]) } -async fn execute_operation(payload: &str, command: &str) -> Result<(), CumulocityMapperError> { +async fn execute_operation( + payload: &str, + command: &str, + operation_name: &str, +) -> Result<(), CumulocityMapperError> { let command = command.to_owned(); let payload = payload.to_string(); - let _handle = tokio::spawn(async move { - let mut child = tokio::process::Command::new(command) - .args(&[payload]) - .stdin(Stdio::null()) - .stdout(Stdio::null()) - .stderr(Stdio::null()) - .spawn() - .map_err(|e| CumulocityMapperError::ExecuteFailed(e.to_string())) - .unwrap(); - - child.wait().await - }); + let child = tokio::process::Command::new(&command) + .args(&[&payload]) + .stdin(Stdio::null()) + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .spawn() + .map_err(|e| CumulocityMapperError::ExecuteFailed { + error_message: e.to_string(), + command: command.to_string(), + operation_name: operation_name.to_string(), + }); - Ok(()) + match child { + Ok(mut child) => { + let _handle = tokio::spawn(async move { + let _ = child.wait().await; + }); + return Ok(()); + } + Err(err) => { + return Err(err); + } + }; } async fn process_smartrest( @@ -660,7 +676,7 @@ async fn forward_operation_request( match operations.matching_smartrest_template(template) { Some(operation) => { if let Some(command) = operation.command() { - execute_operation(payload, command.as_str()).await?; + execute_operation(payload, command.as_str(), &operation.name).await?; } Ok(vec![]) } @@ -717,3 +733,20 @@ pub fn get_child_id_from_topic(topic: &str) -> Result<Option<String>, Conversion option => Ok(option), } } + +mod tests { + #[tokio::test] + async fn test_execute_operation_is_not_blocked() { + let now = std::time::Instant::now(); + let () = super::execute_operation("5", "sleep", "sleep_one") + .await + .unwrap(); + let () = super::execute_operation("5", "sleep", "sleep_two") + .await + .unwrap(); + + // a result between now and elapsed that is not 0 probably means that the operations are + // blocking and that you probably removed a tokio::spawn handle (; + assert_eq!(now.elapsed().as_secs(), 0); + } +} |