Пример #1
0
def validate_action_params(parameters, dereferencer, app_name, action_name, action_func, event=''):
    seen = set()
    for parameter in parameters:
        parameter = deref(parameter, dereferencer)
        name = parameter['name']
        if name in seen:
            raise InvalidApi('Duplicate parameter {0} in api for {1} '
                             'for action {2}'.format(name, app_name, action_name))
        seen.add(name)

    if hasattr(action_func, '__arg_names'):
        method_params = list(action_func.__arg_names)
    else:
        method_params = get_function_arg_names(action_func)

    if method_params and method_params[0] == 'self':
        method_params.pop(0)

    if event:
        method_params.pop(0)

        if action_func.__event_name != event:
            logger.warning('In app {0} action {1}, event documented {2} does not match '
                           'event specified {3}'.format(app_name, action_name, event, action_func.__event_name))

    if not seen == set(method_params):
        only_in_api = seen - set(method_params)
        only_in_definition = set(method_params) - seen
        message = ('Discrepancy between defined parameters in API and in method definition '
                   'for app {0} action {1}.'.format(app_name, action_name))
        if only_in_api:
            message += ' Only in API: {0}.'.format(only_in_api)
        if only_in_definition:
            message += ' Only in definition: {0}'.format(only_in_definition)
        raise InvalidApi(message)
Пример #2
0
def validate_data_in_param(params, data_in_param_name, message_prefix):
    data_in_param = next((param for param in params if param['name'] == data_in_param_name), None)
    if data_in_param is None:
        raise InvalidApi(
            '{0} has a dataIn param {1} '
            'for which it does not have a '
            'corresponding parameter'.format(message_prefix, data_in_param_name))
    elif not data_in_param.get('required', False):
        raise InvalidApi(
            '{0} has a dataIn param {1} which is not marked as required in the api. '
            'Add "required: true" to parameter specification for {1}'.format(message_prefix,
                                                                             data_in_param_name))
Пример #3
0
    def _event(func):
        arg_names = get_function_arg_names(func)
        if len(arg_names) < 2:
            raise InvalidApi('Event action has too few parameters. '
                             'There must be a "self" and a second parameter to receive data from the event.')

        @wraps(func)
        def wrapper(*args, **kwargs):
            result = AsyncResult()

            @event_.connect
            def send(data):
                if len(kwargs) > 0:
                    result.set(func(args[0], data, **kwargs))
                else:
                    result.set(func(args[0], data))

            try:
                result = result.get(timeout=timeout)
            except Timeout:
                result = 'Getting event {0} timed out at {1} seconds'.format(event_.name, timeout), 'EventTimedOut'

            event_.disconnect(send)
            return format_result(result)

        tag(wrapper, 'action')
        wrapper.__arg_names = arg_names
        wrapper.__event_name = event_.name
        return wrapper
Пример #4
0
    def _event(func):
        arg_names = get_function_arg_names(func)
        if not arg_names or (arg_names[0] == 'self' and len(arg_names) < 2):
            raise InvalidApi('Event action has too few parameters. '
                             'There must be at least one parameter to receive data from the event.')

        @wraps(func)
        def wrapper(*args, **kwargs):
            result = [('Getting event {0} timed out at {1} seconds'.format(event_.name, timeout), 'EventTimedOut')]
            await_result_condition = Condition()

            @event_.connect
            def send(data):
                await_result_condition.acquire()
                if len(kwargs) > 0:
                    result.append(func(args[0], data, **kwargs))
                else:
                    result.append(func(args[0], data))
                await_result_condition.notify()
                await_result_condition.release()

            await_result_condition.acquire()
            while not len(result) >= 2:
                await_result_condition.wait(timeout=timeout)
                break
            await_result_condition.release()

            event_.disconnect(send)
            return format_result(result[-1])

        tag(wrapper, 'action')
        wrapper.__arg_names = arg_names
        wrapper.__event_name = event_.name
        return wrapper
Пример #5
0
def validate_actions(actions, dereferencer, app_name):
    from apps import get_all_actions_for_app, get_app_action
    defined_actions = get_all_actions_for_app(app_name)
    seen = set()
    for action_name, action in actions.items():
        if action['run'] not in defined_actions:
            raise InvalidApi('Action {0} has "run" property {1} '
                             'which is not defined in App {2}'.format(
                                 action_name, action['run'], app_name))
        action = dereferencer(action)
        action_params = dereferencer(action.get('parameters', []))
        event = action.get('event', '')
        if action_params:
            validate_action_params(action_params,
                                   dereferencer,
                                   app_name,
                                   action_name,
                                   get_app_action(app_name, action['run']),
                                   event=event)
        validate_app_action_return_codes(action.get('returns', []), app_name,
                                         action_name)
        seen.add(action['run'])
    if seen != set(defined_actions.keys()):
        logger.warning(
            'App {0} has defined the following actions which do not have a corresponding API: '
            '{1}'.format(app_name, (set(defined_actions.keys()) - seen)))
