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 copy |
||
18 | import uuid |
||
19 | |||
20 | import mock |
||
21 | import requests |
||
22 | import yaml |
||
23 | |||
24 | from mistralclient.api.base import APIException |
||
25 | from mistralclient.api.v2 import executions |
||
26 | from mistralclient.api.v2 import workbooks |
||
27 | from mistralclient.api.v2 import workflows |
||
28 | from oslo_config import cfg |
||
29 | |||
30 | # XXX: actionsensor import depends on config being setup. |
||
31 | import st2tests.config as tests_config |
||
32 | tests_config.parse_args() |
||
33 | |||
34 | from mistral_v2.mistral_v2 import MistralRunner |
||
35 | from st2common.bootstrap import actionsregistrar |
||
36 | from st2common.bootstrap import runnersregistrar |
||
37 | from st2common.constants import action as action_constants |
||
38 | from st2common.models.api.notification import NotificationsHelper |
||
39 | from st2common.models.db.liveaction import LiveActionDB |
||
40 | from st2common.persistence.liveaction import LiveAction |
||
41 | from st2common.runners import base as runners |
||
42 | from st2common.services import action as action_service |
||
43 | from st2common.transport.liveaction import LiveActionPublisher |
||
44 | from st2common.transport.publishers import CUDPublisher |
||
45 | from st2common.util import loader |
||
46 | from st2tests import DbTestCase |
||
47 | from st2tests import fixturesloader |
||
48 | from st2tests.mocks.liveaction import MockLiveActionPublisher |
||
49 | |||
50 | |||
51 | TEST_FIXTURES = { |
||
52 | 'workflows': [ |
||
53 | 'workbook_v2.yaml', |
||
54 | 'workbook_v2_many_workflows.yaml', |
||
55 | 'workbook_v2_many_workflows_no_default.yaml', |
||
56 | 'workflow_v2.yaml', |
||
57 | 'workflow_v2_many_workflows.yaml' |
||
58 | ], |
||
59 | 'actions': [ |
||
60 | 'workbook_v2.yaml', |
||
61 | 'workbook_v2_many_workflows.yaml', |
||
62 | 'workbook_v2_many_workflows_no_default.yaml', |
||
63 | 'workflow_v2.yaml', |
||
64 | 'workflow_v2_many_workflows.yaml', |
||
65 | 'workbook_v2_name_mismatch.yaml', |
||
66 | 'workflow_v2_name_mismatch.yaml' |
||
67 | ] |
||
68 | } |
||
69 | |||
70 | TEST_PACK = 'mistral_tests' |
||
71 | TEST_PACK_PATH = fixturesloader.get_fixtures_packs_base_path() + '/' + TEST_PACK |
||
72 | |||
73 | PACKS = [ |
||
74 | TEST_PACK_PATH, |
||
75 | fixturesloader.get_fixtures_packs_base_path() + '/core' |
||
76 | ] |
||
77 | |||
78 | # Action executions requirements |
||
79 | MISTRAL_EXECUTION = {'id': str(uuid.uuid4()), 'state': 'RUNNING', 'workflow_name': None} |
||
80 | ACTION_PARAMS = {'friend': 'Rocky'} |
||
81 | NON_EMPTY_RESULT = 'non-empty' |
||
82 | |||
83 | # Workbook with a single workflow |
||
84 | WB1_META_FILE_NAME = TEST_FIXTURES['workflows'][0] |
||
85 | WB1_META_FILE_PATH = TEST_PACK_PATH + '/actions/' + WB1_META_FILE_NAME |
||
86 | WB1_META_CONTENT = loader.load_meta_file(WB1_META_FILE_PATH) |
||
87 | WB1_NAME = WB1_META_CONTENT['pack'] + '.' + WB1_META_CONTENT['name'] |
||
88 | WB1_ENTRY_POINT = TEST_PACK_PATH + '/actions/' + WB1_META_CONTENT['entry_point'] |
||
89 | WB1_ENTRY_POINT_X = WB1_ENTRY_POINT.replace(WB1_META_FILE_NAME, 'xformed_' + WB1_META_FILE_NAME) |
||
90 | WB1_SPEC = yaml.safe_load(MistralRunner.get_workflow_definition(WB1_ENTRY_POINT_X)) |
||
91 | WB1_YAML = yaml.safe_dump(WB1_SPEC, default_flow_style=False) |
||
92 | WB1 = workbooks.Workbook(None, {'name': WB1_NAME, 'definition': WB1_YAML}) |
||
93 | WB1_OLD = workbooks.Workbook(None, {'name': WB1_NAME, 'definition': ''}) |
||
94 | WB1_EXEC = copy.deepcopy(MISTRAL_EXECUTION) |
||
95 | WB1_EXEC['workflow_name'] = WB1_NAME |
||
96 | |||
97 | # Workbook with many workflows |
||
98 | WB2_META_FILE_NAME = TEST_FIXTURES['workflows'][1] |
||
99 | WB2_META_FILE_PATH = TEST_PACK_PATH + '/actions/' + WB2_META_FILE_NAME |
||
100 | WB2_META_CONTENT = loader.load_meta_file(WB2_META_FILE_PATH) |
||
101 | WB2_NAME = WB2_META_CONTENT['pack'] + '.' + WB2_META_CONTENT['name'] |
||
102 | WB2_ENTRY_POINT = TEST_PACK_PATH + '/actions/' + WB2_META_CONTENT['entry_point'] |
||
103 | WB2_ENTRY_POINT_X = WB2_ENTRY_POINT.replace(WB2_META_FILE_NAME, 'xformed_' + WB2_META_FILE_NAME) |
||
104 | WB2_SPEC = yaml.safe_load(MistralRunner.get_workflow_definition(WB2_ENTRY_POINT_X)) |
||
105 | WB2_YAML = yaml.safe_dump(WB2_SPEC, default_flow_style=False) |
||
106 | WB2 = workbooks.Workbook(None, {'name': WB2_NAME, 'definition': WB2_YAML}) |
||
107 | WB2_EXEC = copy.deepcopy(MISTRAL_EXECUTION) |
||
108 | WB2_EXEC['workflow_name'] = WB2_NAME |
||
109 | |||
110 | # Workbook with many workflows but no default workflow is defined |
||
111 | WB3_META_FILE_NAME = TEST_FIXTURES['workflows'][2] |
||
112 | WB3_META_FILE_PATH = TEST_PACK_PATH + '/actions/' + WB3_META_FILE_NAME |
||
113 | WB3_META_CONTENT = loader.load_meta_file(WB3_META_FILE_PATH) |
||
114 | WB3_NAME = WB3_META_CONTENT['pack'] + '.' + WB3_META_CONTENT['name'] |
||
115 | WB3_ENTRY_POINT = TEST_PACK_PATH + '/actions/' + WB3_META_CONTENT['entry_point'] |
||
116 | WB3_ENTRY_POINT_X = WB3_ENTRY_POINT.replace(WB3_META_FILE_NAME, 'xformed_' + WB3_META_FILE_NAME) |
||
117 | WB3_SPEC = yaml.safe_load(MistralRunner.get_workflow_definition(WB3_ENTRY_POINT_X)) |
||
118 | WB3_YAML = yaml.safe_dump(WB3_SPEC, default_flow_style=False) |
||
119 | WB3 = workbooks.Workbook(None, {'name': WB3_NAME, 'definition': WB3_YAML}) |
||
120 | WB3_EXEC = copy.deepcopy(MISTRAL_EXECUTION) |
||
121 | WB3_EXEC['workflow_name'] = WB3_NAME |
||
122 | |||
123 | # Non-workbook with a single workflow |
||
124 | WF1_META_FILE_NAME = TEST_FIXTURES['workflows'][3] |
||
125 | WF1_META_FILE_PATH = TEST_PACK_PATH + '/actions/' + WF1_META_FILE_NAME |
||
126 | WF1_META_CONTENT = loader.load_meta_file(WF1_META_FILE_PATH) |
||
127 | WF1_NAME = WF1_META_CONTENT['pack'] + '.' + WF1_META_CONTENT['name'] |
||
128 | WF1_ENTRY_POINT = TEST_PACK_PATH + '/actions/' + WF1_META_CONTENT['entry_point'] |
||
129 | WF1_ENTRY_POINT_X = WF1_ENTRY_POINT.replace(WF1_META_FILE_NAME, 'xformed_' + WF1_META_FILE_NAME) |
||
130 | WF1_SPEC = yaml.safe_load(MistralRunner.get_workflow_definition(WF1_ENTRY_POINT_X)) |
||
131 | WF1_YAML = yaml.safe_dump(WF1_SPEC, default_flow_style=False) |
||
132 | WF1 = workflows.Workflow(None, {'name': WF1_NAME, 'definition': WF1_YAML}) |
||
133 | WF1_OLD = workflows.Workflow(None, {'name': WF1_NAME, 'definition': ''}) |
||
134 | WF1_EXEC = copy.deepcopy(MISTRAL_EXECUTION) |
||
135 | WF1_EXEC['workflow_name'] = WF1_NAME |
||
136 | |||
137 | # Non-workbook with a many workflows |
||
138 | WF2_META_FILE_NAME = TEST_FIXTURES['workflows'][4] |
||
139 | WF2_META_FILE_PATH = TEST_PACK_PATH + '/actions/' + WF2_META_FILE_NAME |
||
140 | WF2_META_CONTENT = loader.load_meta_file(WF2_META_FILE_PATH) |
||
141 | WF2_NAME = WF2_META_CONTENT['pack'] + '.' + WF2_META_CONTENT['name'] |
||
142 | WF2_ENTRY_POINT = TEST_PACK_PATH + '/actions/' + WF2_META_CONTENT['entry_point'] |
||
143 | WF2_ENTRY_POINT_X = WF2_ENTRY_POINT.replace(WF2_META_FILE_NAME, 'xformed_' + WF2_META_FILE_NAME) |
||
144 | WF2_SPEC = yaml.safe_load(MistralRunner.get_workflow_definition(WF2_ENTRY_POINT_X)) |
||
145 | WF2_YAML = yaml.safe_dump(WF2_SPEC, default_flow_style=False) |
||
146 | WF2 = workflows.Workflow(None, {'name': WF2_NAME, 'definition': WF2_YAML}) |
||
147 | WF2_EXEC = copy.deepcopy(MISTRAL_EXECUTION) |
||
148 | WF2_EXEC['workflow_name'] = WF2_NAME |
||
149 | |||
150 | # Data for the notify param |
||
151 | NOTIFY = [{'type': 'st2'}] |
||
152 | |||
153 | |||
154 | @mock.patch.object( |
||
155 | CUDPublisher, |
||
156 | 'publish_update', |
||
157 | mock.MagicMock(return_value=None)) |
||
158 | @mock.patch.object( |
||
159 | CUDPublisher, |
||
160 | 'publish_create', |
||
161 | mock.MagicMock(side_effect=MockLiveActionPublisher.publish_create)) |
||
162 | @mock.patch.object( |
||
163 | LiveActionPublisher, |
||
164 | 'publish_state', |
||
165 | mock.MagicMock(side_effect=MockLiveActionPublisher.publish_state)) |
||
166 | class MistralRunnerTest(DbTestCase): |
||
167 | |||
168 | @classmethod |
||
169 | def setUpClass(cls): |
||
170 | super(MistralRunnerTest, cls).setUpClass() |
||
171 | |||
172 | # Override the retry configuration here otherwise st2tests.config.parse_args |
||
173 | # in DbTestCase.setUpClass will reset these overrides. |
||
174 | cfg.CONF.set_override('retry_exp_msec', 100, group='mistral') |
||
175 | cfg.CONF.set_override('retry_exp_max_msec', 200, group='mistral') |
||
176 | cfg.CONF.set_override('retry_stop_max_msec', 200, group='mistral') |
||
177 | cfg.CONF.set_override('api_url', 'http://0.0.0.0:9101', group='auth') |
||
178 | |||
179 | # Register runners. |
||
180 | runnersregistrar.register_runners() |
||
181 | |||
182 | # Register test pack(s). |
||
183 | actions_registrar = actionsregistrar.ActionsRegistrar( |
||
184 | use_pack_cache=False, |
||
185 | fail_on_failure=True |
||
186 | ) |
||
187 | |||
188 | for pack in PACKS: |
||
189 | actions_registrar.register_from_pack(pack) |
||
190 | |||
191 | @classmethod |
||
192 | def get_runner_class(cls, runner_name): |
||
193 | return runners.get_runner(runner_name, runner_name).__class__ |
||
194 | |||
195 | def test_build_context(self): |
||
196 | parent = { |
||
197 | 'mistral': { |
||
198 | 'workflow_name': 'foo', |
||
199 | 'workflow_execution_id': 'b222b934-7473-4cd4-a2ec-e204a8c93848', |
||
200 | 'task_tags': None, |
||
201 | 'task_name': 'some_fancy_wf_task', |
||
202 | 'task_id': '6c7d4334-3e7d-49c6-918d-698e846affaf', |
||
203 | 'action_execution_id': '24da5c88-834c-4a65-8b56-4ddbd654eb68' |
||
204 | } |
||
205 | } |
||
206 | |||
207 | current = { |
||
208 | 'workflow_name': 'foo.subwf', |
||
209 | 'workflow_execution_id': '135e3446-4c89-4afe-821f-6ec6a0849b27' |
||
210 | } |
||
211 | |||
212 | context = MistralRunner._build_mistral_context(parent, current) |
||
0 ignored issues
–
show
|
|||
213 | self.assertTrue(context is not None) |
||
214 | self.assertTrue('parent' in list(context['mistral'].keys())) |
||
215 | |||
216 | parent_dict = { |
||
217 | 'workflow_name': parent['mistral']['workflow_name'], |
||
218 | 'workflow_execution_id': parent['mistral']['workflow_execution_id'] |
||
219 | } |
||
220 | |||
221 | self.assertDictEqual(context['mistral']['parent'], parent_dict) |
||
222 | self.assertEqual(context['mistral']['workflow_execution_id'], |
||
223 | current['workflow_execution_id']) |
||
224 | |||
225 | parent = None |
||
226 | context = MistralRunner._build_mistral_context(parent, current) |
||
0 ignored issues
–
show
It seems like
_build_mistral_context 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...
|
|||
227 | self.assertDictEqual(context['mistral'], current) |
||
228 | |||
229 | @mock.patch.object( |
||
230 | workflows.WorkflowManager, 'list', |
||
231 | mock.MagicMock(return_value=[])) |
||
232 | @mock.patch.object( |
||
233 | workflows.WorkflowManager, 'get', |
||
234 | mock.MagicMock(return_value=WF1)) |
||
235 | @mock.patch.object( |
||
236 | workflows.WorkflowManager, 'create', |
||
237 | mock.MagicMock(return_value=[WF1])) |
||
238 | @mock.patch.object( |
||
239 | executions.ExecutionManager, 'create', |
||
240 | mock.MagicMock(return_value=executions.Execution(None, WF1_EXEC))) |
||
241 | def test_launch_workflow(self): |
||
242 | liveaction = LiveActionDB(action=WF1_NAME, parameters=ACTION_PARAMS) |
||
243 | liveaction, execution = action_service.request(liveaction) |
||
244 | liveaction = LiveAction.get_by_id(str(liveaction.id)) |
||
245 | self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_RUNNING) |
||
246 | |||
247 | mistral_context = liveaction.context.get('mistral', None) |
||
248 | self.assertIsNotNone(mistral_context) |
||
249 | self.assertEqual(mistral_context['execution_id'], WF1_EXEC.get('id')) |
||
250 | self.assertEqual(mistral_context['workflow_name'], WF1_EXEC.get('workflow_name')) |
||
251 | |||
252 | workflow_input = copy.deepcopy(ACTION_PARAMS) |
||
253 | workflow_input.update({'count': '3'}) |
||
254 | |||
255 | env = { |
||
256 | 'st2_execution_id': str(execution.id), |
||
257 | 'st2_liveaction_id': str(liveaction.id), |
||
258 | 'st2_action_api_url': 'http://0.0.0.0:9101/v1', |
||
259 | '__actions': { |
||
260 | 'st2.action': { |
||
261 | 'st2_context': { |
||
262 | 'api_url': 'http://0.0.0.0:9101/v1', |
||
263 | 'endpoint': 'http://0.0.0.0:9101/v1/actionexecutions', |
||
264 | 'parent': { |
||
265 | 'pack': 'mistral_tests', |
||
266 | 'execution_id': str(execution.id) |
||
267 | }, |
||
268 | 'notify': {}, |
||
269 | 'skip_notify_tasks': [] |
||
270 | } |
||
271 | } |
||
272 | } |
||
273 | } |
||
274 | |||
275 | executions.ExecutionManager.create.assert_called_with( |
||
276 | WF1_NAME, workflow_input=workflow_input, env=env, notify=NOTIFY) |
||
277 | |||
278 | @mock.patch.object( |
||
279 | workflows.WorkflowManager, 'list', |
||
280 | mock.MagicMock(return_value=[])) |
||
281 | @mock.patch.object( |
||
282 | workflows.WorkflowManager, 'get', |
||
283 | mock.MagicMock(return_value=WF1)) |
||
284 | @mock.patch.object( |
||
285 | workflows.WorkflowManager, 'create', |
||
286 | mock.MagicMock(return_value=[WF1])) |
||
287 | @mock.patch.object( |
||
288 | executions.ExecutionManager, 'create', |
||
289 | mock.MagicMock(return_value=executions.Execution(None, WF1_EXEC))) |
||
290 | def test_launch_workflow_under_parent_chain_with_jinja_params(self): |
||
291 | ac_ctx = { |
||
292 | 'chain': { |
||
293 | 'params': { |
||
294 | 'var1': 'foobar', |
||
295 | 'var2': '{{foobar}}', |
||
296 | 'var3': ['{{foo}}', '{{bar}}'], |
||
297 | 'var4': { |
||
298 | 'foobar': '{{foobar}}' |
||
299 | }, |
||
300 | 'var5': { |
||
301 | 'foobar': '{% for item in items %}foobar{% end for %}' |
||
302 | } |
||
303 | } |
||
304 | } |
||
305 | } |
||
306 | |||
307 | liveaction = LiveActionDB(action=WF1_NAME, parameters=ACTION_PARAMS, context=ac_ctx) |
||
308 | liveaction, execution = action_service.request(liveaction) |
||
309 | liveaction = LiveAction.get_by_id(str(liveaction.id)) |
||
310 | self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_RUNNING) |
||
311 | |||
312 | mistral_context = liveaction.context.get('mistral', None) |
||
313 | self.assertIsNotNone(mistral_context) |
||
314 | self.assertEqual(mistral_context['execution_id'], WF1_EXEC.get('id')) |
||
315 | self.assertEqual(mistral_context['workflow_name'], WF1_EXEC.get('workflow_name')) |
||
316 | |||
317 | workflow_input = copy.deepcopy(ACTION_PARAMS) |
||
318 | workflow_input.update({'count': '3'}) |
||
319 | |||
320 | env = { |
||
321 | 'st2_execution_id': str(execution.id), |
||
322 | 'st2_liveaction_id': str(liveaction.id), |
||
323 | 'st2_action_api_url': 'http://0.0.0.0:9101/v1', |
||
324 | '__actions': { |
||
325 | 'st2.action': { |
||
326 | 'st2_context': { |
||
327 | 'api_url': 'http://0.0.0.0:9101/v1', |
||
328 | 'endpoint': 'http://0.0.0.0:9101/v1/actionexecutions', |
||
329 | 'parent': { |
||
330 | 'pack': 'mistral_tests', |
||
331 | 'execution_id': str(execution.id), |
||
332 | 'chain': { |
||
333 | 'params': { |
||
334 | 'var1': 'foobar', |
||
335 | 'var2': '{% raw %}{{foobar}}{% endraw %}', |
||
336 | 'var3': [ |
||
337 | '{% raw %}{{foo}}{% endraw %}', |
||
338 | '{% raw %}{{bar}}{% endraw %}' |
||
339 | ], |
||
340 | 'var4': { |
||
341 | 'foobar': '{% raw %}{{foobar}}{% endraw %}' |
||
342 | }, |
||
343 | 'var5': { |
||
344 | 'foobar': ( |
||
345 | '{% raw %}{% for item in items %}' |
||
346 | 'foobar{% end for %}{% endraw %}' |
||
347 | ) |
||
348 | } |
||
349 | } |
||
350 | } |
||
351 | }, |
||
352 | 'notify': {}, |
||
353 | 'skip_notify_tasks': [] |
||
354 | } |
||
355 | } |
||
356 | } |
||
357 | } |
||
358 | |||
359 | executions.ExecutionManager.create.assert_called_with( |
||
360 | WF1_NAME, workflow_input=workflow_input, env=env, notify=NOTIFY) |
||
361 | |||
362 | @mock.patch.object( |
||
363 | workflows.WorkflowManager, 'list', |
||
364 | mock.MagicMock(return_value=[])) |
||
365 | @mock.patch.object( |
||
366 | workflows.WorkflowManager, 'get', |
||
367 | mock.MagicMock(return_value=WF1)) |
||
368 | @mock.patch.object( |
||
369 | workflows.WorkflowManager, 'create', |
||
370 | mock.MagicMock(return_value=[WF1])) |
||
371 | @mock.patch.object( |
||
372 | executions.ExecutionManager, 'create', |
||
373 | mock.MagicMock(return_value=executions.Execution(None, WF1_EXEC))) |
||
374 | def test_launch_workflow_under_parent_chain_with_jinja_parameters(self): |
||
375 | ac_ctx = { |
||
376 | 'chain': { |
||
377 | 'parameters': { |
||
378 | 'var1': 'foobar', |
||
379 | 'var2': '{{foobar}}', |
||
380 | 'var3': ['{{foo}}', '{{bar}}'], |
||
381 | 'var4': { |
||
382 | 'foobar': '{{foobar}}' |
||
383 | }, |
||
384 | } |
||
385 | } |
||
386 | } |
||
387 | |||
388 | liveaction = LiveActionDB(action=WF1_NAME, parameters=ACTION_PARAMS, context=ac_ctx) |
||
389 | liveaction, execution = action_service.request(liveaction) |
||
390 | liveaction = LiveAction.get_by_id(str(liveaction.id)) |
||
391 | self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_RUNNING) |
||
392 | |||
393 | mistral_context = liveaction.context.get('mistral', None) |
||
394 | self.assertIsNotNone(mistral_context) |
||
395 | self.assertEqual(mistral_context['execution_id'], WF1_EXEC.get('id')) |
||
396 | self.assertEqual(mistral_context['workflow_name'], WF1_EXEC.get('workflow_name')) |
||
397 | |||
398 | workflow_input = copy.deepcopy(ACTION_PARAMS) |
||
399 | workflow_input.update({'count': '3'}) |
||
400 | |||
401 | env = { |
||
402 | 'st2_execution_id': str(execution.id), |
||
403 | 'st2_liveaction_id': str(liveaction.id), |
||
404 | 'st2_action_api_url': 'http://0.0.0.0:9101/v1', |
||
405 | '__actions': { |
||
406 | 'st2.action': { |
||
407 | 'st2_context': { |
||
408 | 'api_url': 'http://0.0.0.0:9101/v1', |
||
409 | 'endpoint': 'http://0.0.0.0:9101/v1/actionexecutions', |
||
410 | 'parent': { |
||
411 | 'pack': 'mistral_tests', |
||
412 | 'execution_id': str(execution.id), |
||
413 | 'chain': { |
||
414 | 'parameters': { |
||
415 | 'var1': 'foobar', |
||
416 | 'var2': '{% raw %}{{foobar}}{% endraw %}', |
||
417 | 'var3': [ |
||
418 | '{% raw %}{{foo}}{% endraw %}', |
||
419 | '{% raw %}{{bar}}{% endraw %}' |
||
420 | ], |
||
421 | 'var4': { |
||
422 | 'foobar': '{% raw %}{{foobar}}{% endraw %}' |
||
423 | } |
||
424 | } |
||
425 | } |
||
426 | }, |
||
427 | 'notify': {}, |
||
428 | 'skip_notify_tasks': [] |
||
429 | } |
||
430 | } |
||
431 | } |
||
432 | } |
||
433 | |||
434 | executions.ExecutionManager.create.assert_called_with( |
||
435 | WF1_NAME, workflow_input=workflow_input, env=env, notify=NOTIFY) |
||
436 | |||
437 | @mock.patch.object( |
||
438 | workflows.WorkflowManager, 'list', |
||
439 | mock.MagicMock(return_value=[])) |
||
440 | @mock.patch.object( |
||
441 | workflows.WorkflowManager, 'get', |
||
442 | mock.MagicMock(return_value=WF1)) |
||
443 | @mock.patch.object( |
||
444 | workflows.WorkflowManager, 'create', |
||
445 | mock.MagicMock(return_value=[WF1])) |
||
446 | @mock.patch.object( |
||
447 | executions.ExecutionManager, 'create', |
||
448 | mock.MagicMock(return_value=executions.Execution(None, WF1_EXEC))) |
||
449 | def test_launch_workflow_under_parent_chain_with_nonetype_in_chain_context(self): |
||
450 | ac_ctx = {'chain': None} |
||
451 | |||
452 | liveaction = LiveActionDB(action=WF1_NAME, parameters=ACTION_PARAMS, context=ac_ctx) |
||
453 | liveaction, execution = action_service.request(liveaction) |
||
454 | liveaction = LiveAction.get_by_id(str(liveaction.id)) |
||
455 | self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_RUNNING) |
||
456 | |||
457 | mistral_context = liveaction.context.get('mistral', None) |
||
458 | self.assertIsNotNone(mistral_context) |
||
459 | self.assertEqual(mistral_context['execution_id'], WF1_EXEC.get('id')) |
||
460 | self.assertEqual(mistral_context['workflow_name'], WF1_EXEC.get('workflow_name')) |
||
461 | |||
462 | workflow_input = copy.deepcopy(ACTION_PARAMS) |
||
463 | workflow_input.update({'count': '3'}) |
||
464 | |||
465 | env = { |
||
466 | 'st2_execution_id': str(execution.id), |
||
467 | 'st2_liveaction_id': str(liveaction.id), |
||
468 | 'st2_action_api_url': 'http://0.0.0.0:9101/v1', |
||
469 | '__actions': { |
||
470 | 'st2.action': { |
||
471 | 'st2_context': { |
||
472 | 'api_url': 'http://0.0.0.0:9101/v1', |
||
473 | 'endpoint': 'http://0.0.0.0:9101/v1/actionexecutions', |
||
474 | 'parent': { |
||
475 | 'pack': 'mistral_tests', |
||
476 | 'execution_id': str(execution.id), |
||
477 | 'chain': None |
||
478 | }, |
||
479 | 'notify': {}, |
||
480 | 'skip_notify_tasks': [] |
||
481 | } |
||
482 | } |
||
483 | } |
||
484 | } |
||
485 | |||
486 | executions.ExecutionManager.create.assert_called_with( |
||
487 | WF1_NAME, workflow_input=workflow_input, env=env, notify=NOTIFY) |
||
488 | |||
489 | @mock.patch.object( |
||
490 | workflows.WorkflowManager, 'list', |
||
491 | mock.MagicMock(return_value=[])) |
||
492 | @mock.patch.object( |
||
493 | workflows.WorkflowManager, 'get', |
||
494 | mock.MagicMock(return_value=WF1)) |
||
495 | @mock.patch.object( |
||
496 | workflows.WorkflowManager, 'create', |
||
497 | mock.MagicMock(return_value=[WF1])) |
||
498 | @mock.patch.object( |
||
499 | executions.ExecutionManager, 'create', |
||
500 | mock.MagicMock(return_value=executions.Execution(None, WF1_EXEC))) |
||
501 | def test_launch_workflow_under_parent_chain_with_nonetype_in_params_context(self): |
||
502 | ac_ctx = {'chain': {'params': None}} |
||
503 | |||
504 | liveaction = LiveActionDB(action=WF1_NAME, parameters=ACTION_PARAMS, context=ac_ctx) |
||
505 | liveaction, execution = action_service.request(liveaction) |
||
506 | liveaction = LiveAction.get_by_id(str(liveaction.id)) |
||
507 | self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_RUNNING) |
||
508 | |||
509 | mistral_context = liveaction.context.get('mistral', None) |
||
510 | self.assertIsNotNone(mistral_context) |
||
511 | self.assertEqual(mistral_context['execution_id'], WF1_EXEC.get('id')) |
||
512 | self.assertEqual(mistral_context['workflow_name'], WF1_EXEC.get('workflow_name')) |
||
513 | |||
514 | workflow_input = copy.deepcopy(ACTION_PARAMS) |
||
515 | workflow_input.update({'count': '3'}) |
||
516 | |||
517 | env = { |
||
518 | 'st2_execution_id': str(execution.id), |
||
519 | 'st2_liveaction_id': str(liveaction.id), |
||
520 | 'st2_action_api_url': 'http://0.0.0.0:9101/v1', |
||
521 | '__actions': { |
||
522 | 'st2.action': { |
||
523 | 'st2_context': { |
||
524 | 'api_url': 'http://0.0.0.0:9101/v1', |
||
525 | 'endpoint': 'http://0.0.0.0:9101/v1/actionexecutions', |
||
526 | 'parent': { |
||
527 | 'pack': 'mistral_tests', |
||
528 | 'execution_id': str(execution.id), |
||
529 | 'chain': { |
||
530 | 'params': None |
||
531 | } |
||
532 | }, |
||
533 | 'notify': {}, |
||
534 | 'skip_notify_tasks': [] |
||
535 | } |
||
536 | } |
||
537 | } |
||
538 | } |
||
539 | |||
540 | executions.ExecutionManager.create.assert_called_with( |
||
541 | WF1_NAME, workflow_input=workflow_input, env=env, notify=NOTIFY) |
||
542 | |||
543 | @mock.patch.object( |
||
544 | workflows.WorkflowManager, 'list', |
||
545 | mock.MagicMock(return_value=[])) |
||
546 | @mock.patch.object( |
||
547 | workflows.WorkflowManager, 'get', |
||
548 | mock.MagicMock(return_value=WF1)) |
||
549 | @mock.patch.object( |
||
550 | workflows.WorkflowManager, 'create', |
||
551 | mock.MagicMock(return_value=[WF1])) |
||
552 | @mock.patch.object( |
||
553 | executions.ExecutionManager, 'create', |
||
554 | mock.MagicMock(return_value=executions.Execution(None, WF1_EXEC))) |
||
555 | def test_launch_workflow_with_st2_https(self): |
||
556 | cfg.CONF.set_override('api_url', 'https://0.0.0.0:9101', group='auth') |
||
557 | |||
558 | liveaction = LiveActionDB(action=WF1_NAME, parameters=ACTION_PARAMS) |
||
559 | liveaction, execution = action_service.request(liveaction) |
||
560 | liveaction = LiveAction.get_by_id(str(liveaction.id)) |
||
561 | self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_RUNNING) |
||
562 | |||
563 | mistral_context = liveaction.context.get('mistral', None) |
||
564 | self.assertIsNotNone(mistral_context) |
||
565 | self.assertEqual(mistral_context['execution_id'], WF1_EXEC.get('id')) |
||
566 | self.assertEqual(mistral_context['workflow_name'], WF1_EXEC.get('workflow_name')) |
||
567 | |||
568 | workflow_input = copy.deepcopy(ACTION_PARAMS) |
||
569 | workflow_input.update({'count': '3'}) |
||
570 | |||
571 | env = { |
||
572 | 'st2_execution_id': str(execution.id), |
||
573 | 'st2_liveaction_id': str(liveaction.id), |
||
574 | 'st2_action_api_url': 'https://0.0.0.0:9101/v1', |
||
575 | '__actions': { |
||
576 | 'st2.action': { |
||
577 | 'st2_context': { |
||
578 | 'api_url': 'https://0.0.0.0:9101/v1', |
||
579 | 'endpoint': 'https://0.0.0.0:9101/v1/actionexecutions', |
||
580 | 'parent': { |
||
581 | 'pack': 'mistral_tests', |
||
582 | 'execution_id': str(execution.id) |
||
583 | }, |
||
584 | 'notify': {}, |
||
585 | 'skip_notify_tasks': [] |
||
586 | } |
||
587 | } |
||
588 | } |
||
589 | } |
||
590 | |||
591 | executions.ExecutionManager.create.assert_called_with( |
||
592 | WF1_NAME, workflow_input=workflow_input, env=env, notify=NOTIFY) |
||
593 | |||
594 | @mock.patch.object( |
||
595 | workflows.WorkflowManager, 'list', |
||
596 | mock.MagicMock(return_value=[])) |
||
597 | @mock.patch.object( |
||
598 | workflows.WorkflowManager, 'get', |
||
599 | mock.MagicMock(return_value=WF1)) |
||
600 | @mock.patch.object( |
||
601 | workflows.WorkflowManager, 'create', |
||
602 | mock.MagicMock(return_value=[WF1])) |
||
603 | @mock.patch.object( |
||
604 | executions.ExecutionManager, 'create', |
||
605 | mock.MagicMock(return_value=executions.Execution(None, WF1_EXEC))) |
||
606 | def test_launch_workflow_with_notifications(self): |
||
607 | notify_data = {'on_complete': {'routes': ['slack'], |
||
608 | 'message': '"@channel: Action succeeded."', 'data': {}}} |
||
609 | |||
610 | liveaction = LiveActionDB(action=WF1_NAME, parameters=ACTION_PARAMS, notify=notify_data) |
||
611 | liveaction, execution = action_service.request(liveaction) |
||
612 | liveaction = LiveAction.get_by_id(str(liveaction.id)) |
||
613 | self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_RUNNING) |
||
614 | |||
615 | mistral_context = liveaction.context.get('mistral', None) |
||
616 | self.assertIsNotNone(mistral_context) |
||
617 | self.assertEqual(mistral_context['execution_id'], WF1_EXEC.get('id')) |
||
618 | self.assertEqual(mistral_context['workflow_name'], WF1_EXEC.get('workflow_name')) |
||
619 | |||
620 | workflow_input = copy.deepcopy(ACTION_PARAMS) |
||
621 | workflow_input.update({'count': '3'}) |
||
622 | |||
623 | env = { |
||
624 | 'st2_execution_id': str(execution.id), |
||
625 | 'st2_liveaction_id': str(liveaction.id), |
||
626 | 'st2_action_api_url': 'http://0.0.0.0:9101/v1', |
||
627 | '__actions': { |
||
628 | 'st2.action': { |
||
629 | 'st2_context': { |
||
630 | 'api_url': 'http://0.0.0.0:9101/v1', |
||
631 | 'endpoint': 'http://0.0.0.0:9101/v1/actionexecutions', |
||
632 | 'parent': { |
||
633 | 'pack': 'mistral_tests', |
||
634 | 'execution_id': str(execution.id) |
||
635 | }, |
||
636 | 'notify': NotificationsHelper.from_model(liveaction.notify), |
||
637 | 'skip_notify_tasks': [] |
||
638 | } |
||
639 | } |
||
640 | } |
||
641 | } |
||
642 | |||
643 | executions.ExecutionManager.create.assert_called_with( |
||
644 | WF1_NAME, workflow_input=workflow_input, env=env, notify=NOTIFY) |
||
645 | |||
646 | @mock.patch.object( |
||
647 | workflows.WorkflowManager, 'list', |
||
648 | mock.MagicMock(side_effect=requests.exceptions.ConnectionError('Connection refused'))) |
||
649 | def test_launch_workflow_mistral_offline(self): |
||
650 | liveaction = LiveActionDB(action=WF1_NAME, parameters=ACTION_PARAMS) |
||
651 | liveaction, execution = action_service.request(liveaction) |
||
652 | liveaction = LiveAction.get_by_id(str(liveaction.id)) |
||
653 | self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_FAILED) |
||
654 | self.assertIn('Connection refused', liveaction.result['error']) |
||
655 | |||
656 | @mock.patch.object( |
||
657 | workflows.WorkflowManager, 'list', |
||
658 | mock.MagicMock(side_effect=[requests.exceptions.ConnectionError(), []])) |
||
659 | @mock.patch.object( |
||
660 | workflows.WorkflowManager, 'get', |
||
661 | mock.MagicMock(return_value=WF1)) |
||
662 | @mock.patch.object( |
||
663 | workflows.WorkflowManager, 'create', |
||
664 | mock.MagicMock(return_value=[WF1])) |
||
665 | @mock.patch.object( |
||
666 | executions.ExecutionManager, 'create', |
||
667 | mock.MagicMock(return_value=executions.Execution(None, WF1_EXEC))) |
||
668 | def test_launch_workflow_mistral_retry(self): |
||
669 | liveaction = LiveActionDB(action=WF1_NAME, parameters=ACTION_PARAMS) |
||
670 | liveaction, execution = action_service.request(liveaction) |
||
671 | liveaction = LiveAction.get_by_id(str(liveaction.id)) |
||
672 | self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_RUNNING) |
||
673 | |||
674 | mistral_context = liveaction.context.get('mistral', None) |
||
675 | self.assertIsNotNone(mistral_context) |
||
676 | self.assertEqual(mistral_context['execution_id'], WF1_EXEC.get('id')) |
||
677 | self.assertEqual(mistral_context['workflow_name'], WF1_EXEC.get('workflow_name')) |
||
678 | |||
679 | @mock.patch.object( |
||
680 | workflows.WorkflowManager, 'list', |
||
681 | mock.MagicMock(return_value=[])) |
||
682 | @mock.patch.object( |
||
683 | workflows.WorkflowManager, 'get', |
||
684 | mock.MagicMock(return_value=WF1)) |
||
685 | @mock.patch.object( |
||
686 | workflows.WorkflowManager, 'create', |
||
687 | mock.MagicMock(side_effect=[APIException(error_message='Duplicate entry.'), WF1])) |
||
688 | @mock.patch.object( |
||
689 | executions.ExecutionManager, 'create', |
||
690 | mock.MagicMock(return_value=executions.Execution(None, WF1_EXEC))) |
||
691 | def test_launch_workflow_duplicate_error(self): |
||
692 | liveaction = LiveActionDB(action=WF1_NAME, parameters=ACTION_PARAMS) |
||
693 | liveaction, execution = action_service.request(liveaction) |
||
694 | liveaction = LiveAction.get_by_id(str(liveaction.id)) |
||
695 | self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_RUNNING) |
||
696 | |||
697 | mistral_context = liveaction.context.get('mistral', None) |
||
698 | self.assertIsNotNone(mistral_context) |
||
699 | self.assertEqual(mistral_context['execution_id'], WF1_EXEC.get('id')) |
||
700 | self.assertEqual(mistral_context['workflow_name'], WF1_EXEC.get('workflow_name')) |
||
701 | |||
702 | @mock.patch.object( |
||
703 | workflows.WorkflowManager, 'list', |
||
704 | mock.MagicMock(return_value=[])) |
||
705 | @mock.patch.object( |
||
706 | workflows.WorkflowManager, 'get', |
||
707 | mock.MagicMock(return_value=WF1_OLD)) |
||
708 | @mock.patch.object( |
||
709 | workflows.WorkflowManager, 'create', |
||
710 | mock.MagicMock(return_value=[WF1])) |
||
711 | @mock.patch.object( |
||
712 | workflows.WorkflowManager, 'update', |
||
713 | mock.MagicMock(return_value=[WF1])) |
||
714 | @mock.patch.object( |
||
715 | executions.ExecutionManager, 'create', |
||
716 | mock.MagicMock(return_value=executions.Execution(None, WF1_EXEC))) |
||
717 | def test_launch_when_workflow_definition_changed(self): |
||
718 | liveaction = LiveActionDB(action=WF1_NAME, parameters=ACTION_PARAMS) |
||
719 | liveaction, execution = action_service.request(liveaction) |
||
720 | liveaction = LiveAction.get_by_id(str(liveaction.id)) |
||
721 | self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_RUNNING) |
||
722 | |||
723 | mistral_context = liveaction.context.get('mistral', None) |
||
724 | self.assertIsNotNone(mistral_context) |
||
725 | self.assertEqual(mistral_context['execution_id'], WF1_EXEC.get('id')) |
||
726 | self.assertEqual(mistral_context['workflow_name'], WF1_EXEC.get('workflow_name')) |
||
727 | |||
728 | @mock.patch.object( |
||
729 | workflows.WorkflowManager, 'list', |
||
730 | mock.MagicMock(return_value=[])) |
||
731 | @mock.patch.object( |
||
732 | workflows.WorkflowManager, 'get', |
||
733 | mock.MagicMock(side_effect=Exception())) |
||
734 | @mock.patch.object( |
||
735 | workbooks.WorkbookManager, 'delete', |
||
736 | mock.MagicMock(side_effect=Exception())) |
||
737 | @mock.patch.object( |
||
738 | workflows.WorkflowManager, 'create', |
||
739 | mock.MagicMock(return_value=[WF1])) |
||
740 | @mock.patch.object( |
||
741 | executions.ExecutionManager, 'create', |
||
742 | mock.MagicMock(return_value=executions.Execution(None, WF1_EXEC))) |
||
743 | def test_launch_when_workflow_not_exists(self): |
||
744 | liveaction = LiveActionDB(action=WF1_NAME, parameters=ACTION_PARAMS) |
||
745 | liveaction, execution = action_service.request(liveaction) |
||
746 | liveaction = LiveAction.get_by_id(str(liveaction.id)) |
||
747 | self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_RUNNING) |
||
748 | |||
749 | mistral_context = liveaction.context.get('mistral', None) |
||
750 | self.assertIsNotNone(mistral_context) |
||
751 | self.assertEqual(mistral_context['execution_id'], WF1_EXEC.get('id')) |
||
752 | self.assertEqual(mistral_context['workflow_name'], WF1_EXEC.get('workflow_name')) |
||
753 | |||
754 | @mock.patch.object( |
||
755 | workflows.WorkflowManager, 'list', |
||
756 | mock.MagicMock(return_value=[])) |
||
757 | @mock.patch.object( |
||
758 | workflows.WorkflowManager, 'get', |
||
759 | mock.MagicMock(return_value=WF2)) |
||
760 | def test_launch_workflow_with_many_workflows(self): |
||
761 | liveaction = LiveActionDB(action=WF2_NAME, parameters=ACTION_PARAMS) |
||
762 | liveaction, execution = action_service.request(liveaction) |
||
763 | liveaction = LiveAction.get_by_id(str(liveaction.id)) |
||
764 | self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_FAILED) |
||
765 | self.assertIn('Multiple workflows is not supported.', liveaction.result['error']) |
||
766 | |||
767 | @mock.patch.object( |
||
768 | workflows.WorkflowManager, 'list', |
||
769 | mock.MagicMock(return_value=[])) |
||
770 | @mock.patch.object( |
||
771 | workflows.WorkflowManager, 'get', |
||
772 | mock.MagicMock(side_effect=Exception())) |
||
773 | def test_launch_workflow_name_mistmatch(self): |
||
774 | action_ref = TEST_PACK + '.workflow_v2_name_mismatch' |
||
775 | liveaction = LiveActionDB(action=action_ref, parameters=ACTION_PARAMS) |
||
776 | liveaction, execution = action_service.request(liveaction) |
||
777 | liveaction = LiveAction.get_by_id(str(liveaction.id)) |
||
778 | self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_FAILED) |
||
779 | self.assertIn('Name of the workflow must be the same', liveaction.result['error']) |
||
780 | |||
781 | @mock.patch.object( |
||
782 | workflows.WorkflowManager, 'list', |
||
783 | mock.MagicMock(return_value=[])) |
||
784 | @mock.patch.object( |
||
785 | workbooks.WorkbookManager, 'get', |
||
786 | mock.MagicMock(return_value=WB1)) |
||
787 | @mock.patch.object( |
||
788 | workbooks.WorkbookManager, 'create', |
||
789 | mock.MagicMock(return_value=WB1)) |
||
790 | @mock.patch.object( |
||
791 | workbooks.WorkbookManager, 'update', |
||
792 | mock.MagicMock(return_value=WB1)) |
||
793 | @mock.patch.object( |
||
794 | executions.ExecutionManager, 'create', |
||
795 | mock.MagicMock(return_value=executions.Execution(None, WB1_EXEC))) |
||
796 | def test_launch_workbook(self): |
||
797 | liveaction = LiveActionDB(action=WB1_NAME, parameters=ACTION_PARAMS) |
||
798 | liveaction, execution = action_service.request(liveaction) |
||
799 | liveaction = LiveAction.get_by_id(str(liveaction.id)) |
||
800 | self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_RUNNING) |
||
801 | |||
802 | mistral_context = liveaction.context.get('mistral', None) |
||
803 | self.assertIsNotNone(mistral_context) |
||
804 | self.assertEqual(mistral_context['execution_id'], WB1_EXEC.get('id')) |
||
805 | self.assertEqual(mistral_context['workflow_name'], WB1_EXEC.get('workflow_name')) |
||
806 | |||
807 | @mock.patch.object( |
||
808 | workflows.WorkflowManager, 'list', |
||
809 | mock.MagicMock(return_value=[])) |
||
810 | @mock.patch.object( |
||
811 | workbooks.WorkbookManager, 'get', |
||
812 | mock.MagicMock(return_value=WB2)) |
||
813 | @mock.patch.object( |
||
814 | workbooks.WorkbookManager, 'create', |
||
815 | mock.MagicMock(return_value=WB2)) |
||
816 | @mock.patch.object( |
||
817 | workbooks.WorkbookManager, 'update', |
||
818 | mock.MagicMock(return_value=WB2)) |
||
819 | @mock.patch.object( |
||
820 | executions.ExecutionManager, 'create', |
||
821 | mock.MagicMock(return_value=executions.Execution(None, WB2_EXEC))) |
||
822 | def test_launch_workbook_with_many_workflows(self): |
||
823 | liveaction = LiveActionDB(action=WB2_NAME, parameters=ACTION_PARAMS) |
||
824 | liveaction, execution = action_service.request(liveaction) |
||
825 | liveaction = LiveAction.get_by_id(str(liveaction.id)) |
||
826 | self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_RUNNING) |
||
827 | |||
828 | mistral_context = liveaction.context.get('mistral', None) |
||
829 | self.assertIsNotNone(mistral_context) |
||
830 | self.assertEqual(mistral_context['execution_id'], WB2_EXEC.get('id')) |
||
831 | self.assertEqual(mistral_context['workflow_name'], WB2_EXEC.get('workflow_name')) |
||
832 | |||
833 | @mock.patch.object( |
||
834 | workflows.WorkflowManager, 'list', |
||
835 | mock.MagicMock(return_value=[])) |
||
836 | @mock.patch.object( |
||
837 | workbooks.WorkbookManager, 'get', |
||
838 | mock.MagicMock(return_value=WB3)) |
||
839 | @mock.patch.object( |
||
840 | workbooks.WorkbookManager, 'create', |
||
841 | mock.MagicMock(return_value=WB3)) |
||
842 | @mock.patch.object( |
||
843 | workbooks.WorkbookManager, 'update', |
||
844 | mock.MagicMock(return_value=WB3)) |
||
845 | @mock.patch.object( |
||
846 | executions.ExecutionManager, 'create', |
||
847 | mock.MagicMock(return_value=executions.Execution(None, WB3_EXEC))) |
||
848 | def test_launch_workbook_with_many_workflows_no_default(self): |
||
849 | liveaction = LiveActionDB(action=WB3_NAME, parameters=ACTION_PARAMS) |
||
850 | liveaction, execution = action_service.request(liveaction) |
||
851 | liveaction = LiveAction.get_by_id(str(liveaction.id)) |
||
852 | self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_FAILED) |
||
853 | self.assertIn('Default workflow cannot be determined.', liveaction.result['error']) |
||
854 | |||
855 | @mock.patch.object( |
||
856 | workflows.WorkflowManager, 'list', |
||
857 | mock.MagicMock(return_value=[])) |
||
858 | @mock.patch.object( |
||
859 | workbooks.WorkbookManager, 'get', |
||
860 | mock.MagicMock(return_value=WB1_OLD)) |
||
861 | @mock.patch.object( |
||
862 | workbooks.WorkbookManager, 'create', |
||
863 | mock.MagicMock(return_value=WB1)) |
||
864 | @mock.patch.object( |
||
865 | workbooks.WorkbookManager, 'update', |
||
866 | mock.MagicMock(return_value=WB1)) |
||
867 | @mock.patch.object( |
||
868 | executions.ExecutionManager, 'create', |
||
869 | mock.MagicMock(return_value=executions.Execution(None, WB1_EXEC))) |
||
870 | def test_launch_when_workbook_definition_changed(self): |
||
871 | liveaction = LiveActionDB(action=WB1_NAME, parameters=ACTION_PARAMS) |
||
872 | liveaction, execution = action_service.request(liveaction) |
||
873 | liveaction = LiveAction.get_by_id(str(liveaction.id)) |
||
874 | self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_RUNNING) |
||
875 | |||
876 | mistral_context = liveaction.context.get('mistral', None) |
||
877 | self.assertIsNotNone(mistral_context) |
||
878 | self.assertEqual(mistral_context['execution_id'], WB1_EXEC.get('id')) |
||
879 | self.assertEqual(mistral_context['workflow_name'], WB1_EXEC.get('workflow_name')) |
||
880 | |||
881 | @mock.patch.object( |
||
882 | workflows.WorkflowManager, 'list', |
||
883 | mock.MagicMock(return_value=[])) |
||
884 | @mock.patch.object( |
||
885 | workbooks.WorkbookManager, 'get', |
||
886 | mock.MagicMock(side_effect=Exception())) |
||
887 | @mock.patch.object( |
||
888 | workflows.WorkflowManager, 'delete', |
||
889 | mock.MagicMock(side_effect=Exception())) |
||
890 | @mock.patch.object( |
||
891 | workbooks.WorkbookManager, 'create', |
||
892 | mock.MagicMock(return_value=WB1)) |
||
893 | @mock.patch.object( |
||
894 | executions.ExecutionManager, 'create', |
||
895 | mock.MagicMock(return_value=executions.Execution(None, WB1_EXEC))) |
||
896 | def test_launch_when_workbook_not_exists(self): |
||
897 | liveaction = LiveActionDB(action=WB1_NAME, parameters=ACTION_PARAMS) |
||
898 | liveaction, execution = action_service.request(liveaction) |
||
899 | liveaction = LiveAction.get_by_id(str(liveaction.id)) |
||
900 | self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_RUNNING) |
||
901 | |||
902 | mistral_context = liveaction.context.get('mistral', None) |
||
903 | self.assertIsNotNone(mistral_context) |
||
904 | self.assertEqual(mistral_context['execution_id'], WB1_EXEC.get('id')) |
||
905 | self.assertEqual(mistral_context['workflow_name'], WB1_EXEC.get('workflow_name')) |
||
906 | |||
907 | @mock.patch.object( |
||
908 | workflows.WorkflowManager, 'list', |
||
909 | mock.MagicMock(return_value=[])) |
||
910 | @mock.patch.object( |
||
911 | workbooks.WorkbookManager, 'get', |
||
912 | mock.MagicMock(side_effect=Exception())) |
||
913 | def test_launch_workbook_name_mismatch(self): |
||
914 | action_ref = TEST_PACK + '.workbook_v2_name_mismatch' |
||
915 | liveaction = LiveActionDB(action=action_ref, parameters=ACTION_PARAMS) |
||
916 | liveaction, execution = action_service.request(liveaction) |
||
917 | liveaction = LiveAction.get_by_id(str(liveaction.id)) |
||
918 | self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_FAILED) |
||
919 | self.assertIn('Name of the workbook must be the same', liveaction.result['error']) |
||
920 |
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: