def test_init_with_arguments_with_routing(self): condition = Condition( 'HelloWorld', action_name='mod1_flag2', arguments=[Argument('arg1', reference='action2')]) self.__compare_init(condition, 'HelloWorld', 'mod1_flag2', [], [Argument('arg1', reference="action2")])
def test_execute_sends_callbacks(self): action = Action(app_name='HelloWorld', action_name='Add Three', name='helloWorld', arguments=[ Argument('num1', value='-5.6'), Argument('num2', value='4.3'), Argument('num3', value='10.2') ]) instance = TestAction._make_app_instance() result = {'started_triggered': False, 'result_triggered': False} def callback_is_sent(sender, **kwargs): if isinstance(sender, Action): self.assertIn('event', kwargs) self.assertIn(kwargs['event'], (WalkoffEvent.ActionStarted, WalkoffEvent.ActionExecutionSuccess)) if kwargs['event'] == WalkoffEvent.ActionStarted: result['started_triggered'] = True else: self.assertIn('data', kwargs) data = kwargs['data'] self.assertEqual(data['status'], 'Success') self.assertAlmostEqual(data['result'], 8.9) result['result_triggered'] = True WalkoffEvent.CommonWorkflowSignal.connect(callback_is_sent) action.execute(LocalActionExecutionStrategy(), {}, instance.instance) self.assertTrue(result['started_triggered']) self.assertTrue(result['result_triggered'])
def test_execute_default_return_success(self): action = Action(app_name='HelloWorld', action_name='dummy action', name='helloWorld', arguments=[ Argument('status', value=True), Argument('other', value=True) ]) instance = TestAction._make_app_instance() result = {'started_triggered': False, 'result_triggered': False} def callback_is_sent(sender, **kwargs): if isinstance(sender, Action): self.assertIn('event', kwargs) self.assertIn(kwargs['event'], (WalkoffEvent.ActionStarted, WalkoffEvent.ActionExecutionSuccess)) if kwargs['event'] == WalkoffEvent.ActionStarted: result['started_triggered'] = True else: self.assertIn('data', kwargs) data = kwargs['data'] self.assertEqual(data['status'], 'Success') self.assertEqual(data['result'], None) result['result_triggered'] = True WalkoffEvent.CommonWorkflowSignal.connect(callback_is_sent) action.execute(LocalActionExecutionStrategy(), {}, instance.instance) self.assertTrue(result['started_triggered']) self.assertTrue(result['result_triggered'])
def test_validate_parameters_missing_required_without_default(self): parameter_apis = [{ 'name': 'name1', 'type': 'string', 'minLength': 1, 'maxLength': 25, 'enum': ['test', 'test3'] }, { 'name': 'name2', 'type': 'integer', 'minimum': -3, 'maximum': 25 }, { 'name': 'name3', 'type': 'number', 'required': True, 'minimum': -10.5, 'maximum': 30.725 }] arguments = [ Argument('name1', value='test'), Argument('name2', value='5') ] with self.assertRaises(InvalidArgument): validate_parameters(parameter_apis, arguments, self.message)
def test_execute_with_accumulator_missing_action_callbacks(self): action = Action(app_name='HelloWorld', action_name='Add Three', name='helloWorld', arguments=[ Argument('num1', reference='1'), Argument('num2', reference='action2'), Argument('num3', value='10.2') ]) accumulator = {'1': '-5.6', 'missing': '4.3', '3': '45'} instance = TestAction._make_app_instance() result = {'started_triggered': False, 'result_triggered': False} def callback_is_sent(sender, **kwargs): if isinstance(sender, Action): self.assertIn('event', kwargs) self.assertIn(kwargs['event'], (WalkoffEvent.ActionStarted, WalkoffEvent.ActionArgumentsInvalid)) if kwargs['event'] == WalkoffEvent.ActionStarted: result['started_triggered'] = True else: result['result_triggered'] = True WalkoffEvent.CommonWorkflowSignal.connect(callback_is_sent) action.execute(LocalActionExecutionStrategy(), accumulator, instance.instance) self.assertTrue(result['started_triggered']) self.assertTrue(result['result_triggered'])
def test_validate_parameters_missing_without_default(self): parameter_apis = [{ 'name': 'name1', 'type': 'string', 'minLength': 1, 'maxLength': 25, 'enum': ['test', 'test3'] }, { 'name': 'name2', 'type': 'integer', 'minimum': -3, 'maximum': 25 }, { 'name': 'name3', 'type': 'number', 'minimum': -10.5, 'maximum': 30.725 }] arguments = [ Argument('name1', value='test'), Argument('name2', value='5') ] expected = {'name1': 'test', 'name2': 5, 'name3': None} self.assertAlmostEqual( validate_parameters(parameter_apis, arguments, self.message), expected)
def test_execute(self): condition1 = ConditionalExpression( 'and', conditions=[ Condition('HelloWorld', action_name='regMatch', arguments=[Argument('regex', value='(.*)')]) ]) condition2 = ConditionalExpression( 'and', conditions=[ Condition('HelloWorld', action_name='regMatch', arguments=[Argument('regex', value='(.*)')]), Condition('HelloWorld', action_name='regMatch', arguments=[Argument('regex', value='a')]) ]) inputs = [('name1', None, ActionResult('aaaa', 'Success'), True), ('name2', condition1, ActionResult('anyString', 'Success'), True), ('name3', condition2, ActionResult('anyString', 'Success'), True), ('name4', condition2, ActionResult('bbbb', 'Success'), False), ('name4', condition2, ActionResult('aaaa', 'Custom'), False)] for name, condition, input_str, expect_name in inputs: branch = Branch(source_id=1, destination_id=2, condition=condition) if expect_name: expected_name = branch.destination_id self.assertEqual(branch.execute(input_str, {}), expected_name) else: self.assertIsNone(branch.execute(input_str, {}))
def test_validate_parameters_skip_action_references_inputs_non_string( self): parameter_apis = [{ 'name': 'name1', 'type': 'string', 'minLength': 1, 'maxLength': 25, 'enum': ['test', 'test3'] }, { 'name': 'name2', 'type': 'integer', 'minimum': -3, 'maximum': 25 }, { 'name': 'name3', 'type': 'number', 'required': True, 'minimum': -10.5, 'maximum': 30.725 }] arguments = [ Argument('name1', value='test'), Argument('name2', value=5), Argument('name3', reference='action1') ] expected = {'name1': 'test', 'name2': 5} self.assertDictEqual( validate_parameters(parameter_apis, arguments, self.message), expected)
def test_init_with_args(self): filter_elem = Transform('HelloWorld', action_name='mod1_filter2', arguments=[Argument('arg1', value='5.4')]) self.__compare_init(filter_elem, 'HelloWorld', 'mod1_filter2', arguments=[Argument('arg1', value='5.4')])
def test_execute_action_with_valid_arguments_and_transforms_invalid_data(self): transforms = [Transform('HelloWorld', action_name='mod1_filter2', arguments=[Argument('arg1', value='5')]), Transform('HelloWorld', action_name='Top Transform')] # should go <input = invalid> -> <mod1_filter2 with error = invalid> -> <Top Transform with error = invalid> # -> <mod1_flag2 4+invalid throws error> -> False with self.assertRaises(InvalidArgument): Condition('HelloWorld', action_name='mod1_flag2', arguments=[Argument('arg1', value=4)], transforms=transforms).execute('invalid', {})
def test_init_with_args_with_routing(self): filter_elem = Transform( 'HelloWorld', action_name='mod1_filter2', arguments=[Argument('arg1', reference="action1")]) self.__compare_init(filter_elem, 'HelloWorld', 'mod1_filter2', arguments=[Argument('arg1', reference="action1")])
def test_init_with_arguments_with_conversion(self): action = Action('HelloWorld', 'returnPlusOne', 'returnPlusOne', arguments=[Argument('number', value='-5.6')]) self.__compare_init(action, 'HelloWorld', 'returnPlusOne', 'returnPlusOne', arguments=[Argument('number', value='-5.6')])
def test_init_app_action_only_with_device(self): action = Action('HelloWorld', 'helloWorld', 'helloWorld', device_id=Argument(name='__device__', value="test")) self.__compare_init(action, 'HelloWorld', 'helloWorld', 'helloWorld', device_id=Argument(name='__device__', value="test"))
def test_execute_with_accumulator_missing_action(self): action = Action(app_name='HelloWorld', action_name='Add Three', name='helloWorld', arguments=[ Argument('num1', reference='1'), Argument('num2', reference='action2'), Argument('num3', value='10.2') ]) accumulator = {'1': '-5.6', 'missing': '4.3', '3': '45'} instance = TestAction._make_app_instance() action.execute(LocalActionExecutionStrategy(), accumulator, instance.instance)
def test_execute_with_accumulator_missing_action(self): action = Action(app_name='HelloWorld', action_name='Add Three', name='helloWorld', arguments=[ Argument('num1', reference='1'), Argument('num2', reference='action2'), Argument('num3', value='10.2') ]) accumulator = {'1': '-5.6', 'missing': '4.3', '3': '45'} instance = AppInstance.create(app_name='HelloWorld', device_name='device1') action.execute(instance.instance, accumulator)
def test_execute_with_args(self): action = Action(app_name='HelloWorld', action_name='Add Three', name='helloWorld', arguments=[ Argument('num1', value='-5.6'), Argument('num2', value='4.3'), Argument('num3', value='10.2') ]) instance = AppInstance.create(app_name='HelloWorld', device_name='device1') result = action.execute(instance.instance, {}) self.assertAlmostEqual(result.result, 8.9) self.assertEqual(result.status, 'Success') self.assertEqual(action._output, result)
def test_execute_action_with_valid_arguments_and_transforms_valid_data( self): transforms = [ Transform('HelloWorld', action_name='mod1_filter2', arguments=[Argument('arg1', value='5')]), Transform('HelloWorld', action_name='Top Transform') ] # should go <input = 1> -> <mod1_filter2 = 5+1 = 6> -> <Top Transform 6=6> -> <mod1_flag2 4+6%2==0> -> True self.assertTrue( Condition('HelloWorld', action_name='mod1_flag2', arguments=[Argument('arg1', value=4)], transforms=transforms).execute( LocalActionExecutionStrategy(), '1', {}))
def test_execute_with_accumulator_with_extra_actions(self): action = Action(app_name='HelloWorld', action_name='Add Three', name='helloWorld', arguments=[ Argument('num1', reference='1'), Argument('num2', reference='action2'), Argument('num3', value='10.2') ]) accumulator = {'1': '-5.6', 'action2': '4.3', '3': '45'} instance = TestAction._make_app_instance() result = action.execute(LocalActionExecutionStrategy(), accumulator, instance.instance) self.assertAlmostEqual(accumulator[action.id], 8.9) self.assertEqual(result, 'Success')
def test_execute_with_args(self): action = Action(app_name='HelloWorld', action_name='Add Three', name='helloWorld', arguments=[ Argument('num1', value='-5.6'), Argument('num2', value='4.3'), Argument('num3', value='10.2') ]) instance = TestAction._make_app_instance() acc = {} result = action.execute(LocalActionExecutionStrategy(), acc, instance.instance) self.assertAlmostEqual(acc[action.id], 8.9) self.assertEqual(result, 'Success')
def __func(): data = request.get_json() workflows_in = set(data['execution_ids']) data_in = data['data_in'] arguments = data['arguments'] if 'arguments' in data else [] workflows_awaiting_data = set( current_app.running_context.executor.get_waiting_workflows()) execution_ids = set.intersection(workflows_in, workflows_awaiting_data) user_id = get_jwt_identity() authorization_not_required, authorized_execution_ids = get_authorized_execution_ids( execution_ids, user_id, get_jwt_claims().get('roles', [])) execution_ids = list(authorized_execution_ids | authorization_not_required) completed_execution_ids = [] arg_objects = [] for arg in arguments: arg_objects.append(Argument(**arg)) for execution_id in execution_ids: if current_app.running_context.executor.resume_trigger_step( execution_id, data_in, arg_objects): completed_execution_ids.append(execution_id) log_action_taken_on_message(user_id, execution_id) return completed_execution_ids, SUCCESS
def receive_workflows(self): """Receives requests to execute workflows, and sends them off to worker threads""" logger.info('Starting workflow receiver') box = Box(self.key, self.server_key) while not self.exit: received_message = self.cache.rpop("request_queue") if received_message is not None: try: decrypted_msg = box.decrypt(received_message) except CryptoError: logger.error( 'Worker could not decrypt received workflow message') continue try: message = ExecuteWorkflowMessage() message.ParseFromString(decrypted_msg) except DecodeError: logger.error( 'Workflow could not decode received workflow message') else: start = message.start if hasattr(message, 'start') else None start_arguments = [] if hasattr(message, 'arguments'): for arg in message.arguments: start_arguments.append( Argument(**(MessageToDict( arg, preserving_proto_field_name=True)))) yield message.workflow_id, message.workflow_execution_id, start, start_arguments, message.resume else: yield None raise StopIteration
def __update_arguments_with_data(self, data): arguments = [] for argument in self.arguments: if argument.name != self._data_param_name: arguments.append(argument) arguments.append(Argument(self._data_param_name, value=data)) return arguments
def test_branch_with_priority(self): action = Action('HelloWorld', 'helloWorld', 'helloWorld', id=10) action2 = Action('HelloWorld', 'helloWorld', 'helloWorld', id=5) action3 = Action('HelloWorld', 'helloWorld', 'helloWorld', id=1) condition = ConditionalExpression( 'and', conditions=[ Condition('HelloWorld', action_name='regMatch', arguments=[Argument('regex', value='aaa')]) ]) branch_one = Branch(source_id=action.id, destination_id=5, condition=condition, priority=5) branch_two = Branch(source_id=action.id, destination_id=1, condition=condition, priority=1) action._output = ActionResult(result='aaa', status='Success') workflow = Workflow('test', 1, actions=[action, action2, action3], branches=[branch_one, branch_two]) self.assertEqual(workflow.get_branch(action, {}), 1)
def test_execute_return_failure(self): action = Action(app_name='HelloWorld', action_name='dummy action', name='helloWorld', arguments=[Argument('status', value=False)]) instance = AppInstance.create(app_name='HelloWorld', device_name='device1') result = {'started_triggered': False, 'result_triggered': False} def callback_is_sent(sender, **kwargs): if isinstance(sender, Action): self.assertIn('event', kwargs) self.assertIn(kwargs['event'], (WalkoffEvent.ActionStarted, WalkoffEvent.ActionExecutionError)) if kwargs['event'] == WalkoffEvent.ActionStarted: result['started_triggered'] = True else: self.assertIn('data', kwargs) data = kwargs['data'] self.assertEqual(data['status'], 'Failure') self.assertEqual(data['result'], False) result['result_triggered'] = True WalkoffEvent.CommonWorkflowSignal.connect(callback_is_sent) action.execute(instance.instance, {}) self.assertTrue(result['started_triggered']) self.assertTrue(result['result_triggered'])
def test_execute_with_accumulator_with_extra_actions(self): action = Action(app_name='HelloWorld', action_name='Add Three', name='helloWorld', arguments=[ Argument('num1', reference='1'), Argument('num2', reference='action2'), Argument('num3', value='10.2') ]) accumulator = {'1': '-5.6', 'action2': '4.3', '3': '45'} instance = AppInstance.create(app_name='HelloWorld', device_name='device1') result = action.execute(instance.instance, accumulator) self.assertAlmostEqual(result.result, 8.9) self.assertEqual(result.status, 'Success') self.assertEqual(action._output, result)
def test_execute_with_complex_args(self): action = Action(app_name='HelloWorld', action_name='Json Sample', name='helloWorld', arguments=[ Argument('json_in', value={ 'a': '-5.6', 'b': { 'a': '4.3', 'b': 5.3 }, 'c': ['1', '2', '3'], 'd': [{ 'a': '', 'b': 3 }, { 'a': '', 'b': -1.5 }, { 'a': '', 'b': -0.5 }] }) ]) instance = TestAction._make_app_instance() acc = {} result = action.execute(LocalActionExecutionStrategy(), acc, instance.instance) self.assertAlmostEqual(acc[action.id], 11.0) self.assertEqual(result, 'Success')
def test_execute_with_complex_args(self): action = Action(app_name='HelloWorld', action_name='Json Sample', name='helloWorld', arguments=[ Argument('json_in', value={ 'a': '-5.6', 'b': { 'a': '4.3', 'b': 5.3 }, 'c': ['1', '2', '3'], 'd': [{ 'a': '', 'b': 3 }, { 'a': '', 'b': -1.5 }, { 'a': '', 'b': -0.5 }] }) ]) instance = AppInstance.create(app_name='HelloWorld', device_name='device1') result = action.execute(instance.instance, {}) self.assertAlmostEqual(result.result, 11.0) self.assertEqual(result.status, 'Success') self.assertEqual(action._output, result)
def test_execute_with_complex_args(self): original_filter = Transform( 'HelloWorld', action_name='sub1_filter1', arguments=[Argument('arg1', value={'a': '5.4', 'b': 'string_in'})] ) self.assertEqual(original_filter.execute(LocalActionExecutionStrategy(), 3, {}), '3.0 5.4 string_in')
def __func(workflow): if not workflow.is_valid: return Problem(INVALID_INPUT_ERROR, 'Cannot execute workflow', 'Workflow is invalid') args = data['arguments'] if 'arguments' in data else None start = data['start'] if 'start' in data else None arguments = [] if args: errors = [] arguments = [Argument(**arg) for arg in args] for argument in arguments: if argument.errors: errors.append('Errors in argument {}: {}'.format( argument.name, argument.errors)) if errors: current_app.logger.error( 'Could not execute workflow. Invalid Argument construction' ) return Problem( INVALID_INPUT_ERROR, 'Cannot execute workflow.', 'Some arguments are invalid. Reason: {}'.format(errors)) execution_id = current_app.running_context.executor.execute_workflow( workflow_id, start=start, start_arguments=arguments) current_app.logger.info('Executed workflow {0}'.format(workflow_id)) return {'id': execution_id}, SUCCESS_ASYNC
def test_execute_with_args_with_conversion(self): self.assertAlmostEqual( Transform('HelloWorld', action_name='mod1_filter2', arguments=[Argument('arg1', value='10.3')]).execute(5.4, {}), 15.7)