def test_action_description(self): std_http = db_api.get_action_definition("std.http") std_echo = db_api.get_action_definition("std.echo") self.assertIn("HTTP action", std_http.description) self.assertIn("param body: (optional) Dictionary, bytes", std_http.description) self.assertIn("This action just returns a configured value", std_echo.description)
def test_action_description(self): std_http = db_api.get_action_definition("std.http") std_echo = db_api.get_action_definition("std.echo") self.assertIn("Constructs an HTTP action", std_http.description) self.assertIn("param body: (optional) Dictionary, bytes", std_http.description) self.assertIn("This action just returns a configured value", std_echo.description)
def __init__(self, action_def, action_ex=None, task_ex=None, task_ctx=None, wf_ctx=None): self.action_spec = spec_parser.get_action_spec(action_def.spec) try: base_action_def = db_api.get_action_definition( self.action_spec.get_base() ) except exc.DBEntityNotFoundError: raise exc.InvalidActionException( "Failed to find action [action_name=%s]" % self.action_spec.get_base() ) base_action_def = self._gather_base_actions( action_def, base_action_def ) super(AdHocAction, self).__init__( base_action_def, action_ex, task_ex ) self.adhoc_action_def = action_def self.task_ctx = task_ctx or {} self.wf_ctx = wf_ctx or {}
def _gather_base_actions(self, action_def, base_action_def): """Find all base ad-hoc actions and store them An ad-hoc action may be based on another ad-hoc action (and this recursively). Using twice the same base action is not allowed to avoid infinite loops. It stores the list of ad-hoc actions. :param action_def: Action definition :type action_def: ActionDefinition :param base_action_def: Original base action definition :type base_action_def: ActionDefinition :return; The definition of the base system action :rtype; ActionDefinition """ self.adhoc_action_defs = [action_def] original_base_name = self.action_spec.get_name() action_names = set([original_base_name]) base = base_action_def while not base.is_system and base.name not in action_names: action_names.add(base.name) self.adhoc_action_defs.append(base) base_name = base.spec['base'] base = db_api.get_action_definition(base_name) # if the action is repeated if base.name in action_names: raise ValueError( 'An ad-hoc action cannot use twice the same action, %s is ' 'used at least twice' % base.name ) return base
def test_get_all_pagination(self): # Create an adhoc action for the purpose of the test. adhoc_actions.create_actions(ADHOC_ACTION_YAML) resp = self.app.get('/v2/actions?limit=1&sort_keys=id,name') self.assertEqual(200, resp.status_int) self.assertIn('next', resp.json) self.assertEqual(1, len(resp.json['actions'])) self.check_adhoc_action_json(resp.json['actions'][0]) param_dict = utils.get_dict_from_string( resp.json['next'].split('?')[1], delimiter='&' ) action_def = db_api.get_action_definition('my_action') # TODO(rakhmerov): In this case we can't use IDs for marker because # in general we don't identify action descriptors with IDs. expected_dict = { 'marker': action_def.id, 'limit': 1, 'sort_keys': 'id,name', 'sort_dirs': 'asc,asc' } self.assertTrue( set(expected_dict.items()).issubset(set(param_dict.items())) )
def _gather_base_actions(self, action_def, base_action_def): """Find all base ad-hoc actions and store them An ad-hoc action may be based on another ad-hoc action (and this recursively). Using twice the same base action is not allowed to avoid infinite loops. It stores the list of ad-hoc actions. :param action_def: Action definition :type action_def: ActionDefinition :param base_action_def: Original base action definition :type base_action_def: ActionDefinition :return; The definition of the base system action :rtype; ActionDefinition """ self.adhoc_action_defs = [action_def] original_base_name = self.action_spec.get_name() action_names = set([original_base_name]) base = base_action_def while not base.is_system and base.name not in action_names: action_names.add(base.name) self.adhoc_action_defs.append(base) base_name = base.spec['base'] base = db_api.get_action_definition(base_name) # if the action is repeated if base.name in action_names: raise ValueError( 'An ad-hoc action cannot use twice the same action, %s is ' 'used at least twice' % base.name) return base
def test_get_all_operational_error(self, mocked_get_all): # Create an adhoc action for the purpose of the test. adhoc_actions.create_actions(ADHOC_ACTION_YAML) action_def = db_api.get_action_definition('my_action') mocked_get_all.side_effect = [ # Emulating DB OperationalError sa.exc.OperationalError('Mock', 'mock', 'mock'), [action_def] # Successful run ] resp = self.app.get('/v2/actions') actions_json = resp.json['actions'] # There will be 'std.' actions and the one we've just created. self.assertGreater(len(actions_json), 1) # Let's check some of the well-known 'std.' actions. self._assert_single_item(actions_json, name='std.echo') self._assert_single_item(actions_json, name='std.ssh') self._assert_single_item(actions_json, name='std.fail') self._assert_single_item(actions_json, name='std.noop') self._assert_single_item(actions_json, name='std.async_noop') # Now let's check the ad-hoc action data. adhoc_action_json = self._assert_single_item( actions_json, name='my_action' ) self.check_adhoc_action_json(adhoc_action_json)
def get(self, name): """Return the named action.""" LOG.info("Fetch action [name=%s]" % name) db_model = db_api.get_action_definition(name) return Action.from_dict(db_model.to_dict())
def get(self, name): """Return the named action.""" acl.enforce('actions:get', context.ctx()) LOG.info("Fetch action [name=%s]" % name) db_model = db_api.get_action_definition(name) return Action.from_dict(db_model.to_dict())
def test_action_input(self): std_http = db_api.get_action_definition("std.http") std_email = db_api.get_action_definition("std.email") http_action_input = ('url, method="GET", params=null, body=null, ' 'headers=null, cookies=null, auth=null, ' 'timeout=null, allow_redirects=null, ' 'proxies=null, verify=null') self.assertEqual(http_action_input, std_http.input) std_email_input = ( "from_addr, to_addrs, smtp_server, reply_to=null, cc_addrs=null, " "bcc_addrs=null, smtp_password=null, subject=null, body=null, " "html_body=null") self.assertEqual(std_email_input, std_email.input)
def __init__(self, action_def, action_ex=None, task_ex=None): self.action_spec = spec_parser.get_action_spec(action_def.spec) base_action_def = db_api.get_action_definition( self.action_spec.get_base()) super(AdHocAction, self).__init__(base_action_def, action_ex, task_ex) self.adhoc_action_def = action_def
def _delete_action_definition(): with db_api.transaction(): db_model = db_api.get_action_definition(identifier) if db_model.is_system: msg = "Attempt to delete a system action: %s" % identifier raise exc.DataAccessException(msg) db_api.delete_action_definition(identifier)
def _run_existing_action(action_ex_id, target): action_ex = db_api.get_action_execution(action_ex_id) action_def = db_api.get_action_definition(action_ex.name) result = rpc.get_executor_client().run_action(action_ex_id, action_def.action_class, action_def.attributes or {}, action_ex.input, target) return _get_action_output(result) if result else None
def run_existing_action(action_ex_id, target): action_ex = db_api.get_action_execution(action_ex_id) action_def = db_api.get_action_definition(action_ex.name) return run_action( action_def, action_ex.input, action_ex_id, target )
def test_action_input(self): std_http = db_api.get_action_definition("std.http") std_email = db_api.get_action_definition("std.email") http_action_input = ( 'url, method="GET", params=null, body=null, ' 'headers=null, cookies=null, auth=null, ' 'timeout=null, allow_redirects=null, ' 'proxies=null, verify=null' ) self.assertEqual(http_action_input, std_http.input) std_email_input = ( "from_addr, to_addrs, smtp_server, " "smtp_password, subject=null, body=null" ) self.assertEqual(std_email_input, std_email.input)
def test_action_input(self): std_http = db_api.get_action_definition("std.http") std_email = db_api.get_action_definition("std.email") http_action_input = ( "url, method=GET, params=None, body=None, " "headers=None, cookies=None, auth=None, " "timeout=None, allow_redirects=None, " "proxies=None, verify=None" ) self.assertEqual(http_action_input, std_http.input) std_email_input = ( "from_addr, to_addrs, smtp_server, " "smtp_password, subject=None, body=None" ) self.assertEqual(std_email_input, std_email.input)
def run_action(action_ex_id, target): action_ex = db_api.get_action_execution(action_ex_id) action_def = db_api.get_action_definition(action_ex.name) rpc.get_executor_client().run_action( action_ex.id, action_def.action_class, action_def.attributes or {}, action_ex.input, target )
def _delete_action_definition(): with db_api.transaction(): db_model = db_api.get_action_definition(identifier, namespace=namespace) if db_model.is_system: raise exc.DataAccessException( "Attempt to delete a system action: %s" % identifier) db_api.delete_action_definition(identifier, namespace=namespace)
def delete(self, name): """Delete the named action.""" LOG.info("Delete action [name=%s]" % name) with db_api.transaction(): db_model = db_api.get_action_definition(name) if db_model.is_system: msg = "Attempt to delete a system action: %s" % name raise exc.DataAccessException(msg) db_api.delete_action_definition(name)
def get(self, identifier): """Return the named action. :param identifier: ID or name of the Action to get. """ acl.enforce('actions:get', context.ctx()) LOG.info("Fetch action [identifier=%s]", identifier) db_model = db_api.get_action_definition(identifier) return resources.Action.from_dict(db_model.to_dict())
def delete(self, identifier): """Delete the named action.""" acl.enforce('actions:delete', context.ctx()) LOG.info("Delete action [identifier=%s]", identifier) with db_api.transaction(): db_model = db_api.get_action_definition(identifier) if db_model.is_system: msg = "Attempt to delete a system action: %s" % identifier raise exc.DataAccessException(msg) db_api.delete_action_definition(identifier)
def _run_existing_action(action_ex_id, target): action_ex = db_api.get_action_execution(action_ex_id) action_def = db_api.get_action_definition(action_ex.name) result = rpc.get_executor_client().run_action( action_ex_id, action_def.action_class, action_def.attributes or {}, action_ex.input, target, safe_rerun=action_ex.runtime_context.get('safe_rerun', False)) return _get_action_output(result) if result else None
def _run_existing_action(action_ex_id, target): action_ex = db_api.get_action_execution(action_ex_id) action_def = db_api.get_action_definition(action_ex.name) result = rpc.get_executor_client().run_action( action_ex_id, action_def.action_class, action_def.attributes or {}, action_ex.input, target ) return _get_action_output(result) if result else None
def __init__(self, action_def, action_ex=None, task_ex=None): self.action_spec = spec_parser.get_action_spec(action_def.spec) base_action_def = db_api.get_action_definition( self.action_spec.get_base() ) super(AdHocAction, self).__init__( base_action_def, action_ex, task_ex ) self.adhoc_action_def = action_def
def _run_existing_action(action_ex_id, target): action_ex = db_api.get_action_execution(action_ex_id) action_def = db_api.get_action_definition(action_ex.name) result = rpc.get_executor_client().run_action( action_ex_id, action_def.action_class, action_def.attributes or {}, action_ex.input, target, safe_rerun=action_ex.runtime_context.get('safe_rerun', False) ) return _get_action_output(result) if result else None
def test_delete_action(self): # Create action. adhoc_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 test_get_operational_error(self, mocked_get): # Create an adhoc action for the purpose of the test. adhoc_actions.create_actions(ADHOC_ACTION_YAML) action_def = db_api.get_action_definition('my_action') mocked_get.side_effect = [ # Emulating DB OperationalError sa.exc.OperationalError('Mock', 'mock', 'mock'), action_def # Successful run ] resp = self.app.get('/v2/actions/my_action') self.assertEqual(200, resp.status_int) self.check_adhoc_action_json(resp.json)
def _gather_base_actions(self, action_def, base_action_def): """Find all base ad-hoc actions and store them. An ad-hoc action may be based on another ad-hoc action and this works recursively, so that the base action can also be based on an ad-hoc action. Using the same base action more than once in this action hierarchy is not allowed to avoid infinite loops. The method stores the list of ad-hoc actions. :param action_def: Action definition :type action_def: ActionDefinition :param base_action_def: Original base action definition :type base_action_def: ActionDefinition :return: The definition of the base system action :rtype: ActionDefinition """ self.adhoc_action_defs = [action_def] original_base_name = self.action_spec.get_name() action_names = set([original_base_name]) base = base_action_def while not base.is_system and base.name not in action_names: action_names.add(base.name) self.adhoc_action_defs.append(base) base_name = base.spec['base'] try: base = db_api.get_action_definition(base_name, namespace=base.namespace) except exc.DBEntityNotFoundError: raise exc.InvalidActionException( "Failed to find action [action_name=%s namespace=%s] " % (base_name, base.namespace) ) # if the action is repeated if base.name in action_names: raise ValueError( 'An ad-hoc action cannot use twice the same action, %s is ' 'used at least twice' % base.name ) return base
def check_adhoc_action_json(self, action_json): self.assertIsNotNone(action_json) self.assertIsInstance(action_json, dict) action_name = action_json['name'] action_def = db_api.get_action_definition(action_name) self.assertIsNotNone( action_def, 'Ad-hoc action definition does not exist [name=%s]' % action_name ) # Compare action JSON with the state of the corresponding # persistent object. for k, v in action_json.items(): self.assertEqual(v, utils.datetime_to_str(getattr(action_def, k)))
def __init__(self, action_def, action_ex=None, task_ex=None, task_ctx=None, wf_ctx=None): self.action_spec = spec_parser.get_action_spec(action_def.spec) base_action_def = db_api.get_action_definition( self.action_spec.get_base()) base_action_def = self._gather_base_actions(action_def, base_action_def) super(AdHocAction, self).__init__(base_action_def, action_ex, task_ex) self.adhoc_action_def = action_def self.task_ctx = task_ctx or {} self.wf_ctx = wf_ctx or {}