def heavy_init(cls): super(RunActionEngineTest, cls).heavy_init() action = """--- version: '2.0' concat: base: std.echo base-input: output: <% $.left %><% $.right %> input: - left - right concat3: base: concat base-input: left: <% $.left %><% $.center %> right: <% $.right %> input: - left - center - right concat4: base: concat3 base-input: left: <% $.left %> center: <% $.center_left %><% $.center_right %> right: <% $.right %> input: - left - center_left - center_right - right missing_base: base: wrong input: - some_input loop_action: base: loop_action base-input: output: <% $.output %> input: - output level2_loop_action: base: loop_action base-input: output: <% $.output %> input: - output """ actions.create_actions(action)
def heavy_init(cls): super(RunActionEngineTest, cls).heavy_init() action = """--- version: '2.0' concat: base: std.echo base-input: output: <% $.left %><% $.right %> input: - left - right """ actions.create_actions(action)
def test_delete_action(self): # Create action. action_service.create_actions(ACTION_LIST, namespace=NAMESPACE) action = db_api.get_action_definition('action1', namespace=NAMESPACE) self.assertEqual(NAMESPACE, action.get('namespace')) self.assertEqual('action1', action.get('name')) # Delete action. db_api.delete_action_definition('action1', namespace=NAMESPACE) self.assertRaises(DBEntityNotFoundError, db_api.get_action_definition, name='action1', namespace=NAMESPACE)
def post(self): """Create a new action. NOTE: This text is allowed to have definitions of multiple actions. In this case they all will be created. """ acl.enforce('actions:create', context.ctx()) definition = pecan.request.text scope = pecan.request.GET.get('scope', 'private') pecan.response.status = 201 if scope not in resources.SCOPE_TYPES.values: raise exc.InvalidModelException( "Scope must be one of the following: %s; actual: " "%s" % (resources.SCOPE_TYPES.values, scope)) LOG.info("Create action(s) [definition=%s]", definition) with db_api.transaction(): db_acts = actions.create_actions(definition, scope=scope) models_dicts = [db_act.to_dict() for db_act in db_acts] action_list = [resources.Action.from_dict(act) for act in models_dicts] return resources.Actions(actions=action_list).to_json()
def test_update_actions(self): db_actions = action_service.create_actions(ACTION_LIST) self.assertEqual(2, len(db_actions)) action1_db = self._assert_single_item(db_actions, name='action1') action1_spec = spec_parser.get_action_spec(action1_db.spec) self.assertEqual('action1', action1_spec.get_name()) self.assertEqual('std.echo', action1_spec.get_base()) self.assertDictEqual({'output': 'Hi'}, action1_spec.get_base_input()) self.assertDictEqual({}, action1_spec.get_input()) db_actions = action_service.update_actions(UPDATED_ACTION_LIST) # Action 1. action1_db = self._assert_single_item(db_actions, name='action1') action1_spec = spec_parser.get_action_spec(action1_db.spec) self.assertEqual('action1', action1_spec.get_name()) self.assertListEqual([], action1_spec.get_tags()) self.assertEqual('std.echo', action1_spec.get_base()) self.assertDictEqual({'output': 'Hi'}, action1_spec.get_base_input()) self.assertIn('param1', action1_spec.get_input()) self.assertIs(action1_spec.get_input().get('param1'), utils.NotDefined)
def post(self): """Create a new action. NOTE: This text is allowed to have definitions of multiple actions. In this case they all will be created. """ acl.enforce('actions:create', context.ctx()) definition = pecan.request.text scope = pecan.request.GET.get('scope', 'private') pecan.response.status = 201 if scope not in SCOPE_TYPES.values: raise exc.InvalidModelException( "Scope must be one of the following: %s; actual: " "%s" % (SCOPE_TYPES.values, scope) ) LOG.info("Create action(s) [definition=%s]" % definition) db_acts = actions.create_actions(definition, scope=scope) models_dicts = [db_act.to_dict() for db_act in db_acts] action_list = [Action.from_dict(act) for act in models_dicts] return Actions(actions=action_list).to_json()
def test_update_actions(self): db_actions = action_service.create_actions(ACTION_LIST) self.assertEqual(2, len(db_actions)) action1_db = self._assert_single_item(db_actions, name='action1') action1_spec = spec_parser.get_action_spec(action1_db.spec) self.assertEqual('action1', action1_spec.get_name()) self.assertEqual('std.echo', action1_spec.get_base()) self.assertDictEqual({'output': 'Hi'}, action1_spec.get_base_input()) self.assertDictEqual({}, action1_spec.get_input()) db_actions = action_service.update_actions(UPDATED_ACTION_LIST) # Action 1. action1_db = self._assert_single_item(db_actions, name='action1') action1_spec = spec_parser.get_action_spec(action1_db.spec) self.assertEqual('action1', action1_spec.get_name()) self.assertListEqual([], action1_spec.get_tags()) self.assertEqual('std.echo', action1_spec.get_base()) self.assertDictEqual({'output': 'Hi'}, action1_spec.get_base_input()) self.assertIn('param1', action1_spec.get_input()) self.assertIs( action1_spec.get_input().get('param1'), utils.NotDefined )
def test_create_actions_in_namespace(self): db_actions = action_service.create_actions(ACTION_LIST, namespace=NAMESPACE) self.assertEqual(2, len(db_actions)) action1_db = self._assert_single_item(db_actions, name='action1') self.assertEqual(NAMESPACE, action1_db.namespace) action2_db = self._assert_single_item(db_actions, name='action2') self.assertEqual(NAMESPACE, action2_db.namespace) self.assertRaises(DBEntityNotFoundError, db_api.get_action_definition, name='action1', namespace='')
def post(self): """Create a new action. NOTE: This text is allowed to have definitions of multiple actions. In this case they all will be created. """ definition = pecan.request.text pecan.response.status = 201 LOG.info("Create action(s) [definition=%s]" % definition) db_acts = actions.create_actions(definition) models_dicts = [db_act.to_dict() for db_act in db_acts] action_list = [Action.from_dict(act) for act in models_dicts] return Actions(actions=action_list).to_string()
def test_create_actions(self): db_actions = action_service.create_actions(ACTION_LIST) self.assertEqual(2, len(db_actions)) # Action 1. action1_db = self._assert_single_item(db_actions, name='action1') action1_spec = spec_parser.get_action_spec(action1_db.spec) self.assertEqual('action1', action1_spec.get_name()) self.assertListEqual(['test', 'v2'], action1_spec.get_tags()) self.assertEqual('std.echo', action1_spec.get_base()) self.assertDictEqual({'output': 'Hi'}, action1_spec.get_base_input()) # Action 2. action2_db = self._assert_single_item(db_actions, name='action2') action2_spec = spec_parser.get_action_spec(action2_db.spec) self.assertEqual('action2', action2_spec.get_name()) self.assertEqual('std.echo', action1_spec.get_base()) self.assertDictEqual({'output': 'Hey'}, action2_spec.get_base_input())
def post(self): """Create a new action. NOTE: This text is allowed to have definitions of multiple actions. In this case they all will be created. """ definition = pecan.request.text scope = pecan.request.GET.get('scope', 'private') pecan.response.status = 201 if scope not in SCOPE_TYPES.values: raise exc.InvalidModelException( "Scope must be one of the following: %s; actual: " "%s" % (SCOPE_TYPES.values, scope)) LOG.info("Create action(s) [definition=%s]" % definition) db_acts = actions.create_actions(definition, scope=scope) models_dicts = [db_act.to_dict() for db_act in db_acts] action_list = [Action.from_dict(act) for act in models_dicts] return Actions(actions=action_list).to_string()
def test_run_action_with_namespace(self): namespace = 'test_ns' action_text = """--- version: '2.0' concat1: base: std.echo base-input: output: <% $.left %><% $.right %> input: - left - right concat2: base: concat1 base-input: left: <% $.left %><% $.center %> right: <% $.right %> input: - left - center - right """ actions.create_actions(action_text, namespace=namespace) self.assertRaises(exc.InvalidActionException, self.engine.start_action, 'concat1', { 'left': 'Hello, ', 'right': 'John Doe!' }, save_result=True, namespace='') action_ex = self.engine.start_action('concat1', { 'left': 'Hello, ', 'right': 'John Doe!' }, save_result=True, namespace=namespace) self.assertEqual(namespace, action_ex.workflow_namespace) self.await_action_success(action_ex.id) with db_api.transaction(): action_ex = db_api.get_action_execution(action_ex.id) self.assertEqual(states.SUCCESS, action_ex.state) self.assertEqual({'result': u'Hello, John Doe!'}, action_ex.output) action_ex = self.engine.start_action('concat2', { 'left': 'Hello, ', 'center': 'John', 'right': ' Doe!' }, save_result=True, namespace=namespace) self.assertEqual(namespace, action_ex.workflow_namespace) self.await_action_success(action_ex.id) with db_api.transaction(): action_ex = db_api.get_action_execution(action_ex.id) self.assertEqual(states.SUCCESS, action_ex.state) self.assertEqual('Hello, John Doe!', action_ex.output['result'])
def _create_action_definitions(): with db_api.transaction(): return actions.create_actions(definition, scope=scope)
def test_action_definition_cache_ttl(self): action = """--- version: '2.0' action1: base: std.echo output='Hi' output: result: $ """ wf_text = """--- version: '2.0' wf: tasks: task1: action: action1 on-success: join_task task2: action: action1 on-success: join_task join_task: join: all on-success: task4 task4: action: action1 pause-before: true """ wf_service.create_workflows(wf_text) # Create an action. db_actions = action_service.create_actions(action) self.assertEqual(1, len(db_actions)) self._assert_single_item(db_actions, name='action1') # Explicitly mark the action to be deleted after the test execution. self.addCleanup(db_api.delete_action_definitions, name='action1') # Reinitialise the cache with reduced action_definition_cache_time # to make the test faster. new_cache = cachetools.TTLCache( maxsize=1000, ttl=5 # 5 seconds ) cache_patch = mock.patch.object(lookup_utils, '_ACTION_DEF_CACHE', new_cache) cache_patch.start() self.addCleanup(cache_patch.stop) # Start workflow. wf_ex = self.engine.start_workflow('wf') self.await_workflow_paused(wf_ex.id) # Check that 'action1' 'echo' and 'noop' are cached. self.assertEqual(3, lookup_utils.get_action_definition_cache_size()) self.assertIn('action1', lookup_utils._ACTION_DEF_CACHE) self.assertIn('std.noop', lookup_utils._ACTION_DEF_CACHE) self.assertIn('std.echo', lookup_utils._ACTION_DEF_CACHE) # Wait some time until cache expires self._await( lambda: lookup_utils.get_action_definition_cache_size() == 0, fail_message="No triggers were found") self.assertEqual(0, lookup_utils.get_action_definition_cache_size()) self.engine.resume_workflow(wf_ex.id) self.await_workflow_success(wf_ex.id) # Check all actions are cached again. self.assertEqual(2, lookup_utils.get_action_definition_cache_size()) self.assertIn('action1', lookup_utils._ACTION_DEF_CACHE) self.assertIn('std.echo', lookup_utils._ACTION_DEF_CACHE)
def test_action_definition_cache_ttl(self): action = """--- version: '2.0' action1: base: std.echo output='Hi' output: result: $ """ wf_text = """--- version: '2.0' wf: tasks: task1: action: action1 on-success: join_task task2: action: action1 on-success: join_task join_task: join: all on-success: task4 task4: action: action1 pause-before: true """ wf_service.create_workflows(wf_text) # Create an action. db_actions = action_service.create_actions(action) self.assertEqual(1, len(db_actions)) self._assert_single_item(db_actions, name='action1') # Explicitly mark the action to be deleted after the test execution. self.addCleanup(db_api.delete_action_definitions, name='action1') # Reinitialise the cache with reduced action_definition_cache_time # to make the test faster. # Save the existing cache into a temporary variable and restore # the value when the test passed. old_cache = lookup_utils._ACTION_DEF_CACHE lookup_utils._ACTION_DEF_CACHE = cachetools.TTLCache( maxsize=1000, ttl=5 # 5 seconds ) self.addCleanup(setattr, lookup_utils, '_ACTION_DEF_CACHE', old_cache) # Start workflow. wf_ex = self.engine.start_workflow('wf') self.await_workflow_paused(wf_ex.id) # Check that 'action1' 'echo' and 'noop' are cached. self.assertEqual(3, lookup_utils.get_action_definition_cache_size()) self.assertIn('action1', lookup_utils._ACTION_DEF_CACHE) self.assertIn('std.noop', lookup_utils._ACTION_DEF_CACHE) self.assertIn('std.echo', lookup_utils._ACTION_DEF_CACHE) # Wait some time until cache expires time.sleep(7) self.assertEqual(0, lookup_utils.get_action_definition_cache_size()) self.engine.resume_workflow(wf_ex.id) self.await_workflow_success(wf_ex.id) # Check all actions are cached again. self.assertEqual(2, lookup_utils.get_action_definition_cache_size()) self.assertIn('action1', lookup_utils._ACTION_DEF_CACHE) self.assertIn('std.echo', lookup_utils._ACTION_DEF_CACHE)
def test_action_definition_cache_ttl(self): action = """--- version: '2.0' action1: base: std.echo output='Hi' output: result: $ """ wf_text = """--- version: '2.0' wf: tasks: task1: action: action1 on-success: join_task task2: action: action1 on-success: join_task join_task: join: all on-success: task4 task4: action: action1 pause-before: true """ wf_service.create_workflows(wf_text) # Create an action. db_actions = action_service.create_actions(action) self.assertEqual(1, len(db_actions)) self._assert_single_item(db_actions, name='action1') # Explicitly mark the action to be deleted after the test execution. self.addCleanup(db_api.delete_action_definitions, name='action1') # Reinitialise the cache with reduced action_definition_cache_time # to make the test faster. new_cache = cachetools.TTLCache( maxsize=1000, ttl=5 # 5 seconds ) cache_patch = mock.patch.object( actions, '_ACTION_DEF_CACHE', new_cache) cache_patch.start() self.addCleanup(cache_patch.stop) # Start workflow. wf_ex = self.engine.start_workflow('wf') self.await_workflow_paused(wf_ex.id) # Check that 'action1' 'echo' and 'noop' are cached. self.assertEqual(3, len(actions._ACTION_DEF_CACHE)) self.assertIn('action1', actions._ACTION_DEF_CACHE) self.assertIn('std.noop', actions._ACTION_DEF_CACHE) self.assertIn('std.echo', actions._ACTION_DEF_CACHE) # Wait some time until cache expires self._await( lambda: len(actions._ACTION_DEF_CACHE) == 0, fail_message="No triggers were found" ) self.assertEqual(0, len(actions._ACTION_DEF_CACHE)) self.engine.resume_workflow(wf_ex.id) self.await_workflow_success(wf_ex.id) # Check all actions are cached again. self.assertEqual(2, len(actions._ACTION_DEF_CACHE)) self.assertIn('action1', actions._ACTION_DEF_CACHE) self.assertIn('std.echo', actions._ACTION_DEF_CACHE)