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
|
|||
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 |
It is generally discouraged to redefine built-ins as this makes code very hard to read.