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 !


Reply