Closed reubenmiller closed 1 year ago
The operation is transitioned to EXECUTING then to SUCCESSFUL unexpectedly considering the documentation docs/src/tutorials/supported_operations.md shows that the plugin was using mosquitto_sub to send the messages anyway. I suspect the docs might be out of date now.
I would give a note for the inconsistency of our doc and the current actual behaviour. The Cumulocity Mapper is handling the operations. Last month we changed the mapper to send EXECUTING
and SUCCESSFUL
by https://github.com/thin-edge/thin-edge.io/pull/1475. I was not aware of that the document says sending operation status by mosquitto_pub
.
I would give a note for the inconsistency of our doc and the current actual behaviour. The Cumulocity Mapper is handling the operations. Last month we changed the mapper to send EXECUTING and SUCCESSFUL by https://github.com/thin-edge/thin-edge.io/pull/1475. I was not aware of that the document says sending operation status by mosquitto_pub.
Unfortunately this leads to the operation handler being useless for the c8y_Command
operation as there is not chance for a result to be added to a SUCCESSFUL
operation.
Generally the operation status should never be set to SUCCESSFUL
if there is no verification that an action actually completed and was successful.
But I'm surprised as the code looks handling the error case. If execute_operation
fails, the failure message should be sent. So, most probably the issue is inside the function execute_operation
.
match operations.matching_smartrest_template(template) {
Some(operation) => {
if let Some(command) = operation.command() {
execute_operation(payload, command.as_str(), &operation.name, operation_logs)
.await?;
}
let topic = C8yTopic::SmartRestResponse.to_topic()?;
let msg1 = Message::new(&topic, format!("501,{}", operation.name));
let msg2 = Message::new(&topic, format!("503,{}", operation.name));
Ok(vec![msg1, msg2])
}
None => Ok(vec![]),
}
Though the execute_operation
does not actually wait for the command to complete as it is using tokio:spawn. So the control is being returned quickly.
Merged #1641 to fix this issue. The corresponding build is https://github.com/thin-edge/thin-edge.io/actions/runs/3714360516.
I implemented as @reubenmiller wrote above except one: Escape " with \"
This escape is not accepted as SmartREST, which requires CSV style escape. Thus, I escaped a single double quote "
with ""
(double double-quotes)
Some tips for tests:
exit 1
(non-zero) so that you can test failure case.Merged #1641 to fix this issue. The corresponding build is https://github.com/thin-edge/thin-edge.io/actions/runs/3714360516.
I implemented as @reubenmiller wrote above except one:
Escape " with \"
This escape is not accepted as SmartREST, which requires CSV style escape. Thus, I escaped a single double quote"
with""
(double double-quotes)Some tips for tests:
- It would be good to prepare the case, the command finishes
exit 1
(non-zero) so that you can test failure case.- Also good to include some control characters and double quotes.
I updated the description about escaping "
with ""
.
Is your feature improvement request related to a problem? Please describe.
tedge version: 0.8.0
When implementing the Cumulocity
c8y_Command
(511
) message, the following items are not processed correctlySUCCESSFUL
regardless if the plugin returns a non-zero exit codeSUCCESSFUL
before the command has completed. This means that there is no chance to return the result of the commandEXECUTING
then toSUCCESSFUL
unexpectedly considering the documentation docs/src/tutorials/supported_operations.md shows that the plugin was usingmosquitto_sub
to send the messages anyway. I suspect the docs might be out of date now.The following details the plugin and configuration which was used:
Plugin configuration:
/etc/tedge/operations/c8y/c8y_Command
Plugin:
/etc/tedge/operations/command
Configure the Cumulocity
c8y_Command
handler, where the plugin simulates at command which takes 10s to executeCreate an
c8y_Command
operation using Cumulocit API, wait for the operation to complete and then check the related Cumulocity audit recordsThe audit record will show the timestamps when the operation status transitions occurred.
Describe the solution you'd like
The plugin runner (the component calling the external script) should handle the updating of the Cumulocity operation status and output, however the operation STATUS should be set based on the exit code of the external script.
The
c8y_Command
should be allowed to provide the output of the command so that the user can get information from the command itself.The
c8y_Command
command should be able to control operation status via the following conditions:Result/failure message parsing rules
Before the output or failure message is added to the SMART REST template, the following santization rules/replacements should be done:
"
with""
\n
,\t
,\r
Notes
Stdout needs to be stripped to of control characters before it is included in the
503
smartrest message, otherwise the message will be rejected by CumulocityThe
c8y_Command
generally expects to include outputDescribe alternatives you've considered
The external scripts could be given control to handle the updating of the status operations by themselves, however it assumes that the external plugins always "do the right thing". If an external program forgets to transition the operation, or it crashes unexpectedly, then the operations may be left in the
EXECUTING
state will will affect subsequent operations of the same fragmentType (due to Cumulocity's ID-less operation concept) Command should expect.By having the operation status transitions in the tedge mappers, it potentially allows the same plugin (e.g. c8y_Command plugin) to be used by different mappers, as the cloud specific actions is encapsulated in the mapper itself and not in the plugin.
Additional context
The following shows the evidence of the operation being transitioned to
SUCCESSFUL
before the command was finished. Below shows thec8y_Command
operation (after was set toSUCCESSFUL
).Below shows the Cumulocity audit record entries which shows that the operation is created and set to
SUCCESSFUL
before the command is finished executing (~within 500 milliseconds instead of the expected ~10 seconds as set in the plugin).Log output related to the same command (from the device)
Below shows the command log output which was created under
/var/log/tedge/agent/c8y_Command-*
. The timestamp entries shows that the command did take ~10 seconds to execute.