Creating an Active Action Script
General Rules
Active action scripts are universal for both incidents and aggregations. They can be used for single manual execution as well as during status transitions in Workflow as pre-actions and post-actions.
You can create an Active Action script in two programming languages: JavaScript (NodeJS) and Python. To do this, you need to create a script file in the saf-incident-manager/common/actions
or $OSD_HOME/config/actions
folder.
If scripts are created in $OSD_HOME/config/actions
, they will be saved during plugin updates; otherwise, they will be lost during updates.
All scripts must have unique names; otherwise, the desired script may be recognized incorrectly.
Regardless of the chosen language, the following data will be passed to the script when executing an action for an incident:
{
"currentUser": {
"backend_roles": [
// Current user's backend roles
],
"roles": [
// Current user's roles
]
},
"aggregationId": "zGQt4o8BqXcWBDa4I1DFGDH5", // Aggregation ID
"index": ".incident_of_aggregation_results", // Index where the aggregation is stored
"log": "", // Aggregation logs (change history)
"metadata": {
"aggregationId": "zGQt4o8BqXcWBDa4I1DFGDH5", // Aggregation ID
"aggregationTitle": "Exchange: Anti-spam missed emails", // Aggregation title
"aggregationDescription": "Exchange: Anti-spam missed emails with archive", // Aggregation description
"index": ".incident_of_aggregation_results", // Index where the aggregation is stored
"urlToAggregation": "https://smarthost.ru//incident-manager/aggregations-result...", // Aggregation URL
"baseFields": {
// Base aggregation fields defined during configuration
},
"additionalFields": {
// Additional aggregation fields defined during configuration, plus comparison fields from the aggregation itself
},
"comparation_fields": {
// Fields for comparison within the aggregation
},
"functional_fields": {
// Functional fields in the aggregation
}
},
"sideEffects": {},
"target": "manual", // manual - flag indicating either active action usage or new Workflow status
"workflowId": "my-workflow" // Aggregation workflow ID
"_source": {
// Complete untouched aggregation result
}
}
When executing an active action script for an aggregation, the following parameters will be passed:
{
"currentUser": {
"backend_roles": [
// Current user's backend roles
],
"roles": [
// Current user's roles
]
},
"aggregationId": "zGQt4o8BqXcWBDa4I1DFGDH5", // Aggregation ID
"index": ".incident_of_aggregation_results", // Index where the aggregation is stored
"log": "", // Aggregation logs (change history)
"metadata": {
"aggregationId": "zGQt4o8BqXcWBDa4I1DFGDH5", // Aggregation ID
"aggregationTitle": "Exchange: Anti-spam missed emails", // Aggregation title
"aggregationDescription": "Exchange: Anti-spam missed emails with archive", // Aggregation description
"index": ".incident_of_aggregation_results", // Index where the aggregation is stored
"urlToAggregation": "https://smarthost.ru//incident-manager/aggregations-result...", // Aggregation URL
"baseFields": {
// Base aggregation fields defined during configuration
},
"additionalFields": {
// Additional aggregation fields defined during configuration, plus comparison fields from the aggregation itself
},
"comparation_fields": {
// Fields for comparison within the aggregation
},
"functional_fields": {
// Functional fields in the aggregation
}
},
"sideEffects": {},
"target": "manual", // manual - flag indicating either active action usage or new Workflow status
"workflowId": "my-workflow" // Aggregation workflow ID
"_source": {
// Complete untouched aggregation result
}
}
Scripts invoked with target manual
cannot modify the incident or aggregation itself. If you want to perform an action that modifies the aggregation or incident, execute this action as a pre-action in Workflow during the transition to a new status.
Using JavaScript
When creating an active action in JavaScript, you can follow this function template:
/**
* ! Function for executing active actions
* @param doc - JSON containing active actions
* @param metadata - metadata passed with the entity (aggregation or incident)
* @param entities - list of passed incidents (used for bulk Workflow status editing)
* @param currentUser - current user
* @param index - index where the entity is stored (aggregation or incident)
* @param log - entity logs (change history of aggregation or incident)
* @param sideEffects - actions on status transition
* @param workflowId - entity workflow ID (aggregation or incident)
* @param target - flag indicating whether an active action or new Workflow status is being used
* @param incidentId - incident ID (passed when working with incident)
* @param aggregationId - aggregation ID (passed when working with aggregation)
* @param _source - complete untouched entity result (aggregation or incident)
* @param logger - logging function
*/
export default async (doc, metadata, entities, currentUser, index, log, sideEffects, workflowId, target, incidentId, aggregationId, _source, logger) => {
// function body
};
Parameters are passed directly to the function by calling it during execution. The function should be asynchronous to ensure it executes correctly and completes as planned.
Using Python
When creating an active action in Python, you can use the following template:
import json
class Object:
# Helper function for converting object to JSON
def toJSON(self):
return json.dumps(self, default=lambda o: o.__dict__, sort_keys=True, indent=1)
""" Function for executing active actions
@param: doc - entity(ies) (aggregation or incident)
@param: metadata - metadata passed with the entity (aggregation or incident)
@param: entities - list of passed incidents (used for bulk Workflow status editing)
@param: currentUser - current user
@param: index - index where the entity is stored (aggregation or incident)
@param: log - entity logs (change history of aggregation or incident)
@param: sideEffects - actions on status transition
@param: workflowId - entity workflow ID (aggregation or incident)
@param: target - flag indicating whether an active action or new Workflow status is being used
@param: incidentId - incident ID (passed when working with incident)
@param: aggregationId - aggregation ID (passed when working with aggregation)
@param: _source - complete untouched entity result (aggregation or incident)
"""
def my_func(doc, metadata, entities, currentUser, index, log, sideEffects, workflowId, target, incidentId, aggregationId, _source):
# function code
print(output.toJSON()) # Output doc data
if __name__ == "__main__":
_json = input() # Data is read from stdin stream
res = json.loads(_json)
my_func(
doc=res.get("doc"),
metadata=res.get("metadata"),
entities=res.get("entities"),
currentUser=res.get("currentUser"),
index=res.get("index"),
log=res.get("log"),
sideEffects=res.get("sideEffects"),
workflowId=res.get("workflowId"),
target=res.get("target"),
incidentId=res.get("incidentId"),
aggregationId=res.get("aggregationId"),
_source=res.get("_source"),
)
Parameters for the active action in Python are passed through the console input stream (stdin
). Output parameters, such as the modified incident or aggregation entity (doc
), should be passed through the output stream (stdout
). This example is not definitive, and you can use any methods and functions that are convenient.