Пример #6
0
def validate_condition_transform_params(spec, app_name, action_type,
                                        defined_actions, dereferencer):
    from apps import get_transform, get_condition
    seen = set()
    for action_name, action in spec.items():
        action = dereferencer(action)
        action_params = dereferencer(action.get('parameters', []))
        if action['run'] not in defined_actions:
            raise InvalidApi('{0} action {1} has a "run" param {2} '
                             'which is not defined'.format(
                                 action_type, action_name, action['run']))

        data_in_param_name = action['data_in']
        validate_data_in_param(
            action_params, data_in_param_name,
            '{0} action {1}'.format(action_type, action_name))
        function = get_condition(
            app_name,
            action['run']) if action_type == 'Condition' else get_transform(
                app_name, action['run'])
        validate_action_params(action_params, dereferencer, action_type,
                               action_name, function)
        seen.add(action['run'])

    if seen != set(defined_actions):
        logger.warning(
            'Global {0}s have defined the following actions which do not have a corresponding API: '
            '{1}'.format(action_type.lower(), (set(defined_actions) - seen)))
Пример #7
0
def validate_app_action_return_codes(return_codes, app, action):
    reserved = [
        return_code for return_code in return_codes
        if return_code in reserved_return_codes
    ]
    if reserved:
        message = 'App {0} action {1} has return codes {2} which are reserved'.format(
            app, action, reserved)
        logger.error(message)
        raise InvalidApi(message)
Пример #8
0
def dereference(reference, spec, seen, message_prefix):
    if reference in seen:
        raise InvalidApi(
            '{0}: Improper reference path "{1}". Circular reference detected'.
            format(message_prefix, reference))
    seen.add(reference)
    reference_path = reference.split('/')
    if not reference_path or not reference_path[0] == '#' or len(
            reference_path) == 1:
        raise InvalidApi('{0}: Improperly formatted reference path "{1}". '
                         'Proper format is "#/path/to/reference.'.format(
                             message_prefix, reference))
    working_schema = spec
    for path_element in reference_path[1:]:
        try:
            working_schema = working_schema[path_element]
        except KeyError:
            raise InvalidApi('{0}: Improper reference path "{1}". '
                             'Path element "{2}" not found'.format(
                                 message_prefix, reference, path_element))
    return working_schema
Пример #9
0
def convert_json(spec, param_in, message_prefix):
    if 'type' in spec:
        parameter_type = spec['type']
        if parameter_type in TYPE_MAP:
            try:
                return convert_primitive_type(param_in, parameter_type)
            except ValueError:
                message = (
                    '{0} has invalid input. '
                    'Input {1} could not be converted to type {2}'.format(message_prefix, param_in, parameter_type))
                logger.error(message)
                raise InvalidInput(message)
        elif parameter_type == 'array':
            return convert_array(spec, param_in, message_prefix)
        elif parameter_type == 'object':
            return __convert_json(spec, param_in, message_prefix)
        else:
            raise InvalidApi('{0} has invalid api'.format(message_prefix))
    elif 'schema' in spec:
        return convert_json(spec['schema'], param_in, message_prefix)
    else:
        raise InvalidApi('{0} has invalid api'.format(message_prefix))
Пример #10
0
def validate_definition(definition, dereferencer, definition_name=None):
    definition = dereferencer(definition)

    if 'allOf' in definition:
        for inner_definition in definition['allOf']:
            validate_definition(inner_definition, dereferencer)
    else:
        required = definition.get('required', [])
        properties = definition.get('properties', {}).keys()
        extra_properties = list(set(required) - set(properties))
        if extra_properties:
            raise InvalidApi("Required list of properties for definition "
                             "{0} not defined: {1}".format(definition_name, extra_properties))
Пример #11
0
def validate_flagfilter_params(spec, action_type, defined_actions, dereferencer):
    seen = set()
    for action_name, action in spec.items():
        action = dereferencer(action)
        action_params = dereferencer(action.get('parameters', []))
        if action['run'] not in defined_actions:
            raise InvalidApi('{0} action {1} has a "run" param {2} '
                             'which is not defined'.format(action_type, action_name, action['run']))

        data_in_param_name = action['dataIn']
        validate_data_in_param(action_params, data_in_param_name, '{0} action {1}'.format(action_type, action_name))
        validate_action_params(action_params, dereferencer, action_type, action_name, defined_actions[action['run']])
        seen.add(action['run'])

    if seen != set(defined_actions.keys()):
        logger.warning('Global {0}s have defined the following actions which do not have a corresponding API: '
                       '{1}'.format(action_type.lower(), (set(defined_actions.keys()) - seen)))