def __init__(self, name='', xml=None, children=None, parent_name='', playbook_name=''): """Initializes a Workflow object. A Workflow falls under a Playbook, and has many associated Steps within it that get executed. Args: name (str, optional): The name of the Workflow object. Defaults to an empty string. xml (cElementTree, optional): The XML element tree object. Defaults to None. children (dict, optional): A dict of children. Defaults to None. parent_name (str, optional): The name of the parent for ancestry purposes. Defaults to an empty string. playbook_name (str, optional): The name of the playbook under which the workflow is located. Defaults to an empty string. """ ExecutionElement.__init__(self, name=name, parent_name=parent_name, ancestry=[parent_name]) self.playbook_name = playbook_name self.steps = {} if xml: self._from_xml(xml) else: self.start_step = 'start' self.children = children if (children is not None) else {} self.is_completed = False self.accumulated_risk = 0.0 self.total_risk = float( sum([step.risk for step in self.steps.values() if step.risk > 0])) self.is_paused = False self.executor = None self.breakpoint_steps = []
def test_data_json_field(self): TestCaseDatabase.__construct_basic_db() elem1 = ExecutionElement(name='b', parent_name='a') elem2 = ExecutionElement(name='c', parent_name='b', ancestry=['a', 'b', 'c']) elem3 = ExecutionElement(name='d', parent_name='c') elem4 = ExecutionElement() event4_data = {"a": 4, "b": [1, 2, 3], "c": "Some_String"} event1 = _EventEntry(elem1, 'SYSTEM', 'message1') event2 = _EventEntry(elem2, 'WORKFLOW', 'message2', data='some_string') event3 = _EventEntry(elem3, 'STEP', 'message3', data=6) event4 = _EventEntry(elem4, 'NEXT', 'message4', data=json.dumps(event4_data)) case_database.case_db.add_event(event=event1, cases=['case1', 'case3']) case_database.case_db.add_event(event=event2, cases=['case2', 'case4']) case_database.case_db.add_event(event=event3, cases=['case2', 'case3', 'case4']) case_database.case_db.add_event(event=event4, cases=['case1']) events = case_database.case_db.session.query(case_database.Event).all() event_json_list = [event.as_json() for event in events] input_output = {'message1': None, 'message2': 'some_string', 'message3': 6, 'message4': json.dumps(event4_data)} self.assertEqual(len(event_json_list), len(list(input_output.keys()))) for event in event_json_list: self.assertIn(event['message'], input_output) self.assertEqual(event['data'], input_output[event['message']])
def __init__(self, action=None, xml=None, parent_name='', args=None, filters=None, ancestry=None): """Initializes a new Flag object. Args: xml (cElementTree, optional): The XML element tree object. Defaults to None. parent_name (str, optional): The name of the parent for ancestry purposes. Defaults to an empty string. action (str, optional): The action name for the Flag. Defaults to an empty string. args (dict[str:str], optional): Dictionary of Argument keys to Argument values. This dictionary will be converted to a dictionary of str:Argument. Defaults to None. filters(list[Filter], optional): A list of Filter objects for the Flag object. Defaults to None. ancestry (list[str], optional): The ancestry for the Filter object. Defaults to None. """ if xml is not None: self._from_xml(xml, parent_name=parent_name, ancestry=ancestry) else: if action is None: raise InvalidElementConstructed( 'Action or xml must be specified in flag constructor') ExecutionElement.__init__(self, name=action, parent_name=parent_name, ancestry=ancestry) self.action = action args = args if args is not None else {} self.args_api, self.data_in_api = get_flag_api(self.action) self.args = validate_flag_parameters(self.args_api, args, self.action) self.filters = filters if filters is not None else []
def __init__(self, xml=None, parent_name='', action='', args=None, ancestry=None): if xml: self._from_xml(xml, parent_name, ancestry) else: ExecutionElement.__init__(self, name=action, parent_name=parent_name, ancestry=ancestry) self.action = action args = args if args is not None else {} self.args = { arg_name: arguments.Argument(key=arg_name, value=arg_value, format=type(arg_value).__name__) for arg_name, arg_value in args.items() } super(Filter, self)._register_event_callbacks({ 'FilterSuccess': callbacks.add_filter_entry('Filter success'), 'FilterError': callbacks.add_filter_entry('Filter error') })
def test_edit_note(self): TestCaseDatabase.__construct_basic_db() elem1 = ExecutionElement(name='b', parent_name='a') elem2 = ExecutionElement(name='c', parent_name='b', ancestry=['a', 'b', 'c']) elem3 = ExecutionElement(name='d', parent_name='c') elem4 = ExecutionElement() event1 = _EventEntry(elem1, 'SYSTEM', 'message1') event2 = _EventEntry(elem2, 'WORKFLOW', 'message2') event3 = _EventEntry(elem3, 'STEP', 'message3') event4 = _EventEntry(elem4, 'NEXT', 'message4') case_database.case_db.add_event(event=event1, cases=['case1', 'case3']) case_database.case_db.add_event(event=event2, cases=['case2', 'case4']) case_database.case_db.add_event(event=event3, cases=['case2', 'case3', 'case4']) case_database.case_db.add_event(event=event4, cases=['case1']) events = case_database.case_db.session.query(case_database.Event).all() smallest_id = min([event.id for event in events]) expected_json_list = [event.as_json() for event in events] for event in expected_json_list: if event['id'] == str(smallest_id): event['note'] = 'Note1' case_database.case_db.edit_event_note(smallest_id, 'Note1') events = case_database.case_db.session.query(case_database.Event).all() result_json_list = [event.as_json() for event in events] self.assertEqual(len(result_json_list), len(expected_json_list)) self.assertTrue( all(expected_event in result_json_list for expected_event in expected_json_list))
def test_add_event(self): TestCaseDatabase.__construct_basic_db() elem1 = ExecutionElement(name='b', parent_name='a') elem2 = ExecutionElement(name='c', parent_name='b', ancestry=['a', 'b', 'c']) elem3 = ExecutionElement(name='d', parent_name='c') elem4 = ExecutionElement() event1 = _EventEntry(elem1, 'SYSTEM', 'message1') event2 = _EventEntry(elem2, 'WORKFLOW', 'message2') event3 = _EventEntry(elem3, 'STEP', 'message3') event4 = _EventEntry(elem4, 'NEXT', 'message4') case_database.case_db.add_event(event=event1, cases=['case1', 'case3']) case_database.case_db.add_event(event=event2, cases=['case2', 'case4']) case_database.case_db.add_event(event=event3, cases=['case2', 'case3', 'case4']) case_database.case_db.add_event(event=event4, cases=['case1']) expected_event_messages = {'case1': [('SYSTEM', 'message1'), ('NEXT', 'message4')], 'case2': [('WORKFLOW', 'message2'), ('STEP', 'message3')], 'case3': [('SYSTEM', 'message1'), ('STEP', 'message3')], 'case4': [('WORKFLOW', 'message2'), ('STEP', 'message3')]} # check cases to events is as expected for case_name, expected_events in expected_event_messages.items(): case = case_database.case_db.session.query(case_database.Case) \ .filter(case_database.Case.name == case_name).all() self.assertEqual(len(case), 1, 'There are more than one cases sharing a name {0}'.format(case_name)) case_event_info = [(event.type, event.message) for event in case[0].events.all()] self.assertEqual(len(case_event_info), len(expected_events), 'Unexpected number of messages encountered for case {0}'.format(case_name)) self.assertSetEqual(set(case_event_info), set(expected_events), 'Expected event info does not equal received event info for case {0}'.format(case_name))
def __init__(self, xml=None, status='Success', name='', parent_name='', flags=None, ancestry=None): """Initializes a new NextStep object. Args: xml (cElementTree, optional): The XML element tree object. Defaults to None. parent_name (str, optional): The name of the parent for ancestry purposes. Defaults to an empty string. name (str, optional): The name of the NextStep object. Defaults to an empty string. flags (list[Flag], optional): A list of Flag objects for the NextStep object. Defaults to None. ancestry (list[str], optional): The ancestry for the NextStep object. Defaults to None. """ if xml is not None: self._from_xml(xml, parent_name=parent_name, ancestry=ancestry) else: ExecutionElement.__init__(self, name=name, parent_name=parent_name, ancestry=ancestry) self.status = status self.flags = flags if flags is not None else []
def __init__(self, xml=None, parent_name='', action='', args=None, filters=None, ancestry=None): """Initializes a new Flag object. Args: xml (cElementTree, optional): The XML element tree object. Defaults to None. parent_name (str, optional): The name of the parent for ancestry purposes. Defaults to an empty string. action (str, optional): The action name for the Flag. Defaults to an empty string. args (dict[str:str], optional): Dictionary of Argument keys to Argument values. This dictionary will be converted to a dictionary of str:Argument. Defaults to None. filters(list[Filter], optional): A list of Filter objects for the Flag object. Defaults to None. ancestry (list[str], optional): The ancestry for the Filter object. Defaults to None. """ if xml: self._from_xml(xml, parent_name=parent_name, ancestry=ancestry) else: ExecutionElement.__init__(self, name=action, parent_name=parent_name, ancestry=ancestry) self.action = action self.args = args if args is not None else {} self.filters = filters if filters is not None else []
def __init__(self, xml=None, name='', action='', app='', device='', inputs=None, next_steps=None, errors=None, parent_name='', position=None, ancestry=None, widgets=None, risk=0): """Initializes a new Step object. A Workflow has many steps that it executes. Args: xml (ElementTree, optional): The XML element tree object. Defaults to None. name (str, optional): The name of the Step object. Defaults to an empty string. action (str, optional): The name of the action associated with a Step. Defaults to an empty string. app (str, optional): The name of the app associated with the Step. Defaults to an empty string. device (str, optional): The name of the device associated with the app associated with the Step. Defaults to an empty string. inputs (dict, optional): A dictionary of Argument objects that are input to the step execution. Defaults to None. next_steps (list[NextStep], optional): A list of NextStep objects for the Step object. Defaults to None. errors (list[NextStep], optional): A list of NextStep error objects for the Step object. Defaults to None. parent_name (str, optional): The name of the parent for ancestry purposes. Defaults to an empty string. position (dict, optional): A dictionary with the x and y coordinates of the Step object. This is used for UI display purposes. Defaults to None. ancestry (list[str], optional): The ancestry for the Step object. Defaults to None. widgets (list[tuple(str, str)], optional): A list of widget tuples, which holds the app and the corresponding widget. Defaults to None. risk (int, optional): The risk associated with the Step. Defaults to 0. """ ExecutionElement.__init__(self, name=name, parent_name=parent_name, ancestry=ancestry) if xml is not None: self._from_xml(xml, parent_name=parent_name, ancestry=ancestry) else: if action == '' or app == '': raise InvalidElementConstructed('Either both action and app or xml must be ' 'specified in step constructor') self.action = action self.app = app self.run, self.input_api = get_app_action_api(self.app, self.action) get_app_action(self.app, self.run) inputs = inputs if inputs is not None else {} self.input = validate_app_action_parameters(self.input_api, inputs, self.app, self.action) self.device = device self.risk = risk self.conditionals = next_steps if next_steps is not None else [] self.errors = errors if errors is not None else [] self.position = position if position is not None else {} self.widgets = [_Widget(widget_app, widget_name) for (widget_app, widget_name) in widgets] if widgets is not None else [] self.raw_xml = self.to_xml() self.templated = False self.output = None self.next_up = None
def __init__(self, xml=None, parent_name="", name="", nextWorkflow="", flags=None, ancestry=None): if xml is not None: self._from_xml(xml, parent_name=parent_name, ancestry=ancestry) else: ExecutionElement.__init__(self, name=name, parent_name=parent_name, ancestry=ancestry) self.flags = flags if flags is not None else [] super(Next, self)._register_event_callbacks({'NextStepTaken': callbacks.add_next_step_entry('Step taken'), 'NextStepNotTaken': callbacks.add_next_step_entry('Step not taken')})
def _from_xml(self, xml_element, parent_name='', ancestry=None): self.action = xml_element.get("action") ExecutionElement.__init__(self, name=self.action, parent_name=parent_name, ancestry=ancestry) self.args = {arg.tag: arguments.Argument(key=arg.tag, value=arg.text, format=arg.get("format")) for arg in xml_element.findall("args/*")} self.filters = [Filter(xml=filter_element, parent_name=self.name, ancestry=self.ancestry) for filter_element in xml_element.findall("filters/*")]
def __init__(self, xml=None, parent_name='', action='', args=None, filters=None, ancestry=None): if xml: self._from_xml(xml, parent_name=parent_name, ancestry=ancestry) else: ExecutionElement.__init__(self, name=action, parent_name=parent_name, ancestry=ancestry) self.action = action self.args = args if args is not None else {} self.filters = filters if filters is not None else [] super(Flag, self)._register_event_callbacks({'FlagArgsValid': callbacks.add_flag_entry('Flag args valid'), 'FlagArgsInvalid': callbacks.add_flag_entry('Flag args invalid')})
def _from_xml(self, xml_element, parent_name=None, ancestry=None): self.action = xml_element.get('action') ExecutionElement.__init__(self, name=self.action, parent_name=parent_name, ancestry=ancestry) self.args_api, self.data_in_api = get_filter_api(self.action) args_xml = xml_element.find('args') args = (inputs_xml_to_dict(args_xml) or {}) if args_xml is not None else {} self.args = validate_filter_parameters(self.args_api, args, self.action)
def _from_xml(self, xml_element, parent_name=None, ancestry=None): self.action = xml_element.get('action') ExecutionElement.__init__(self, name=self.action, parent_name=parent_name, ancestry=ancestry) self.args = { arg.tag: arguments.Argument(key=arg.tag, value=arg.text, format=arg.get('format')) for arg in xml_element.findall('args/*') }
def _from_xml(self, step_xml, parent_name='', ancestry=None): name = step_xml.get("id") ExecutionElement.__init__(self, name=name, parent_name=parent_name, ancestry=ancestry) self.action = step_xml.find("action").text self.app = step_xml.find("app").text self.device = step_xml.find("device").text self.input = {arg.tag: arguments.Argument(key=arg.tag, value=arg.text, format=arg.get("format")) for arg in step_xml.findall("input/*")} self.conditionals = [nextstep.NextStep(xml=next_step_element, parent_name=self.name, ancestry=self.ancestry) for next_step_element in step_xml.findall("next")] self.errors = [nextstep.NextStep(xml=error_step_element, parent_name=self.name, ancestry=self.ancestry) for error_step_element in step_xml.findall("error")]
def _from_xml(self, xml_element, parent_name='', ancestry=None): name = xml_element.get('step') ExecutionElement.__init__(self, name=name, parent_name=parent_name, ancestry=ancestry) self.flags = [ Flag(xml=flag_element, parent_name=self.name, ancestry=self.ancestry) for flag_element in xml_element.findall('flag') ]
def __init__(self, name='', xml=None, children=None, parent_name='', playbook_name=''): ExecutionElement.__init__(self, name=name, parent_name=parent_name, ancestry=[parent_name]) self.playbook_name = playbook_name self.steps = {} if xml: self._from_xml(xml) self.children = children if (children is not None) else {} self.is_completed = False self.accumulated_risk = 0.0 self.total_risk = float(sum([step.risk for step in self.steps.values() if step.risk > 0])) self.is_paused = False self.executor = None self.breakpoint_steps = []
def _from_xml(self, step_xml, parent_name='', ancestry=None): self.raw_xml = step_xml name = step_xml.get('id') ExecutionElement.__init__(self, name=name, parent_name=parent_name, ancestry=ancestry) self.action = step_xml.find('action').text self.app = step_xml.find('app').text self.run, self.input_api = get_app_action_api(self.app, self.action) is_templated_xml = step_xml.find('templated') self.templated = is_templated_xml is not None and bool( is_templated_xml.text) get_app_action(self.app, self.run) input_xml = step_xml.find('inputs') if input_xml is not None: inputs = inputs_xml_to_dict(input_xml) or {} if not self.templated: self.input = validate_app_action_parameters( self.input_api, inputs, self.app, self.action) else: self.input = inputs else: self.input = validate_app_action_parameters( self.input_api, {}, self.app, self.action) device_field = step_xml.find('device') self.device = device_field.text if device_field is not None else '' risk_field = step_xml.find('risk') self.risk = risk_field.text if risk_field is not None else 0 self.conditionals = [ nextstep.NextStep(xml=next_step_element, parent_name=self.name, ancestry=self.ancestry) for next_step_element in step_xml.findall('next') ] self.widgets = [ _Widget(widget.get('app'), widget.text) for widget in step_xml.findall('widgets/*') ] position = step_xml.find('position') if position is None: self.position = {} else: x_position = position.find('x') y_position = position.find('y') if x_position is not None and y_position is not None: self.position = {'x': x_position.text, 'y': y_position.text} else: self.position = {}
def __init__(self, xml=None, parent_name='', name='', flags=None, ancestry=None): if xml is not None: self._from_xml(xml, parent_name=parent_name, ancestry=ancestry) else: ExecutionElement.__init__(self, name=name, parent_name=parent_name, ancestry=ancestry) self.flags = flags if flags is not None else []
def _from_xml(self, xml_element, parent_name='', ancestry=None): name = xml_element.get('step') status_field = xml_element.find('status') self.status = status_field.text if status_field is not None else 'Success' ExecutionElement.__init__(self, name=name, parent_name=parent_name, ancestry=ancestry) self.flags = [ Flag(xml=flag_element, parent_name=self.name, ancestry=self.ancestry) for flag_element in xml_element.findall('flag') ]
def __init__(self, xml=None, scheduler=None, children=None, enabled=False, workflow_name='', options_name=''): if xml is not None: self._from_xml(xml) else: ExecutionElement.__init__(self, name=options_name, parent_name=workflow_name) self.scheduler = scheduler if scheduler is not None else {} self.enabled = enabled self.children = children if children is not None else {}
def test_init(self): elem = ExecutionElement() self.assertEqual(elem.name, '') self.assertEqual(elem.parent_name, '') elem = ExecutionElement(name='test') self.assertEqual(elem.name, 'test') self.assertEqual(elem.parent_name, '') elem = ExecutionElement(parent_name='parent_test') self.assertEqual(elem.name, '') self.assertEqual(elem.parent_name, 'parent_test') elem = ExecutionElement(ancestry=['a', 'b', 'c']) self.assertEqual(elem.name, '') self.assertEqual(elem.parent_name, '')
def __init__(self, xml=None, parent_name='', action='', args=None, filters=None, ancestry=None): if xml: self._from_xml(xml, parent_name=parent_name, ancestry=ancestry) else: ExecutionElement.__init__(self, name=action, parent_name=parent_name, ancestry=ancestry) self.action = action self.args = args if args is not None else {} self.filters = filters if filters is not None else []
def _from_xml(self, xml_element, options_name='Default', workflow_name=''): ExecutionElement.__init__(self, name=options_name, parent_name=workflow_name) self.scheduler = { "autorun": xml_element.find(".//scheduler").get("autorun"), "type": xml_element.find(".//scheduler").get("type"), "args": { option.tag: option.text for option in xml_element.findall(".//scheduler/*") } } self.enabled = xml_element.find(".//enabled").text self.children = { child.text: None for child in xml_element.findall(".//children/child") }
def _from_xml(self, step_xml, parent_name='', ancestry=None): name = step_xml.get('id') ExecutionElement.__init__(self, name=name, parent_name=parent_name, ancestry=ancestry) self.action = step_xml.find('action').text self.app = step_xml.find('app').text device_field = step_xml.find('device') self.device = device_field.text if device_field is not None else '' risk_field = step_xml.find('risk') self.risk = int(risk_field.text) if risk_field is not None else 0 self.input = { arg.tag: arguments.Argument(key=arg.tag, value=arg.text, format=arg.get('format')) for arg in step_xml.findall('input/*') } self.conditionals = [ nextstep.NextStep(xml=next_step_element, parent_name=self.name, ancestry=self.ancestry) for next_step_element in step_xml.findall('next') ] self.errors = [ nextstep.NextStep(xml=error_step_element, parent_name=self.name, ancestry=self.ancestry) for error_step_element in step_xml.findall('error') ] self.widgets = [ _Widget(widget.get('app'), widget.text) for widget in step_xml.findall('widgets/*') ] position = step_xml.find('position') if position is None: self.position = {} else: x_position = position.find('x') y_position = position.find('y') if x_position is not None and y_position is not None: self.position = {'x': x_position.text, 'y': y_position.text} else: self.position = {}
def _from_xml(self, xml_element, parent_name=None, ancestry=None): self.action = xml_element.get('action') ExecutionElement.__init__(self, name=self.action, parent_name=parent_name, ancestry=ancestry) args = { arg.tag: arguments.Argument(key=arg.tag, value=arg.text, format=arg.get("format")) for arg in xml_element.findall("args/*") } self.args = { arg: arguments.Argument(key=arg, value=args[arg], format=type(args[arg]).__name__) for arg in args }
def __init__(self, xml=None, parent_name='', action='', args=None, ancestry=None): """Initializes a new Filter object. A Filter is used to filter input into a workflow. Args: xml (cElementTree, optional): The XML element tree object. Defaults to None. parent_name (str, optional): The name of the parent for ancestry purposes. Defaults to an empty string. action (str, optional): The action name for the filter. Defaults to an empty string. args (dict[str:str], optional): Dictionary of Argument keys to Argument values. This dictionary will be converted to a dictionary of str:Argument. Defaults to None. ancestry (list[str], optional): The ancestry for the Filter object. Defaults to None. """ if xml: self._from_xml(xml, parent_name, ancestry) else: ExecutionElement.__init__(self, name=action, parent_name=parent_name, ancestry=ancestry) self.action = action args = args if args is not None else {} self.args = {arg_name: arguments.Argument(key=arg_name, value=arg_value, format=type(arg_value).__name__) for arg_name, arg_value in args.items()}
def _from_xml(self, xml_element, options_name='Default', workflow_name='', filename=''): ExecutionElement.__init__(self, name=options_name, parent_name=workflow_name) self.scheduler = { 'autorun': xml_element.find('.//scheduler').get('autorun'), 'type': xml_element.find('.//scheduler').get('type'), 'args': { option.tag: option.text for option in xml_element.findall('.//scheduler/*') } } self.enabled = bool(xml_element.find('.//enabled').text) self.children = { construct_workflow_name_key(filename, child.text): None for child in xml_element.findall('.//children/child') }
def __init__(self, xml=None, parent_name='', action='', args=None, ancestry=None): if xml: self._from_xml(xml, parent_name, ancestry) else: ExecutionElement.__init__(self, name=action, parent_name=parent_name, ancestry=ancestry) self.action = action args = args if args is not None else {} self.args = { arg_name: arguments.Argument(key=arg_name, value=arg_value, format=type(arg_value).__name__) for arg_name, arg_value in args.items() }
def __init__(self, name="", workflowConfig=None, children=None, parent_name=""): ExecutionElement.__init__(self, name=name, parent_name=parent_name, ancestry=[parent_name]) self.workflowXML = workflowConfig self._from_xml(self.workflowXML) self.children = children if (children is not None) else {} super(Workflow, self)._register_event_callbacks({ 'InstanceCreated': callbacks.add_workflow_entry("New workflow instance Created"), 'StepExecutionSuccess': callbacks.add_workflow_entry('Step executed successfully'), 'NextStepFound': callbacks.add_workflow_entry('Next step found'), 'WorkflowShutdown': callbacks.add_workflow_entry("Workflow shut down") })