Skip to main content

Hi folks,
I am creating an async action that would call an API for every IP address from a list of IPs. For each iteration, I use the "additional_data" parameter for passing the list index of the IP to the next iteration.
I can successfully execute this, but on the Case wall, there are some issues when I view the execution.

I have set the polling interval as 30 seconds, so I am expecting my action to run after every 30 seconds until my stopping condition is satisfied. In the case wall, I see that every iteration overrides the results of the previous iteration, but the Output Message remains the same as the first iteration. 

As shown in the screenshot, I see the output of the second iteration ('abc' is at index 1) whereas the message in orange (Successfully fetched...) is for the first iteration ('10.10.10.10'). Is this the expected behaviour, or am I missing something ??

Thanks. 

@preet_mehta would it be possible to share a code that you are using to make action async or dummy copy of a code? It seems to be an issue on how this async action is build. 


Sure @f3rz 
Here is the code:

from ScriptResult import EXECUTION_STATE_COMPLETED, EXECUTION_STATE_FAILED, EXECUTION_STATE_INPROGRESS from SiemplifyAction import SiemplifyAction from SiemplifyUtils import output_handler from TIPCommon.transformation import construct_csv from ApiManager import ApiManager from constants import GET_IP_INFO_SCRIPT_NAME from utils import get_integration_params, create_api_usage_table from IPInfo import IPInfo @output_handler def main(): siemplify = SiemplifyAction() auth_type, api_key, username, password, verify_ssl = get_integration_params(siemplify) try: previous_iteration_data = siemplify.parameters.get("additional_data") ip_index = 0 if previous_iteration_data is not None: ip_index = previous_iteration_data ip_info = IPInfo(siemplify) ip_address = ip_info.ip_address if ip_index < len(ip_info.ip_address) - 1: status = EXECUTION_STATE_INPROGRESS if ip_info.error: raise Exception(ip_info.error) api_manager = ApiManager(auth_type, api_key, username, password, siemplify.LOGGER, verify_ssl) is_success, response = ip_info.get_ip_details(api_manager, ip_index) if is_success is False: raise Exception(response) output_message = f"Successfully fetched the IP Information for '{ip_address}'." siemplify.result.add_result_json(response) ip_info.generate_tables() account_usage = create_api_usage_table(response.get("usage", {})) siemplify.result.add_data_table("Account Usage", construct_csv(account_usage)) if ip_index == len(ip_info.ip_address) - 1: status = EXECUTION_STATE_COMPLETED except Exception as e: is_success = False response = str(e) siemplify.LOGGER.error(f"General error performing action {GET_IP_INFO_SCRIPT_NAME}.") siemplify.LOGGER.exception(response) if ip_index == len(ip_info.ip_address) - 1: status = EXECUTION_STATE_FAILED output_message = f"Failed to fetch IP information for {ip_address}!\\nError: {response}" result_value = is_success siemplify.LOGGER.info(f"Status: {status}") siemplify.LOGGER.info(f"Result: {result_value}") siemplify.LOGGER.info(f"Output Message: {output_message}") if ip_index < len(ip_info.ip_address) - 1: siemplify.end(output_message, ip_index + 1, status) else: siemplify.end(output_message, "Done", status) if __name__ == "__main__": main()

Sure @f3rz 
Here is the code:

from ScriptResult import EXECUTION_STATE_COMPLETED, EXECUTION_STATE_FAILED, EXECUTION_STATE_INPROGRESS from SiemplifyAction import SiemplifyAction from SiemplifyUtils import output_handler from TIPCommon.transformation import construct_csv from ApiManager import ApiManager from constants import GET_IP_INFO_SCRIPT_NAME from utils import get_integration_params, create_api_usage_table from IPInfo import IPInfo @output_handler def main(): siemplify = SiemplifyAction() auth_type, api_key, username, password, verify_ssl = get_integration_params(siemplify) try: previous_iteration_data = siemplify.parameters.get("additional_data") ip_index = 0 if previous_iteration_data is not None: ip_index = previous_iteration_data ip_info = IPInfo(siemplify) ip_address = ip_info.ip_address if ip_index < len(ip_info.ip_address) - 1: status = EXECUTION_STATE_INPROGRESS if ip_info.error: raise Exception(ip_info.error) api_manager = ApiManager(auth_type, api_key, username, password, siemplify.LOGGER, verify_ssl) is_success, response = ip_info.get_ip_details(api_manager, ip_index) if is_success is False: raise Exception(response) output_message = f"Successfully fetched the IP Information for '{ip_address}'." siemplify.result.add_result_json(response) ip_info.generate_tables() account_usage = create_api_usage_table(response.get("usage", {})) siemplify.result.add_data_table("Account Usage", construct_csv(account_usage)) if ip_index == len(ip_info.ip_address) - 1: status = EXECUTION_STATE_COMPLETED except Exception as e: is_success = False response = str(e) siemplify.LOGGER.error(f"General error performing action {GET_IP_INFO_SCRIPT_NAME}.") siemplify.LOGGER.exception(response) if ip_index == len(ip_info.ip_address) - 1: status = EXECUTION_STATE_FAILED output_message = f"Failed to fetch IP information for {ip_address}!\\nError: {response}" result_value = is_success siemplify.LOGGER.info(f"Status: {status}") siemplify.LOGGER.info(f"Result: {result_value}") siemplify.LOGGER.info(f"Output Message: {output_message}") if ip_index < len(ip_info.ip_address) - 1: siemplify.end(output_message, ip_index + 1, status) else: siemplify.end(output_message, "Done", status) if __name__ == "__main__": main()

The problem that your "Failed..." output_message variable overwriting everything else. Async logic seems to be build correctly, so I would recommend you to add output_message variables right after execution statuses such as EXECUTION_STATE_INPROGRESS or EXECUTION_STATE_COMPLETED.

Here's a quick example of working async action, hope it helps:

from ScriptResult import EXECUTION_STATE_COMPLETED, EXECUTION_STATE_INPROGRESS from SiemplifyAction import SiemplifyAction from SiemplifyUtils import output_handler @output_handler def main(): siemplify = SiemplifyAction() initial_value = 1 expected_value = 3 try: current_value = siemplify.parameters.get("additional_data") if current_value: current_value = int(current_value) + 1 else: current_value = initial_value except Exception as e: siemplify.LOGGER.error(f"Error: {str(e)}") status = EXECUTION_STATE_COMPLETED result_value = 0 output_message = f"An error occurred: {str(e)}" siemplify.LOGGER.info(f"Current Value: {current_value} \\nExpected Value {expected_value}") if current_value >= expected_value: status = EXECUTION_STATE_COMPLETED output_message = f"Reached the target value: {current_value}" else: status = EXECUTION_STATE_INPROGRESS output_message = f"Current value: {current_value}, waiting for it to reach {expected_value}." result_value = current_value siemplify.end(output_message, result_value, status) if __name__ == "__main__": main()

Hey @f3rz Understood the issue, and thanks for the sample async action. It really helped !