Test Failed
Push — master ( e380d0...f5671d )
by W
02:58
created

st2common/st2common/validators/api/action.py (1 issue)

1
# Licensed to the StackStorm, Inc ('StackStorm') under one or more
2
# contributor license agreements.  See the NOTICE file distributed with
3
# this work for additional information regarding copyright ownership.
4
# The ASF licenses this file to You under the Apache License, Version 2.0
5
# (the "License"); you may not use this file except in compliance with
6
# the License.  You may obtain a copy of the License at
7
#
8
#     http://www.apache.org/licenses/LICENSE-2.0
9
#
10
# Unless required by applicable law or agreed to in writing, software
11
# distributed under the License is distributed on an "AS IS" BASIS,
12
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
# See the License for the specific language governing permissions and
14
# limitations under the License.
15
16
from __future__ import absolute_import
17
import six
18
19
from st2common.exceptions.apivalidation import ValueValidationException
20
from st2common.exceptions.db import StackStormDBObjectNotFoundError
21
from st2common import log as logging
22
from st2common.util.action_db import get_runnertype_by_name
23
from st2common.util import schema as util_schema
24
from st2common.content.utils import get_packs_base_paths
25
from st2common.content.utils import check_pack_content_directory_exists
26
from st2common.models.system.common import ResourceReference
27
from six.moves import range
0 ignored issues
show
Bug Best Practice introduced by
This seems to re-define the built-in range.

It is generally discouraged to redefine built-ins as this makes code very hard to read.

Loading history...
28
29
30
LOG = logging.getLogger(__name__)
31
32
33
def validate_action(action_api):
34
    runner_db = _get_runner_model(action_api)
35
36
    # Check if pack is valid.
37
    if not _is_valid_pack(action_api.pack):
38
        packs_base_paths = get_packs_base_paths()
39
        packs_base_paths = ','.join(packs_base_paths)
40
        msg = ('Content pack "%s" is not found or doesn\'t contain actions directory. '
41
               'Searched in: %s' %
42
               (action_api.pack, packs_base_paths))
43
        raise ValueValidationException(msg)
44
45
    # Check if parameters defined are valid.
46
    action_ref = ResourceReference.to_string_reference(pack=action_api.pack, name=action_api.name)
47
    _validate_parameters(action_ref, action_api.parameters, runner_db.runner_parameters)
48
49
50
def _get_runner_model(action_api):
51
    runner_db = None
52
    # Check if runner exists.
53
    try:
54
        runner_db = get_runnertype_by_name(action_api.runner_type)
55
    except StackStormDBObjectNotFoundError:
56
        msg = 'RunnerType %s is not found.' % action_api.runner_type
57
        raise ValueValidationException(msg)
58
    return runner_db
59
60
61
def _is_valid_pack(pack):
62
    return check_pack_content_directory_exists(pack=pack, content_type='actions')
63
64
65
def _validate_parameters(action_ref, action_params=None, runner_params=None):
66
    position_params = {}
67
    for action_param, action_param_meta in six.iteritems(action_params):
68
        # Check if overridden runner parameters are permitted.
69
        if action_param in runner_params:
70
            for action_param_attr, value in six.iteritems(action_param_meta):
71
                util_schema.validate_runner_parameter_attribute_override(
72
                    action_ref, action_param, action_param_attr,
73
                    value, runner_params[action_param].get(action_param_attr))
74
75
        if 'position' in action_param_meta:
76
            pos = action_param_meta['position']
77
            param = position_params.get(pos, None)
78
            if param:
79
                msg = ('Parameters %s and %s have same position %d.' % (action_param, param, pos) +
80
                       ' Position values have to be unique.')
81
                raise ValueValidationException(msg)
82
            else:
83
                position_params[pos] = action_param
84
85
        if 'immutable' in action_param_meta:
86
            if action_param in runner_params:
87
                runner_param_meta = runner_params[action_param]
88
                if 'immutable' in runner_param_meta:
89
                    msg = 'Param %s is declared immutable in runner. ' % action_param + \
90
                          'Cannot override in action.'
91
                    raise ValueValidationException(msg)
92
                if 'default' not in action_param_meta and 'default' not in runner_param_meta:
93
                    msg = 'Immutable param %s requires a default value.' % action_param
94
                    raise ValueValidationException(msg)
95
            else:
96
                if 'default' not in action_param_meta:
97
                    msg = 'Immutable param %s requires a default value.' % action_param
98
                    raise ValueValidationException(msg)
99
100
    return _validate_position_values_contiguous(position_params)
101
102
103
def _validate_position_values_contiguous(position_params):
104
    if not position_params:
105
        return True
106
107
    positions = sorted(position_params.keys())
108
    contiguous = (positions == list(range(min(positions), max(positions) + 1)))
109
110
    if not contiguous:
111
        msg = 'Positions supplied %s for parameters are not contiguous.' % positions
112
        raise ValueValidationException(msg)
113
114
    return True
115