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 | |||
18 | import six |
||
19 | import mock |
||
20 | |||
21 | from action_chain_runner import action_chain_runner as acr |
||
22 | from st2common.constants.action import LIVEACTION_STATUS_RUNNING |
||
23 | from st2common.constants.action import LIVEACTION_STATUS_SUCCEEDED |
||
24 | from st2common.constants.action import LIVEACTION_STATUS_CANCELED |
||
25 | from st2common.constants.action import LIVEACTION_STATUS_TIMED_OUT |
||
26 | from st2common.constants.action import LIVEACTION_STATUS_FAILED |
||
27 | from st2common.exceptions import actionrunner as runnerexceptions |
||
28 | from st2common.models.api.notification import NotificationsHelper |
||
29 | from st2common.models.db.liveaction import LiveActionDB |
||
30 | from st2common.models.db.keyvalue import KeyValuePairDB |
||
31 | from st2common.models.system.common import ResourceReference |
||
32 | from st2common.persistence.keyvalue import KeyValuePair |
||
33 | from st2common.persistence.runner import RunnerType |
||
34 | from st2common.services import action as action_service |
||
35 | from st2common.util import action_db as action_db_util |
||
36 | from st2common.exceptions.action import ParameterRenderingFailedException |
||
37 | from st2tests import DbTestCase |
||
38 | from st2tests.fixturesloader import FixturesLoader |
||
39 | |||
40 | |||
41 | class DummyActionExecution(object): |
||
42 | def __init__(self, status=LIVEACTION_STATUS_SUCCEEDED, result=''): |
||
43 | self.id = None |
||
44 | self.status = status |
||
45 | self.result = result |
||
46 | |||
47 | |||
48 | FIXTURES_PACK = 'generic' |
||
49 | |||
50 | TEST_MODELS = { |
||
51 | 'actions': ['a1.yaml', 'a2.yaml', 'action_4_action_context_param.yaml'], |
||
52 | 'runners': ['testrunner1.yaml'] |
||
53 | } |
||
54 | |||
55 | MODELS = FixturesLoader().load_models(fixtures_pack=FIXTURES_PACK, |
||
56 | fixtures_dict=TEST_MODELS) |
||
57 | ACTION_1 = MODELS['actions']['a1.yaml'] |
||
58 | ACTION_2 = MODELS['actions']['a2.yaml'] |
||
59 | ACTION_3 = MODELS['actions']['action_4_action_context_param.yaml'] |
||
60 | RUNNER = MODELS['runners']['testrunner1.yaml'] |
||
61 | |||
62 | CHAIN_1_PATH = FixturesLoader().get_fixture_file_path_abs( |
||
63 | FIXTURES_PACK, 'actionchains', 'chain1.yaml') |
||
64 | CHAIN_2_PATH = FixturesLoader().get_fixture_file_path_abs( |
||
65 | FIXTURES_PACK, 'actionchains', 'chain2.yaml') |
||
66 | CHAIN_ACTION_CALL_NO_PARAMS_PATH = FixturesLoader().get_fixture_file_path_abs( |
||
67 | FIXTURES_PACK, 'actionchains', 'chain_action_call_no_params.yaml') |
||
68 | CHAIN_NO_DEFAULT = FixturesLoader().get_fixture_file_path_abs( |
||
69 | FIXTURES_PACK, 'actionchains', 'no_default_chain.yaml') |
||
70 | CHAIN_NO_DEFAULT_2 = FixturesLoader().get_fixture_file_path_abs( |
||
71 | FIXTURES_PACK, 'actionchains', 'no_default_chain_2.yaml') |
||
72 | CHAIN_BAD_DEFAULT = FixturesLoader().get_fixture_file_path_abs( |
||
73 | FIXTURES_PACK, 'actionchains', 'bad_default_chain.yaml') |
||
74 | CHAIN_BROKEN_ON_SUCCESS_PATH_STATIC_TASK_NAME = FixturesLoader().get_fixture_file_path_abs( |
||
75 | FIXTURES_PACK, 'actionchains', 'chain_broken_on_success_path_static_task_name.yaml') |
||
76 | CHAIN_BROKEN_ON_FAILURE_PATH_STATIC_TASK_NAME = FixturesLoader().get_fixture_file_path_abs( |
||
77 | FIXTURES_PACK, 'actionchains', 'chain_broken_on_failure_path_static_task_name.yaml') |
||
78 | CHAIN_FIRST_TASK_RENDER_FAIL_PATH = FixturesLoader().get_fixture_file_path_abs( |
||
79 | FIXTURES_PACK, 'actionchains', 'chain_first_task_parameter_render_fail.yaml') |
||
80 | CHAIN_SECOND_TASK_RENDER_FAIL_PATH = FixturesLoader().get_fixture_file_path_abs( |
||
81 | FIXTURES_PACK, 'actionchains', 'chain_second_task_parameter_render_fail.yaml') |
||
82 | CHAIN_LIST_TEMP_PATH = FixturesLoader().get_fixture_file_path_abs( |
||
83 | FIXTURES_PACK, 'actionchains', 'chain_list_template.yaml') |
||
84 | CHAIN_DICT_TEMP_PATH = FixturesLoader().get_fixture_file_path_abs( |
||
85 | FIXTURES_PACK, 'actionchains', 'chain_dict_template.yaml') |
||
86 | CHAIN_DEP_INPUT = FixturesLoader().get_fixture_file_path_abs( |
||
87 | FIXTURES_PACK, 'actionchains', 'chain_dependent_input.yaml') |
||
88 | CHAIN_DEP_RESULTS_INPUT = FixturesLoader().get_fixture_file_path_abs( |
||
89 | FIXTURES_PACK, 'actionchains', 'chain_dep_result_input.yaml') |
||
90 | MALFORMED_CHAIN_PATH = FixturesLoader().get_fixture_file_path_abs( |
||
91 | FIXTURES_PACK, 'actionchains', 'malformedchain.yaml') |
||
92 | CHAIN_TYPED_PARAMS = FixturesLoader().get_fixture_file_path_abs( |
||
93 | FIXTURES_PACK, 'actionchains', 'chain_typed_params.yaml') |
||
94 | CHAIN_SYSTEM_PARAMS = FixturesLoader().get_fixture_file_path_abs( |
||
95 | FIXTURES_PACK, 'actionchains', 'chain_typed_system_params.yaml') |
||
96 | CHAIN_WITH_ACTIONPARAM_VARS = FixturesLoader().get_fixture_file_path_abs( |
||
97 | FIXTURES_PACK, 'actionchains', 'chain_with_actionparam_vars.yaml') |
||
98 | CHAIN_WITH_SYSTEM_VARS = FixturesLoader().get_fixture_file_path_abs( |
||
99 | FIXTURES_PACK, 'actionchains', 'chain_with_system_vars.yaml') |
||
100 | CHAIN_WITH_PUBLISH = FixturesLoader().get_fixture_file_path_abs( |
||
101 | FIXTURES_PACK, 'actionchains', 'chain_with_publish.yaml') |
||
102 | CHAIN_WITH_PUBLISH_2 = FixturesLoader().get_fixture_file_path_abs( |
||
103 | FIXTURES_PACK, 'actionchains', 'chain_with_publish_2.yaml') |
||
104 | CHAIN_WITH_PUBLISH_PARAM_RENDERING_FAILURE = FixturesLoader().get_fixture_file_path_abs( |
||
105 | FIXTURES_PACK, 'actionchains', 'chain_publish_params_rendering_failure.yaml') |
||
106 | CHAIN_WITH_INVALID_ACTION = FixturesLoader().get_fixture_file_path_abs( |
||
107 | FIXTURES_PACK, 'actionchains', 'chain_with_invalid_action.yaml') |
||
108 | CHAIN_ACTION_PARAMS_AND_PARAMETERS_ATTRIBUTE = FixturesLoader().get_fixture_file_path_abs( |
||
109 | FIXTURES_PACK, 'actionchains', 'chain_action_params_and_parameters.yaml') |
||
110 | CHAIN_ACTION_PARAMS_ATTRIBUTE = FixturesLoader().get_fixture_file_path_abs( |
||
111 | FIXTURES_PACK, 'actionchains', 'chain_action_params_attribute.yaml') |
||
112 | CHAIN_ACTION_PARAMETERS_ATTRIBUTE = FixturesLoader().get_fixture_file_path_abs( |
||
113 | FIXTURES_PACK, 'actionchains', 'chain_action_parameters_attribute.yaml') |
||
114 | CHAIN_ACTION_INVALID_PARAMETER_TYPE = FixturesLoader().get_fixture_file_path_abs( |
||
115 | FIXTURES_PACK, 'actionchains', 'chain_invalid_parameter_type_passed_to_action.yaml') |
||
116 | |||
117 | CHAIN_NOTIFY_API = {'notify': {'on-complete': {'message': 'foo happened.'}}} |
||
118 | CHAIN_NOTIFY_DB = NotificationsHelper.to_model(CHAIN_NOTIFY_API) |
||
119 | |||
120 | |||
121 | @mock.patch.object( |
||
122 | action_db_util, |
||
123 | 'get_runnertype_by_name', |
||
124 | mock.MagicMock(return_value=RUNNER)) |
||
125 | @mock.patch.object( |
||
126 | action_service, |
||
127 | 'is_action_canceled_or_canceling', |
||
128 | mock.MagicMock(return_value=False)) |
||
129 | @mock.patch.object( |
||
130 | action_service, |
||
131 | 'is_action_paused_or_pausing', |
||
132 | mock.MagicMock(return_value=False)) |
||
133 | class TestActionChainRunner(DbTestCase): |
||
134 | |||
135 | def test_runner_creation(self): |
||
136 | runner = acr.get_runner() |
||
137 | self.assertTrue(runner) |
||
138 | self.assertTrue(runner.runner_id) |
||
139 | |||
140 | def test_malformed_chain(self): |
||
141 | try: |
||
142 | chain_runner = acr.get_runner() |
||
143 | chain_runner.entry_point = MALFORMED_CHAIN_PATH |
||
144 | chain_runner.action = ACTION_1 |
||
145 | chain_runner.pre_run() |
||
146 | self.assertTrue(False, 'Expected pre_run to fail.') |
||
147 | except runnerexceptions.ActionRunnerPreRunError: |
||
148 | self.assertTrue(True) |
||
149 | |||
150 | @mock.patch.object(action_db_util, 'get_action_by_ref', |
||
151 | mock.MagicMock(return_value=ACTION_1)) |
||
152 | @mock.patch.object(action_service, 'request', return_value=(DummyActionExecution(), None)) |
||
153 | def test_chain_runner_success_path(self, request): |
||
154 | chain_runner = acr.get_runner() |
||
155 | chain_runner.entry_point = CHAIN_1_PATH |
||
156 | chain_runner.action = ACTION_1 |
||
157 | action_ref = ResourceReference.to_string_reference(name=ACTION_1.name, pack=ACTION_1.pack) |
||
158 | chain_runner.liveaction = LiveActionDB(action=action_ref) |
||
159 | chain_runner.liveaction.notify = CHAIN_NOTIFY_DB |
||
160 | chain_runner.pre_run() |
||
161 | chain_runner.run({}) |
||
162 | self.assertNotEqual(chain_runner.chain_holder.actionchain, None) |
||
163 | # based on the chain the callcount is known to be 3. Not great but works. |
||
164 | self.assertEqual(request.call_count, 3) |
||
165 | |||
166 | @mock.patch.object(action_db_util, 'get_action_by_ref', |
||
167 | mock.MagicMock(return_value=ACTION_1)) |
||
168 | @mock.patch.object(action_service, 'request', return_value=(DummyActionExecution(), None)) |
||
169 | def test_chain_runner_chain_second_task_times_out(self, request): |
||
170 | # Second task in the chain times out so the action chain status should be timeout |
||
171 | chain_runner = acr.get_runner() |
||
172 | chain_runner.entry_point = CHAIN_2_PATH |
||
173 | chain_runner.action = ACTION_1 |
||
174 | |||
175 | original_run_action = chain_runner._run_action |
||
0 ignored issues
–
show
|
|||
176 | |||
177 | def mock_run_action(*args, **kwargs): |
||
178 | original_live_action = args[0] |
||
179 | liveaction = original_run_action(*args, **kwargs) |
||
180 | if original_live_action.action == 'wolfpack.a2': |
||
181 | # Mock a timeout for second task |
||
182 | liveaction.status = LIVEACTION_STATUS_TIMED_OUT |
||
183 | return liveaction |
||
184 | |||
185 | chain_runner._run_action = mock_run_action |
||
0 ignored issues
–
show
It seems like
_run_action was declared protected and should not be accessed from this context.
Prefixing a member variable class MyParent:
def __init__(self):
self._x = 1;
self.y = 2;
class MyChild(MyParent):
def some_method(self):
return self._x # Ok, since accessed from a child class
class AnotherClass:
def some_method(self, instance_of_my_child):
return instance_of_my_child._x # Would be flagged as AnotherClass is not
# a child class of MyParent
Loading history...
|
|||
186 | action_ref = ResourceReference.to_string_reference(name=ACTION_1.name, pack=ACTION_1.pack) |
||
187 | chain_runner.liveaction = LiveActionDB(action=action_ref) |
||
188 | chain_runner.pre_run() |
||
189 | status, _, _ = chain_runner.run({}) |
||
190 | |||
191 | self.assertEqual(status, LIVEACTION_STATUS_TIMED_OUT) |
||
192 | self.assertNotEqual(chain_runner.chain_holder.actionchain, None) |
||
193 | # based on the chain the callcount is known to be 3. Not great but works. |
||
194 | self.assertEqual(request.call_count, 3) |
||
195 | |||
196 | @mock.patch.object(action_db_util, 'get_action_by_ref', |
||
197 | mock.MagicMock(return_value=ACTION_1)) |
||
198 | @mock.patch.object(action_service, 'request', return_value=(DummyActionExecution(), None)) |
||
199 | def test_chain_runner_task_is_canceled_while_running(self, request): |
||
200 | # Second task in the action is CANCELED, make sure runner doesn't get stuck in an infinite |
||
201 | # loop |
||
202 | chain_runner = acr.get_runner() |
||
203 | chain_runner.entry_point = CHAIN_2_PATH |
||
204 | chain_runner.action = ACTION_1 |
||
205 | |||
206 | original_run_action = chain_runner._run_action |
||
0 ignored issues
–
show
It seems like
_run_action was declared protected and should not be accessed from this context.
Prefixing a member variable class MyParent:
def __init__(self):
self._x = 1;
self.y = 2;
class MyChild(MyParent):
def some_method(self):
return self._x # Ok, since accessed from a child class
class AnotherClass:
def some_method(self, instance_of_my_child):
return instance_of_my_child._x # Would be flagged as AnotherClass is not
# a child class of MyParent
Loading history...
|
|||
207 | |||
208 | def mock_run_action(*args, **kwargs): |
||
209 | original_live_action = args[0] |
||
210 | if original_live_action.action == 'wolfpack.a2': |
||
211 | status = LIVEACTION_STATUS_CANCELED |
||
212 | else: |
||
213 | status = LIVEACTION_STATUS_SUCCEEDED |
||
214 | request.return_value = (DummyActionExecution(status=status), None) |
||
215 | liveaction = original_run_action(*args, **kwargs) |
||
216 | return liveaction |
||
217 | |||
218 | chain_runner._run_action = mock_run_action |
||
0 ignored issues
–
show
It seems like
_run_action was declared protected and should not be accessed from this context.
Prefixing a member variable class MyParent:
def __init__(self):
self._x = 1;
self.y = 2;
class MyChild(MyParent):
def some_method(self):
return self._x # Ok, since accessed from a child class
class AnotherClass:
def some_method(self, instance_of_my_child):
return instance_of_my_child._x # Would be flagged as AnotherClass is not
# a child class of MyParent
Loading history...
|
|||
219 | action_ref = ResourceReference.to_string_reference(name=ACTION_1.name, pack=ACTION_1.pack) |
||
220 | chain_runner.liveaction = LiveActionDB(action=action_ref) |
||
221 | chain_runner.pre_run() |
||
222 | status, _, _ = chain_runner.run({}) |
||
223 | |||
224 | self.assertEqual(status, LIVEACTION_STATUS_CANCELED) |
||
225 | self.assertNotEqual(chain_runner.chain_holder.actionchain, None) |
||
226 | # Chain count should be 2 since the last task doesn't get called since the second one was |
||
227 | # canceled |
||
228 | self.assertEqual(request.call_count, 2) |
||
229 | |||
230 | @mock.patch.object(action_db_util, 'get_action_by_ref', |
||
231 | mock.MagicMock(return_value=ACTION_1)) |
||
232 | @mock.patch.object(action_service, 'request', return_value=(DummyActionExecution(), None)) |
||
233 | def test_chain_runner_success_task_action_call_with_no_params(self, request): |
||
234 | # Make sure that the runner doesn't explode if task definition contains |
||
235 | # no "params" section |
||
236 | chain_runner = acr.get_runner() |
||
237 | chain_runner.entry_point = CHAIN_ACTION_CALL_NO_PARAMS_PATH |
||
238 | chain_runner.action = ACTION_1 |
||
239 | action_ref = ResourceReference.to_string_reference(name=ACTION_1.name, pack=ACTION_1.pack) |
||
240 | chain_runner.liveaction = LiveActionDB(action=action_ref) |
||
241 | chain_runner.liveaction.notify = CHAIN_NOTIFY_DB |
||
242 | chain_runner.pre_run() |
||
243 | chain_runner.run({}) |
||
244 | self.assertNotEqual(chain_runner.chain_holder.actionchain, None) |
||
245 | # based on the chain the callcount is known to be 3. Not great but works. |
||
246 | self.assertEqual(request.call_count, 3) |
||
247 | |||
248 | @mock.patch.object(action_db_util, 'get_action_by_ref', |
||
249 | mock.MagicMock(return_value=ACTION_1)) |
||
250 | @mock.patch.object(action_service, 'request', return_value=(DummyActionExecution(), None)) |
||
251 | def test_chain_runner_no_default(self, request): |
||
252 | chain_runner = acr.get_runner() |
||
253 | chain_runner.entry_point = CHAIN_NO_DEFAULT |
||
254 | chain_runner.action = ACTION_1 |
||
255 | action_ref = ResourceReference.to_string_reference(name=ACTION_1.name, pack=ACTION_1.pack) |
||
256 | chain_runner.liveaction = LiveActionDB(action=action_ref) |
||
257 | chain_runner.pre_run() |
||
258 | chain_runner.run({}) |
||
259 | self.assertNotEqual(chain_runner.chain_holder.actionchain, None) |
||
260 | # In case of this chain default_node is the first_node. |
||
261 | default_node = chain_runner.chain_holder.actionchain.default |
||
262 | first_node = chain_runner.chain_holder.actionchain.chain[0] |
||
263 | self.assertEqual(default_node, first_node.name) |
||
264 | # based on the chain the callcount is known to be 3. Not great but works. |
||
265 | self.assertEqual(request.call_count, 3) |
||
266 | |||
267 | @mock.patch.object(action_db_util, 'get_action_by_ref', |
||
268 | mock.MagicMock(return_value=ACTION_1)) |
||
269 | @mock.patch.object(action_service, 'request', return_value=(DummyActionExecution(), None)) |
||
270 | def test_chain_runner_no_default_multiple_options(self, request): |
||
271 | # subtle difference is that when there are multiple possible default nodes |
||
272 | # the order per chain definition may not be preseved. This is really a |
||
273 | # poorly formatted chain but we still the best attempt to work. |
||
274 | chain_runner = acr.get_runner() |
||
275 | chain_runner.entry_point = CHAIN_NO_DEFAULT_2 |
||
276 | chain_runner.action = ACTION_1 |
||
277 | action_ref = ResourceReference.to_string_reference(name=ACTION_1.name, pack=ACTION_1.pack) |
||
278 | chain_runner.liveaction = LiveActionDB(action=action_ref) |
||
279 | chain_runner.pre_run() |
||
280 | chain_runner.run({}) |
||
281 | self.assertNotEqual(chain_runner.chain_holder.actionchain, None) |
||
282 | # In case of this chain default_node is the first_node. |
||
283 | default_node = chain_runner.chain_holder.actionchain.default |
||
284 | first_node = chain_runner.chain_holder.actionchain.chain[0] |
||
285 | self.assertEqual(default_node, first_node.name) |
||
286 | # based on the chain the callcount is known to be 2. |
||
287 | self.assertEqual(request.call_count, 2) |
||
288 | |||
289 | @mock.patch.object(action_db_util, 'get_action_by_ref', |
||
290 | mock.MagicMock(return_value=ACTION_1)) |
||
291 | @mock.patch.object(action_service, 'request', return_value=(DummyActionExecution(), None)) |
||
292 | def test_chain_runner_bad_default(self, request): |
||
293 | chain_runner = acr.get_runner() |
||
294 | chain_runner.entry_point = CHAIN_BAD_DEFAULT |
||
295 | chain_runner.action = ACTION_1 |
||
296 | expected_msg = 'Unable to find node with name "bad_default" referenced in "default".' |
||
297 | self.assertRaisesRegexp(runnerexceptions.ActionRunnerPreRunError, |
||
298 | expected_msg, chain_runner.pre_run) |
||
299 | |||
300 | @mock.patch('eventlet.sleep', mock.MagicMock()) |
||
301 | @mock.patch.object(action_db_util, 'get_liveaction_by_id', mock.MagicMock( |
||
302 | return_value=DummyActionExecution())) |
||
303 | @mock.patch.object(action_db_util, 'get_action_by_ref', |
||
304 | mock.MagicMock(return_value=ACTION_1)) |
||
305 | @mock.patch.object(action_service, 'request', |
||
306 | return_value=(DummyActionExecution(status=LIVEACTION_STATUS_RUNNING), None)) |
||
307 | def test_chain_runner_success_path_with_wait(self, request): |
||
308 | chain_runner = acr.get_runner() |
||
309 | chain_runner.entry_point = CHAIN_1_PATH |
||
310 | chain_runner.action = ACTION_1 |
||
311 | action_ref = ResourceReference.to_string_reference(name=ACTION_1.name, pack=ACTION_1.pack) |
||
312 | chain_runner.liveaction = LiveActionDB(action=action_ref) |
||
313 | chain_runner.pre_run() |
||
314 | chain_runner.run({}) |
||
315 | self.assertNotEqual(chain_runner.chain_holder.actionchain, None) |
||
316 | # based on the chain the callcount is known to be 3. Not great but works. |
||
317 | self.assertEqual(request.call_count, 3) |
||
318 | |||
319 | @mock.patch.object(action_db_util, 'get_action_by_ref', |
||
320 | mock.MagicMock(return_value=ACTION_1)) |
||
321 | @mock.patch.object(action_service, 'request', |
||
322 | return_value=(DummyActionExecution(status=LIVEACTION_STATUS_FAILED), None)) |
||
323 | def test_chain_runner_failure_path(self, request): |
||
324 | chain_runner = acr.get_runner() |
||
325 | chain_runner.entry_point = CHAIN_1_PATH |
||
326 | chain_runner.action = ACTION_1 |
||
327 | action_ref = ResourceReference.to_string_reference(name=ACTION_1.name, pack=ACTION_1.pack) |
||
328 | chain_runner.liveaction = LiveActionDB(action=action_ref) |
||
329 | chain_runner.pre_run() |
||
330 | status, _, _ = chain_runner.run({}) |
||
331 | self.assertEqual(status, LIVEACTION_STATUS_FAILED) |
||
332 | self.assertNotEqual(chain_runner.chain_holder.actionchain, None) |
||
333 | # based on the chain the callcount is known to be 2. Not great but works. |
||
334 | self.assertEqual(request.call_count, 2) |
||
335 | |||
336 | @mock.patch.object(action_db_util, 'get_action_by_ref', |
||
337 | mock.MagicMock(return_value=ACTION_1)) |
||
338 | @mock.patch.object(action_service, 'request', |
||
339 | return_value=(DummyActionExecution(), None)) |
||
340 | def test_chain_runner_broken_on_success_path_static_task_name(self, request): |
||
341 | chain_runner = acr.get_runner() |
||
342 | chain_runner.entry_point = CHAIN_BROKEN_ON_SUCCESS_PATH_STATIC_TASK_NAME |
||
343 | chain_runner.action = ACTION_1 |
||
344 | |||
345 | expected_msg = ('Unable to find node with name "c5" referenced in "on-success" ' |
||
346 | 'in task "c2"') |
||
347 | self.assertRaisesRegexp(runnerexceptions.ActionRunnerPreRunError, |
||
348 | expected_msg, chain_runner.pre_run) |
||
349 | |||
350 | @mock.patch.object(action_db_util, 'get_action_by_ref', |
||
351 | mock.MagicMock(return_value=ACTION_1)) |
||
352 | @mock.patch.object(action_service, 'request', |
||
353 | return_value=(DummyActionExecution(), None)) |
||
354 | def test_chain_runner_broken_on_failure_path_static_task_name(self, request): |
||
355 | chain_runner = acr.get_runner() |
||
356 | chain_runner.entry_point = CHAIN_BROKEN_ON_FAILURE_PATH_STATIC_TASK_NAME |
||
357 | chain_runner.action = ACTION_1 |
||
358 | |||
359 | expected_msg = ('Unable to find node with name "c6" referenced in "on-failure" ' |
||
360 | 'in task "c2"') |
||
361 | self.assertRaisesRegexp(runnerexceptions.ActionRunnerPreRunError, |
||
362 | expected_msg, chain_runner.pre_run) |
||
363 | |||
364 | @mock.patch.object(action_db_util, 'get_action_by_ref', |
||
365 | mock.MagicMock(return_value=ACTION_1)) |
||
366 | @mock.patch.object(action_service, 'request', side_effect=RuntimeError('Test Failure.')) |
||
367 | def test_chain_runner_action_exception(self, request): |
||
368 | chain_runner = acr.get_runner() |
||
369 | chain_runner.entry_point = CHAIN_1_PATH |
||
370 | chain_runner.action = ACTION_1 |
||
371 | action_ref = ResourceReference.to_string_reference(name=ACTION_1.name, pack=ACTION_1.pack) |
||
372 | chain_runner.liveaction = LiveActionDB(action=action_ref) |
||
373 | chain_runner.pre_run() |
||
374 | status, results, _ = chain_runner.run({}) |
||
375 | self.assertEqual(status, LIVEACTION_STATUS_FAILED) |
||
376 | self.assertNotEqual(chain_runner.chain_holder.actionchain, None) |
||
377 | |||
378 | # based on the chain the callcount is known to be 2. Not great but works. |
||
379 | self.assertEqual(request.call_count, 2) |
||
380 | |||
381 | error_count = 0 |
||
382 | for task_result in results['tasks']: |
||
383 | if task_result['result'].get('error', None): |
||
384 | error_count += 1 |
||
385 | |||
386 | self.assertEqual(error_count, 2) |
||
387 | |||
388 | @mock.patch.object(action_db_util, 'get_action_by_ref', |
||
389 | mock.MagicMock(return_value=ACTION_1)) |
||
390 | @mock.patch.object(action_service, 'request', return_value=(DummyActionExecution(), None)) |
||
391 | def test_chain_runner_str_param_temp(self, request): |
||
392 | chain_runner = acr.get_runner() |
||
393 | chain_runner.entry_point = CHAIN_FIRST_TASK_RENDER_FAIL_PATH |
||
394 | chain_runner.action = ACTION_1 |
||
395 | action_ref = ResourceReference.to_string_reference(name=ACTION_1.name, pack=ACTION_1.pack) |
||
396 | chain_runner.liveaction = LiveActionDB(action=action_ref) |
||
397 | chain_runner.pre_run() |
||
398 | chain_runner.run({'s1': 1, 's2': 2, 's3': 3, 's4': 4}) |
||
399 | self.assertNotEqual(chain_runner.chain_holder.actionchain, None) |
||
400 | mock_args, _ = request.call_args |
||
401 | self.assertEqual(mock_args[0].parameters, {"p1": "1"}) |
||
402 | |||
403 | @mock.patch.object(action_db_util, 'get_action_by_ref', |
||
404 | mock.MagicMock(return_value=ACTION_1)) |
||
405 | @mock.patch.object(action_service, 'request', return_value=(DummyActionExecution(), None)) |
||
406 | def test_chain_runner_list_param_temp(self, request): |
||
407 | chain_runner = acr.get_runner() |
||
408 | chain_runner.entry_point = CHAIN_LIST_TEMP_PATH |
||
409 | chain_runner.action = ACTION_1 |
||
410 | action_ref = ResourceReference.to_string_reference(name=ACTION_1.name, pack=ACTION_1.pack) |
||
411 | chain_runner.liveaction = LiveActionDB(action=action_ref) |
||
412 | chain_runner.pre_run() |
||
413 | chain_runner.run({'s1': 1, 's2': 2, 's3': 3, 's4': 4}) |
||
414 | self.assertNotEqual(chain_runner.chain_holder.actionchain, None) |
||
415 | mock_args, _ = request.call_args |
||
416 | self.assertEqual(mock_args[0].parameters, {"p1": "[2, 3, 4]"}) |
||
417 | |||
418 | @mock.patch.object(action_db_util, 'get_action_by_ref', |
||
419 | mock.MagicMock(return_value=ACTION_1)) |
||
420 | @mock.patch.object(action_service, 'request', return_value=(DummyActionExecution(), None)) |
||
421 | def test_chain_runner_dict_param_temp(self, request): |
||
422 | chain_runner = acr.get_runner() |
||
423 | chain_runner.entry_point = CHAIN_DICT_TEMP_PATH |
||
424 | chain_runner.action = ACTION_1 |
||
425 | action_ref = ResourceReference.to_string_reference(name=ACTION_1.name, pack=ACTION_1.pack) |
||
426 | chain_runner.liveaction = LiveActionDB(action=action_ref) |
||
427 | chain_runner.pre_run() |
||
428 | chain_runner.run({'s1': 1, 's2': 2, 's3': 3, 's4': 4}) |
||
429 | self.assertNotEqual(chain_runner.chain_holder.actionchain, None) |
||
430 | expected_value = {"p1": {"p1.3": "[3, 4]", "p1.2": "2", "p1.1": "1"}} |
||
431 | mock_args, _ = request.call_args |
||
432 | self.assertEqual(mock_args[0].parameters, expected_value) |
||
433 | |||
434 | @mock.patch.object(action_db_util, 'get_action_by_ref', |
||
435 | mock.MagicMock(return_value=ACTION_1)) |
||
436 | @mock.patch.object(action_service, 'request', |
||
437 | return_value=(DummyActionExecution(result={'o1': '1'}), None)) |
||
438 | def test_chain_runner_dependent_param_temp(self, request): |
||
439 | chain_runner = acr.get_runner() |
||
440 | chain_runner.entry_point = CHAIN_DEP_INPUT |
||
441 | chain_runner.action = ACTION_1 |
||
442 | action_ref = ResourceReference.to_string_reference(name=ACTION_1.name, pack=ACTION_1.pack) |
||
443 | chain_runner.liveaction = LiveActionDB(action=action_ref) |
||
444 | chain_runner.pre_run() |
||
445 | chain_runner.run({'s1': 1, 's2': 2, 's3': 3, 's4': 4}) |
||
446 | self.assertNotEqual(chain_runner.chain_holder.actionchain, None) |
||
447 | expected_values = [{u'p1': u'1'}, |
||
448 | {u'p1': u'1'}, |
||
449 | {u'p2': u'1', u'p3': u'1', u'p1': u'1'}] |
||
450 | # Each of the call_args must be one of |
||
451 | for call_args in request.call_args_list: |
||
452 | self.assertTrue(call_args[0][0].parameters in expected_values) |
||
453 | expected_values.remove(call_args[0][0].parameters) |
||
454 | self.assertEqual(len(expected_values), 0, 'Not all expected values received.') |
||
455 | |||
456 | @mock.patch.object(action_db_util, 'get_action_by_ref', |
||
457 | mock.MagicMock(return_value=ACTION_1)) |
||
458 | @mock.patch.object(action_service, 'request', |
||
459 | return_value=(DummyActionExecution(result={'o1': '1'}), None)) |
||
460 | def test_chain_runner_dependent_results_param(self, request): |
||
461 | chain_runner = acr.get_runner() |
||
462 | chain_runner.entry_point = CHAIN_DEP_RESULTS_INPUT |
||
463 | chain_runner.action = ACTION_1 |
||
464 | action_ref = ResourceReference.to_string_reference(name=ACTION_1.name, pack=ACTION_1.pack) |
||
465 | chain_runner.liveaction = LiveActionDB(action=action_ref) |
||
466 | chain_runner.pre_run() |
||
467 | chain_runner.run({'s1': 1}) |
||
468 | self.assertNotEqual(chain_runner.chain_holder.actionchain, None) |
||
469 | |||
470 | if six.PY2: |
||
471 | expected_values = [{u'p1': u'1'}, |
||
472 | {u'p1': u'1'}, |
||
473 | {u'out': u"{'c2': {'o1': '1'}, 'c1': {'o1': '1'}}"}] |
||
474 | else: |
||
475 | expected_values = [{'p1': '1'}, |
||
476 | {'p1': '1'}, |
||
477 | {'out': "{'c1': {'o1': '1'}, 'c2': {'o1': '1'}}"}] |
||
478 | |||
479 | # Each of the call_args must be one of |
||
480 | self.assertEqual(request.call_count, 3) |
||
481 | for call_args in request.call_args_list: |
||
482 | self.assertTrue(call_args[0][0].parameters in expected_values) |
||
483 | expected_values.remove(call_args[0][0].parameters) |
||
484 | |||
485 | self.assertEqual(len(expected_values), 0, 'Not all expected values received.') |
||
486 | |||
487 | @mock.patch.object(action_db_util, 'get_action_by_ref', |
||
488 | mock.MagicMock(return_value=ACTION_1)) |
||
489 | @mock.patch.object(RunnerType, 'get_by_name', |
||
490 | mock.MagicMock(return_value=RUNNER)) |
||
491 | @mock.patch.object(action_service, 'request', return_value=(DummyActionExecution(), None)) |
||
492 | def test_chain_runner_missing_param_temp(self, request): |
||
493 | chain_runner = acr.get_runner() |
||
494 | chain_runner.entry_point = CHAIN_FIRST_TASK_RENDER_FAIL_PATH |
||
495 | chain_runner.action = ACTION_1 |
||
496 | action_ref = ResourceReference.to_string_reference(name=ACTION_1.name, pack=ACTION_1.pack) |
||
497 | chain_runner.liveaction = LiveActionDB(action=action_ref) |
||
498 | chain_runner.pre_run() |
||
499 | chain_runner.run({}) |
||
500 | self.assertEqual(request.call_count, 0, 'No call expected.') |
||
501 | |||
502 | @mock.patch.object(action_db_util, 'get_action_by_ref', |
||
503 | mock.MagicMock(return_value=ACTION_1)) |
||
504 | @mock.patch.object(action_service, 'request', return_value=(DummyActionExecution(), None)) |
||
505 | def test_chain_runner_failure_during_param_rendering_single_task(self, request): |
||
506 | # Parameter rendering should result in a top level error which aborts |
||
507 | # the whole chain |
||
508 | chain_runner = acr.get_runner() |
||
509 | chain_runner.entry_point = CHAIN_FIRST_TASK_RENDER_FAIL_PATH |
||
510 | chain_runner.action = ACTION_1 |
||
511 | action_ref = ResourceReference.to_string_reference(name=ACTION_1.name, pack=ACTION_1.pack) |
||
512 | chain_runner.liveaction = LiveActionDB(action=action_ref) |
||
513 | chain_runner.pre_run() |
||
514 | status, result, _ = chain_runner.run({}) |
||
515 | |||
516 | # No tasks ran because rendering of parameters for the first task failed |
||
517 | self.assertEqual(status, LIVEACTION_STATUS_FAILED) |
||
518 | self.assertEqual(result['tasks'], []) |
||
519 | self.assertTrue('error' in result) |
||
520 | self.assertTrue('traceback' in result) |
||
521 | self.assertTrue('Failed to run task "c1". Parameter rendering failed' in result['error']) |
||
522 | self.assertTrue('Traceback' in result['traceback']) |
||
523 | |||
524 | @mock.patch.object(action_db_util, 'get_action_by_ref', |
||
525 | mock.MagicMock(return_value=ACTION_1)) |
||
526 | @mock.patch.object(action_service, 'request', return_value=(DummyActionExecution(), None)) |
||
527 | def test_chain_runner_failure_during_param_rendering_multiple_tasks(self, request): |
||
528 | # Parameter rendering should result in a top level error which aborts |
||
529 | # the whole chain |
||
530 | chain_runner = acr.get_runner() |
||
531 | chain_runner.entry_point = CHAIN_SECOND_TASK_RENDER_FAIL_PATH |
||
532 | chain_runner.action = ACTION_1 |
||
533 | action_ref = ResourceReference.to_string_reference(name=ACTION_1.name, pack=ACTION_1.pack) |
||
534 | chain_runner.liveaction = LiveActionDB(action=action_ref) |
||
535 | chain_runner.pre_run() |
||
536 | status, result, _ = chain_runner.run({}) |
||
537 | |||
538 | # Verify that only first task has ran |
||
539 | self.assertEqual(status, LIVEACTION_STATUS_FAILED) |
||
540 | self.assertEqual(len(result['tasks']), 1) |
||
541 | self.assertEqual(result['tasks'][0]['name'], 'c1') |
||
542 | |||
543 | expected_error = ('Failed rendering value for action parameter "p1" in ' |
||
544 | 'task "c2" (template string={{s1}}):') |
||
545 | |||
546 | self.assertTrue('error' in result) |
||
547 | self.assertTrue('traceback' in result) |
||
548 | self.assertTrue('Failed to run task "c2". Parameter rendering failed' in result['error']) |
||
549 | self.assertTrue(expected_error in result['error']) |
||
550 | self.assertTrue('Traceback' in result['traceback']) |
||
551 | |||
552 | @mock.patch.object(action_db_util, 'get_action_by_ref', |
||
553 | mock.MagicMock(return_value=ACTION_2)) |
||
554 | @mock.patch.object(action_service, 'request', return_value=(DummyActionExecution(), None)) |
||
555 | def test_chain_runner_typed_params(self, request): |
||
556 | chain_runner = acr.get_runner() |
||
557 | chain_runner.entry_point = CHAIN_TYPED_PARAMS |
||
558 | chain_runner.action = ACTION_2 |
||
559 | action_ref = ResourceReference.to_string_reference(name=ACTION_2.name, pack=ACTION_2.pack) |
||
560 | chain_runner.liveaction = LiveActionDB(action=action_ref) |
||
561 | chain_runner.pre_run() |
||
562 | chain_runner.run({'s1': 1, 's2': 'two', 's3': 3.14}) |
||
563 | self.assertNotEqual(chain_runner.chain_holder.actionchain, None) |
||
564 | expected_value = {'booltype': True, |
||
565 | 'inttype': 1, |
||
566 | 'numbertype': 3.14, |
||
567 | 'strtype': 'two', |
||
568 | 'arrtype': ['1', 'two'], |
||
569 | 'objtype': {'s2': 'two', |
||
570 | 'k1': '1'}} |
||
571 | mock_args, _ = request.call_args |
||
572 | self.assertEqual(mock_args[0].parameters, expected_value) |
||
573 | |||
574 | @mock.patch.object(action_db_util, 'get_action_by_ref', |
||
575 | mock.MagicMock(return_value=ACTION_2)) |
||
576 | @mock.patch.object(action_service, 'request', return_value=(DummyActionExecution(), None)) |
||
577 | def test_chain_runner_typed_system_params(self, request): |
||
578 | action_ref = ResourceReference.to_string_reference(name=ACTION_2.name, pack=ACTION_2.pack) |
||
579 | kvps = [] |
||
580 | try: |
||
581 | kvps.append(KeyValuePair.add_or_update(KeyValuePairDB(name='a', value='1'))) |
||
582 | kvps.append(KeyValuePair.add_or_update(KeyValuePairDB(name='a.b.c', value='two'))) |
||
583 | chain_runner = acr.get_runner() |
||
584 | chain_runner.entry_point = CHAIN_SYSTEM_PARAMS |
||
585 | chain_runner.action = ACTION_2 |
||
586 | chain_runner.liveaction = LiveActionDB(action=action_ref) |
||
587 | chain_runner.pre_run() |
||
588 | chain_runner.run({}) |
||
589 | self.assertNotEqual(chain_runner.chain_holder.actionchain, None) |
||
590 | expected_value = {'inttype': 1, |
||
591 | 'strtype': 'two'} |
||
592 | mock_args, _ = request.call_args |
||
593 | self.assertEqual(mock_args[0].parameters, expected_value) |
||
594 | finally: |
||
595 | for kvp in kvps: |
||
596 | KeyValuePair.delete(kvp) |
||
597 | |||
598 | @mock.patch.object(action_db_util, 'get_action_by_ref', |
||
599 | mock.MagicMock(return_value=ACTION_2)) |
||
600 | @mock.patch.object(action_service, 'request', return_value=(DummyActionExecution(), None)) |
||
601 | def test_chain_runner_vars_system_params(self, request): |
||
602 | action_ref = ResourceReference.to_string_reference(name=ACTION_2.name, pack=ACTION_2.pack) |
||
603 | kvps = [] |
||
604 | try: |
||
605 | kvps.append(KeyValuePair.add_or_update(KeyValuePairDB(name='a', value='two'))) |
||
606 | chain_runner = acr.get_runner() |
||
607 | chain_runner.entry_point = CHAIN_WITH_SYSTEM_VARS |
||
608 | chain_runner.action = ACTION_2 |
||
609 | chain_runner.liveaction = LiveActionDB(action=action_ref) |
||
610 | chain_runner.pre_run() |
||
611 | chain_runner.run({}) |
||
612 | self.assertNotEqual(chain_runner.chain_holder.actionchain, None) |
||
613 | expected_value = {'inttype': 1, |
||
614 | 'strtype': 'two', |
||
615 | 'booltype': True} |
||
616 | mock_args, _ = request.call_args |
||
617 | self.assertEqual(mock_args[0].parameters, expected_value) |
||
618 | finally: |
||
619 | for kvp in kvps: |
||
620 | KeyValuePair.delete(kvp) |
||
621 | |||
622 | @mock.patch.object(action_db_util, 'get_action_by_ref', |
||
623 | mock.MagicMock(return_value=ACTION_2)) |
||
624 | @mock.patch.object(action_service, 'request', return_value=(DummyActionExecution(), None)) |
||
625 | def test_chain_runner_vars_action_params(self, request): |
||
626 | chain_runner = acr.get_runner() |
||
627 | chain_runner.entry_point = CHAIN_WITH_ACTIONPARAM_VARS |
||
628 | chain_runner.action = ACTION_2 |
||
629 | action_ref = ResourceReference.to_string_reference(name=ACTION_2.name, pack=ACTION_2.pack) |
||
630 | chain_runner.liveaction = LiveActionDB(action=action_ref) |
||
631 | chain_runner.pre_run() |
||
632 | chain_runner.run({'input_a': 'two'}) |
||
633 | self.assertNotEqual(chain_runner.chain_holder.actionchain, None) |
||
634 | expected_value = {'inttype': 1, |
||
635 | 'strtype': 'two', |
||
636 | 'booltype': True} |
||
637 | mock_args, _ = request.call_args |
||
638 | self.assertEqual(mock_args[0].parameters, expected_value) |
||
639 | |||
640 | @mock.patch.object(action_db_util, 'get_action_by_ref', |
||
641 | mock.MagicMock(return_value=ACTION_2)) |
||
642 | @mock.patch.object(action_service, 'request', |
||
643 | return_value=(DummyActionExecution(result={'raw_out': 'published'}), None)) |
||
644 | def test_chain_runner_publish(self, request): |
||
645 | chain_runner = acr.get_runner() |
||
646 | chain_runner.entry_point = CHAIN_WITH_PUBLISH |
||
647 | chain_runner.action = ACTION_2 |
||
648 | action_ref = ResourceReference.to_string_reference(name=ACTION_2.name, pack=ACTION_2.pack) |
||
649 | chain_runner.liveaction = LiveActionDB(action=action_ref) |
||
650 | chain_runner.runner_parameters = {'display_published': True} |
||
651 | chain_runner.pre_run() |
||
652 | |||
653 | action_parameters = {'action_param_1': 'test value 1'} |
||
654 | _, result, _ = chain_runner.run(action_parameters=action_parameters) |
||
655 | |||
656 | # We also assert that the action parameters are available in the |
||
657 | # "publish" scope |
||
658 | self.assertNotEqual(chain_runner.chain_holder.actionchain, None) |
||
659 | expected_value = {'inttype': 1, |
||
660 | 'strtype': 'published', |
||
661 | 'booltype': True, |
||
662 | 'published_action_param': action_parameters['action_param_1']} |
||
663 | mock_args, _ = request.call_args |
||
664 | self.assertEqual(mock_args[0].parameters, expected_value) |
||
665 | # Assert that the variables are correctly published |
||
666 | self.assertEqual(result['published'], |
||
667 | {'published_action_param': u'test value 1', 'o1': u'published'}) |
||
668 | |||
669 | @mock.patch.object(action_db_util, 'get_action_by_ref', |
||
670 | mock.MagicMock(return_value=ACTION_1)) |
||
671 | @mock.patch.object(action_service, 'request', return_value=(DummyActionExecution(), None)) |
||
672 | def test_chain_runner_publish_param_rendering_failure(self, request): |
||
673 | # Parameter rendering should result in a top level error which aborts |
||
674 | # the whole chain |
||
675 | chain_runner = acr.get_runner() |
||
676 | chain_runner.entry_point = CHAIN_WITH_PUBLISH_PARAM_RENDERING_FAILURE |
||
677 | chain_runner.action = ACTION_1 |
||
678 | action_ref = ResourceReference.to_string_reference(name=ACTION_1.name, pack=ACTION_1.pack) |
||
679 | chain_runner.liveaction = LiveActionDB(action=action_ref) |
||
680 | chain_runner.pre_run() |
||
681 | |||
682 | try: |
||
683 | chain_runner.run({}) |
||
684 | except ParameterRenderingFailedException as e: |
||
685 | # TODO: Should we treat this as task error? Right now it bubbles all |
||
686 | # the way up and it's not really consistent with action param |
||
687 | # rendering failure |
||
688 | expected_error = ('Failed rendering value for publish parameter "p1" in ' |
||
689 | 'task "c2" (template string={{ not_defined }}):') |
||
690 | self.assertTrue(expected_error in str(e)) |
||
691 | pass |
||
0 ignored issues
–
show
|
|||
692 | else: |
||
693 | self.fail('Exception was not thrown') |
||
694 | |||
695 | @mock.patch.object(action_db_util, 'get_action_by_ref', |
||
696 | mock.MagicMock(return_value=ACTION_2)) |
||
697 | @mock.patch.object(action_service, 'request', return_value=(DummyActionExecution(), None)) |
||
698 | def test_chain_task_passes_invalid_parameter_type_to_action(self, mock_request): |
||
699 | chain_runner = acr.get_runner() |
||
700 | chain_runner.entry_point = CHAIN_ACTION_INVALID_PARAMETER_TYPE |
||
701 | chain_runner.action = ACTION_2 |
||
702 | chain_runner.pre_run() |
||
703 | |||
704 | action_parameters = {} |
||
705 | expected_msg = ('Failed to cast value "stringnotanarray" \(type: str\) for parameter ' |
||
0 ignored issues
–
show
A suspicious escape sequence
\( was found. Did you maybe forget to add an r prefix?
Escape sequences in Python are generally interpreted according to rules similar
to standard C. Only if strings are prefixed with The escape sequence that was used indicates that you might have intended to write a regular expression. Learn more about the available escape sequences. in the Python documentation.
Loading history...
A suspicious escape sequence
\) was found. Did you maybe forget to add an r prefix?
Escape sequences in Python are generally interpreted according to rules similar
to standard C. Only if strings are prefixed with The escape sequence that was used indicates that you might have intended to write a regular expression. Learn more about the available escape sequences. in the Python documentation.
Loading history...
|
|||
706 | '"arrtype" of type "array"') |
||
707 | self.assertRaisesRegexp(ValueError, expected_msg, chain_runner.run, |
||
708 | action_parameters=action_parameters) |
||
709 | |||
710 | @mock.patch.object(action_db_util, 'get_action_by_ref', |
||
711 | mock.MagicMock(return_value=None)) |
||
712 | @mock.patch.object(action_service, 'request', |
||
713 | return_value=(DummyActionExecution(result={'raw_out': 'published'}), None)) |
||
714 | def test_action_chain_runner_referenced_action_doesnt_exist(self, mock_request): |
||
715 | # Action referenced by a task doesn't exist, should result in a top level error |
||
716 | chain_runner = acr.get_runner() |
||
717 | chain_runner.entry_point = CHAIN_WITH_INVALID_ACTION |
||
718 | chain_runner.action = ACTION_2 |
||
719 | action_ref = ResourceReference.to_string_reference(name=ACTION_2.name, pack=ACTION_2.pack) |
||
720 | chain_runner.liveaction = LiveActionDB(action=action_ref) |
||
721 | chain_runner.pre_run() |
||
722 | |||
723 | action_parameters = {} |
||
724 | status, output, _ = chain_runner.run(action_parameters=action_parameters) |
||
725 | |||
726 | expected_error = ('Failed to run task "c1". Action with reference "wolfpack.a2" ' |
||
727 | 'doesn\'t exist.') |
||
728 | self.assertEqual(status, LIVEACTION_STATUS_FAILED) |
||
729 | self.assertTrue(expected_error in output['error']) |
||
730 | self.assertTrue('Traceback' in output['traceback'], output['traceback']) |
||
731 | |||
732 | def test_exception_is_thrown_if_both_params_and_parameters_attributes_are_provided(self): |
||
733 | chain_runner = acr.get_runner() |
||
734 | chain_runner.entry_point = CHAIN_ACTION_PARAMS_AND_PARAMETERS_ATTRIBUTE |
||
735 | chain_runner.action = ACTION_2 |
||
736 | |||
737 | expected_msg = ('Either "params" or "parameters" attribute needs to be provided, but ' |
||
738 | 'not both') |
||
739 | self.assertRaisesRegexp(runnerexceptions.ActionRunnerPreRunError, expected_msg, |
||
740 | chain_runner.pre_run) |
||
741 | |||
742 | @mock.patch.object(action_db_util, 'get_action_by_ref', |
||
743 | mock.MagicMock(return_value=ACTION_2)) |
||
744 | @mock.patch.object(action_service, 'request', return_value=(DummyActionExecution(), None)) |
||
745 | def test_params_and_parameters_attributes_both_work(self, _): |
||
746 | action_ref = ResourceReference.to_string_reference(name=ACTION_2.name, pack=ACTION_2.pack) |
||
747 | |||
748 | # "params" attribute used |
||
749 | chain_runner = acr.get_runner() |
||
750 | chain_runner.entry_point = CHAIN_ACTION_PARAMS_ATTRIBUTE |
||
751 | chain_runner.action = ACTION_2 |
||
752 | chain_runner.liveaction = LiveActionDB(action=action_ref) |
||
753 | chain_runner.pre_run() |
||
754 | |||
755 | original_build_liveaction_object = chain_runner._build_liveaction_object |
||
0 ignored issues
–
show
It seems like
_build_liveaction_object was declared protected and should not be accessed from this context.
Prefixing a member variable class MyParent:
def __init__(self):
self._x = 1;
self.y = 2;
class MyChild(MyParent):
def some_method(self):
return self._x # Ok, since accessed from a child class
class AnotherClass:
def some_method(self, instance_of_my_child):
return instance_of_my_child._x # Would be flagged as AnotherClass is not
# a child class of MyParent
Loading history...
|
|||
756 | |||
757 | def mock_build_liveaction_object(action_node, resolved_params, parent_context): |
||
758 | # Verify parameters are correctly passed to the action |
||
759 | self.assertEqual(resolved_params, {'pparams': 'v1'}) |
||
760 | original_build_liveaction_object(action_node=action_node, |
||
761 | resolved_params=resolved_params, |
||
762 | parent_context=parent_context) |
||
763 | |||
764 | chain_runner._build_liveaction_object = mock_build_liveaction_object |
||
0 ignored issues
–
show
It seems like
_build_liveaction_object was declared protected and should not be accessed from this context.
Prefixing a member variable class MyParent:
def __init__(self):
self._x = 1;
self.y = 2;
class MyChild(MyParent):
def some_method(self):
return self._x # Ok, since accessed from a child class
class AnotherClass:
def some_method(self, instance_of_my_child):
return instance_of_my_child._x # Would be flagged as AnotherClass is not
# a child class of MyParent
Loading history...
|
|||
765 | |||
766 | action_parameters = {} |
||
767 | status, output, _ = chain_runner.run(action_parameters=action_parameters) |
||
768 | self.assertEqual(status, LIVEACTION_STATUS_SUCCEEDED) |
||
769 | |||
770 | # "parameters" attribute used |
||
771 | chain_runner = acr.get_runner() |
||
772 | chain_runner.entry_point = CHAIN_ACTION_PARAMETERS_ATTRIBUTE |
||
773 | chain_runner.action = ACTION_2 |
||
774 | chain_runner.liveaction = LiveActionDB(action=action_ref) |
||
775 | chain_runner.pre_run() |
||
776 | |||
777 | def mock_build_liveaction_object(action_node, resolved_params, parent_context): |
||
0 ignored issues
–
show
|
|||
778 | # Verify parameters are correctly passed to the action |
||
779 | self.assertEqual(resolved_params, {'pparameters': 'v1'}) |
||
780 | original_build_liveaction_object(action_node=action_node, |
||
781 | resolved_params=resolved_params, |
||
782 | parent_context=parent_context) |
||
783 | |||
784 | chain_runner._build_liveaction_object = mock_build_liveaction_object |
||
0 ignored issues
–
show
It seems like
_build_liveaction_object was declared protected and should not be accessed from this context.
Prefixing a member variable class MyParent:
def __init__(self):
self._x = 1;
self.y = 2;
class MyChild(MyParent):
def some_method(self):
return self._x # Ok, since accessed from a child class
class AnotherClass:
def some_method(self, instance_of_my_child):
return instance_of_my_child._x # Would be flagged as AnotherClass is not
# a child class of MyParent
Loading history...
|
|||
785 | |||
786 | action_parameters = {} |
||
787 | status, output, _ = chain_runner.run(action_parameters=action_parameters) |
||
788 | self.assertEqual(status, LIVEACTION_STATUS_SUCCEEDED) |
||
789 | |||
790 | @mock.patch.object(action_db_util, 'get_action_by_ref', |
||
791 | mock.MagicMock(return_value=ACTION_2)) |
||
792 | @mock.patch.object(action_service, 'request', |
||
793 | return_value=(DummyActionExecution(result={'raw_out': 'published'}), None)) |
||
794 | def test_display_published_is_true_by_default(self, _): |
||
795 | action_ref = ResourceReference.to_string_reference(name=ACTION_2.name, pack=ACTION_2.pack) |
||
796 | |||
797 | expected_published_values = { |
||
798 | 't1_publish_param_1': 'foo1', |
||
799 | 't1_publish_param_2': 'foo2', |
||
800 | 't1_publish_param_3': 'foo3', |
||
801 | 't2_publish_param_1': 'foo4', |
||
802 | 't2_publish_param_2': 'foo5', |
||
803 | 't2_publish_param_3': 'foo6', |
||
804 | 'publish_last_wins': 'bar_last', |
||
805 | } |
||
806 | |||
807 | # 1. display_published is True by default |
||
808 | chain_runner = acr.get_runner() |
||
809 | chain_runner.entry_point = CHAIN_WITH_PUBLISH_2 |
||
810 | chain_runner.action = ACTION_2 |
||
811 | chain_runner.liveaction = LiveActionDB(action=action_ref) |
||
812 | chain_runner.runner_parameters = {} |
||
813 | chain_runner.pre_run() |
||
814 | |||
815 | action_parameters = {} |
||
816 | _, result, _ = chain_runner.run(action_parameters=action_parameters) |
||
817 | |||
818 | # Assert that the variables are correctly published |
||
819 | self.assertEqual(result['published'], expected_published_values) |
||
820 | |||
821 | # 2. display_published is True by default so end result should be the same |
||
822 | chain_runner = acr.get_runner() |
||
823 | chain_runner.entry_point = CHAIN_WITH_PUBLISH_2 |
||
824 | chain_runner.action = ACTION_2 |
||
825 | chain_runner.liveaction = LiveActionDB(action=action_ref) |
||
826 | chain_runner.runner_parameters = {'display_published': True} |
||
827 | chain_runner.pre_run() |
||
828 | |||
829 | action_parameters = {} |
||
830 | _, result, _ = chain_runner.run(action_parameters=action_parameters) |
||
831 | |||
832 | # Assert that the variables are correctly published |
||
833 | self.assertEqual(result['published'], expected_published_values) |
||
834 | |||
835 | # 3. display_published is disabled |
||
836 | chain_runner = acr.get_runner() |
||
837 | chain_runner.entry_point = CHAIN_WITH_PUBLISH_2 |
||
838 | chain_runner.action = ACTION_2 |
||
839 | chain_runner.liveaction = LiveActionDB(action=action_ref) |
||
840 | chain_runner.runner_parameters = {'display_published': False} |
||
841 | chain_runner.pre_run() |
||
842 | |||
843 | action_parameters = {} |
||
844 | _, result, _ = chain_runner.run(action_parameters=action_parameters) |
||
845 | |||
846 | self.assertTrue('published' not in result) |
||
847 | self.assertEqual(result.get('published', {}), {}) |
||
848 | |||
849 | @classmethod |
||
850 | def tearDownClass(cls): |
||
851 | FixturesLoader().delete_models_from_db(MODELS) |
||
852 |
Prefixing a member variable
_
is usually regarded as the equivalent of declaring it with protected visibility that exists in other languages. Consequentially, such a member should only be accessed from the same class or a child class: