def test_chain_cancel_cascade_to_subworkflow(self): # A temp file is created during test setup. Ensure the temp file exists. # The test action chain will stall until this file is deleted. This gives # the unit test a moment to run any test related logic. path = self.temp_file_path self.assertTrue(os.path.exists(path)) action = TEST_PACK + '.' + 'test_cancel_with_subworkflow' params = {'tempfile': path, 'message': 'foobar'} liveaction = LiveActionDB(action=action, parameters=params) liveaction, execution = action_service.request(liveaction) liveaction = LiveAction.get_by_id(str(liveaction.id)) # Wait until the liveaction is running. liveaction = self._wait_on_status(liveaction, action_constants.LIVEACTION_STATUS_RUNNING) # Wait for subworkflow to register. execution = self._wait_for_children(execution) self.assertEqual(len(execution.children), 1) # Wait until the subworkflow is running. task1_exec = ActionExecution.get_by_id(execution.children[0]) task1_live = LiveAction.get_by_id(task1_exec.liveaction['id']) task1_live = self._wait_on_status(task1_live, action_constants.LIVEACTION_STATUS_RUNNING) # Request action chain to cancel. liveaction, execution = action_service.request_cancellation(liveaction, USERNAME) # Wait until the liveaction is canceling. liveaction = self._wait_on_status(liveaction, action_constants.LIVEACTION_STATUS_CANCELING) self.assertEqual(len(execution.children), 1) # Wait until the subworkflow is canceling. task1_exec = ActionExecution.get_by_id(execution.children[0]) task1_live = LiveAction.get_by_id(task1_exec.liveaction['id']) task1_live = self._wait_on_status(task1_live, action_constants.LIVEACTION_STATUS_CANCELING) # Delete the temporary file that the action chain is waiting on. os.remove(path) self.assertFalse(os.path.exists(path)) # Wait until the liveaction is canceled. liveaction = self._wait_on_status(liveaction, action_constants.LIVEACTION_STATUS_CANCELED) self.assertEqual(len(execution.children), 1) # Wait until the subworkflow is canceled. task1_exec = ActionExecution.get_by_id(execution.children[0]) task1_live = LiveAction.get_by_id(task1_exec.liveaction['id']) task1_live = self._wait_on_status(task1_live, action_constants.LIVEACTION_STATUS_CANCELED) # Wait for non-blocking threads to complete. Ensure runner is not running. MockLiveActionPublisherNonBlocking.wait_all() # Check liveaction result. self.assertIn('tasks', liveaction.result) self.assertEqual(len(liveaction.result['tasks']), 1) subworkflow = liveaction.result['tasks'][0] self.assertEqual(len(subworkflow['result']['tasks']), 1) self.assertEqual(subworkflow['state'], action_constants.LIVEACTION_STATUS_CANCELED)
def test_crud_partial(self): # Create the DB record. obj = ActionExecutionAPI(**copy.deepcopy(self.fake_history_subtasks[0])) ActionExecution.add_or_update(ActionExecutionAPI.to_model(obj)) model = ActionExecution.get_by_id(obj.id) self.assertEqual(str(model.id), obj.id) self.assertDictEqual(model.trigger, {}) self.assertDictEqual(model.trigger_type, {}) self.assertDictEqual(model.trigger_instance, {}) self.assertDictEqual(model.rule, {}) self.assertDictEqual(model.action, self.fake_history_subtasks[0]['action']) self.assertDictEqual(model.runner, self.fake_history_subtasks[0]['runner']) doc = copy.deepcopy(self.fake_history_subtasks[0]['liveaction']) doc['start_timestamp'] = doc['start_timestamp'] doc['end_timestamp'] = doc['end_timestamp'] self.assertDictEqual(model.liveaction, doc) self.assertEqual(model.parent, self.fake_history_subtasks[0]['parent']) self.assertListEqual(model.children, []) # Update the DB record. children = [str(bson.ObjectId()), str(bson.ObjectId())] model.children = children ActionExecution.add_or_update(model) model = ActionExecution.get_by_id(obj.id) self.assertListEqual(model.children, children) # Delete the DB record. ActionExecution.delete(model) self.assertRaises(StackStormDBObjectNotFoundError, ActionExecution.get_by_id, obj.id)
def test_crud_complete(self): # Create the DB record. obj = ActionExecutionAPI(**copy.deepcopy(self.fake_history_workflow)) ActionExecution.add_or_update(ActionExecutionAPI.to_model(obj)) model = ActionExecution.get_by_id(obj.id) self.assertEqual(str(model.id), obj.id) self.assertDictEqual(model.trigger, self.fake_history_workflow['trigger']) self.assertDictEqual(model.trigger_type, self.fake_history_workflow['trigger_type']) self.assertDictEqual(model.trigger_instance, self.fake_history_workflow['trigger_instance']) self.assertDictEqual(model.rule, self.fake_history_workflow['rule']) self.assertDictEqual(model.action, self.fake_history_workflow['action']) self.assertDictEqual(model.runner, self.fake_history_workflow['runner']) doc = copy.deepcopy(self.fake_history_workflow['liveaction']) doc['start_timestamp'] = doc['start_timestamp'] doc['end_timestamp'] = doc['end_timestamp'] self.assertDictEqual(model.liveaction, doc) self.assertIsNone(getattr(model, 'parent', None)) self.assertListEqual(model.children, self.fake_history_workflow['children']) # Update the DB record. children = [str(bson.ObjectId()), str(bson.ObjectId())] model.children = children ActionExecution.add_or_update(model) model = ActionExecution.get_by_id(obj.id) self.assertListEqual(model.children, children) # Delete the DB record. ActionExecution.delete(model) self.assertRaises(ValueError, ActionExecution.get_by_id, obj.id)
def test_execution_creation_chains(self): childliveaction = self.MODELS['liveactions']['childliveaction.yaml'] child_exec = executions_util.create_execution_object(childliveaction) parent_execution_id = childliveaction.context['parent']['execution_id'] parent_execution = ActionExecution.get_by_id(parent_execution_id) child_execs = parent_execution.children self.assertTrue(str(child_exec.id) in child_execs)
def tearDown(self): for name, execution in self.executions.items(): ActionExecutionModelTest._delete([execution]) try: retrieved = ActionExecution.get_by_id(execution.id) except StackStormDBObjectNotFoundError: retrieved = None self.assertIsNone(retrieved, 'managed to retrieve after failure.')
def _wait_for_children(self, execution, interval=0.1, retries=100): # Wait until the execution has children. for i in range(0, retries): execution = ActionExecution.get_by_id(str(execution.id)) if len(getattr(execution, 'children', [])) <= 0: eventlet.sleep(interval) continue return execution
def test_cleanup_policy_delayed(self): self.reset() liveaction_db = self._create_liveaction_db() schedule_q_db = self.scheduler._create_execution_queue_item_db_from_liveaction( liveaction_db ) schedule_q_db = ActionExecutionSchedulingQueue.add_or_update(schedule_q_db) # Manually update the liveaction to policy-delayed status. # Using action_service.update_status will throw an exception on the # deprecated action_constants.LIVEACTION_STATUS_POLICY_DELAYED. liveaction_db.status = 'policy-delayed' liveaction_db = LiveAction.add_or_update(liveaction_db) execution_db = execution_service.update_execution(liveaction_db) # Check that the execution status is set to policy-delayed. liveaction_db = LiveAction.get_by_id(str(liveaction_db.id)) self.assertEqual(liveaction_db.status, 'policy-delayed') execution_db = ActionExecution.get_by_id(str(execution_db.id)) self.assertEqual(execution_db.status, 'policy-delayed') # Run the clean up logic. self.scheduling_queue._cleanup_policy_delayed() # Check that the execution status is reset to requested. liveaction_db = LiveAction.get_by_id(str(liveaction_db.id)) self.assertEqual(liveaction_db.status, action_constants.LIVEACTION_STATUS_REQUESTED) execution_db = ActionExecution.get_by_id(str(execution_db.id)) self.assertEqual(execution_db.status, action_constants.LIVEACTION_STATUS_REQUESTED) # The old entry should have been deleted. Since the execution is # reset to requested, there should be a new scheduling entry. new_schedule_q_db = self.scheduling_queue._get_next_execution() self.assertIsNotNone(new_schedule_q_db) self.assertNotEqual(str(schedule_q_db.id), str(new_schedule_q_db.id)) self.assertEqual(schedule_q_db.action_execution_id, new_schedule_q_db.action_execution_id) self.assertEqual(schedule_q_db.liveaction_id, new_schedule_q_db.liveaction_id)
def _get_parent_execution(child_liveaction_db): parent_context = child_liveaction_db.context.get('parent', None) if parent_context: parent_id = parent_context['execution_id'] try: return ActionExecution.get_by_id(parent_id) except: LOG.exception('No valid execution object found in db for id: %s' % parent_id) return None return None
def test_non_utf8_action_result_string(self): action_worker = actions_worker.get_worker() params = {"cmd": "python -c 'print \"\\x82\"'"} liveaction_db = self._get_liveaction_model(WorkerTestCase.local_action_db, params) liveaction_db = LiveAction.add_or_update(liveaction_db) execution_db = executions.create_execution_object(liveaction_db) try: action_worker._run_action(liveaction_db) except InvalidStringData: liveaction_db = LiveAction.get_by_id(liveaction_db.id) self.assertEqual(liveaction_db.status, "failed") self.assertTrue("error" in liveaction_db.result) self.assertTrue("traceback" in liveaction_db.result) execution_db = ActionExecution.get_by_id(execution_db.id) self.assertEqual(liveaction_db.status, "failed")
def test_non_utf8_action_result_string(self): action_worker = actions_worker.get_worker() params = { 'cmd': "python -c 'print \"\\x82\"'" } liveaction_db = self._get_liveaction_model(WorkerTestCase.local_action_db, params) liveaction_db = LiveAction.add_or_update(liveaction_db) execution_db = executions.create_execution_object(liveaction_db) try: action_worker._run_action(liveaction_db) except InvalidStringData: liveaction_db = LiveAction.get_by_id(liveaction_db.id) self.assertEqual(liveaction_db.status, action_constants.LIVEACTION_STATUS_FAILED) self.assertTrue('error' in liveaction_db.result) self.assertTrue('traceback' in liveaction_db.result) execution_db = ActionExecution.get_by_id(execution_db.id) self.assertEqual(liveaction_db.status, action_constants.LIVEACTION_STATUS_FAILED)
def setUp(self): self.executions = {} for name, execution in ACTIONEXECUTIONS.items(): created = ActionExecutionDB() created.action = execution['action'] created.status = execution['status'] created.runner = execution['runner'] created.liveaction = execution['liveaction'] created.result = execution['result'] saved = ActionExecutionModelTest._save_execution(created) retrieved = ActionExecution.get_by_id(saved.id) self.assertEqual(saved.action, retrieved.action, 'Same action was not returned.') self.executions[name] = retrieved
def test_non_utf8_action_result_string(self): action_worker = actions_worker.get_worker() params = {"cmd": "python -c 'print \"\\x82\"'"} liveaction_db = self._get_liveaction_model( WorkerTestCase.local_action_db, params) liveaction_db = LiveAction.add_or_update(liveaction_db) execution_db = executions.create_execution_object(liveaction_db) try: action_worker._run_action(liveaction_db) except InvalidStringData: liveaction_db = LiveAction.get_by_id(liveaction_db.id) self.assertEqual(liveaction_db.status, action_constants.LIVEACTION_STATUS_FAILED) self.assertIn("error", liveaction_db.result) self.assertIn("traceback", liveaction_db.result) execution_db = ActionExecution.get_by_id(execution_db.id) self.assertEqual(liveaction_db.status, action_constants.LIVEACTION_STATUS_FAILED)
def test_chain_pause_resume_cascade_to_parent_workflow(self): # A temp file is created during test setup. Ensure the temp file exists. # The test action chain will stall until this file is deleted. This gives # the unit test a moment to run any test related logic. path = self.temp_file_path self.assertTrue(os.path.exists(path)) action = TEST_PACK + '.' + 'test_pause_resume_with_subworkflow' params = {'tempfile': path, 'message': 'foobar'} liveaction = LiveActionDB(action=action, parameters=params) liveaction, execution = action_service.request(liveaction) liveaction = LiveAction.get_by_id(str(liveaction.id)) # Wait until the liveaction is running. liveaction = self._wait_for_status(liveaction, action_constants.LIVEACTION_STATUS_RUNNING) self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_RUNNING) # Wait for subworkflow to register. execution = self._wait_for_children(execution) self.assertEqual(len(execution.children), 1) # Wait until the subworkflow is running. task1_exec = ActionExecution.get_by_id(execution.children[0]) task1_live = LiveAction.get_by_id(task1_exec.liveaction['id']) task1_live = self._wait_for_status(task1_live, action_constants.LIVEACTION_STATUS_RUNNING) self.assertEqual(task1_live.status, action_constants.LIVEACTION_STATUS_RUNNING) # Request subworkflow to pause. task1_live, task1_exec = action_service.request_pause(task1_live, USERNAME) # Wait until the subworkflow is pausing. task1_exec = ActionExecution.get_by_id(execution.children[0]) task1_live = LiveAction.get_by_id(task1_exec.liveaction['id']) task1_live = self._wait_for_status(task1_live, action_constants.LIVEACTION_STATUS_PAUSING) extra_info = str(task1_live) self.assertEqual(task1_live.status, action_constants.LIVEACTION_STATUS_PAUSING, extra_info) # Delete the temporary file that the action chain is waiting on. os.remove(path) self.assertFalse(os.path.exists(path)) # Wait until the subworkflow is paused. task1_exec = ActionExecution.get_by_id(execution.children[0]) task1_live = LiveAction.get_by_id(task1_exec.liveaction['id']) task1_live = self._wait_for_status(task1_live, action_constants.LIVEACTION_STATUS_PAUSED) extra_info = str(task1_live) self.assertEqual(task1_live.status, action_constants.LIVEACTION_STATUS_PAUSED, extra_info) # Wait until the parent liveaction is paused. liveaction = self._wait_for_status(liveaction, action_constants.LIVEACTION_STATUS_PAUSED) extra_info = str(liveaction) self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_PAUSED, extra_info) self.assertEqual(len(execution.children), 1) # Wait for non-blocking threads to complete. Ensure runner is not running. MockLiveActionPublisherNonBlocking.wait_all() # Check liveaction result. self.assertIn('tasks', liveaction.result) self.assertEqual(len(liveaction.result['tasks']), 1) subworkflow = liveaction.result['tasks'][0] self.assertEqual(len(subworkflow['result']['tasks']), 1) self.assertEqual(subworkflow['state'], action_constants.LIVEACTION_STATUS_PAUSED) # Request subworkflow to resume. task1_live, task1_exec = action_service.request_resume(task1_live, USERNAME) # Wait until the subworkflow is paused. task1_exec = ActionExecution.get_by_id(execution.children[0]) task1_live = LiveAction.get_by_id(task1_exec.liveaction['id']) task1_live = self._wait_for_status(task1_live, action_constants.LIVEACTION_STATUS_SUCCEEDED) self.assertEqual(task1_live.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) # The parent workflow will stay paused. liveaction = self._wait_for_status(liveaction, action_constants.LIVEACTION_STATUS_PAUSED) self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_PAUSED) # Wait for non-blocking threads to complete. MockLiveActionPublisherNonBlocking.wait_all() # Check liveaction result of the parent, which should stay the same # because only the subworkflow was resumed. self.assertIn('tasks', liveaction.result) self.assertEqual(len(liveaction.result['tasks']), 1) subworkflow = liveaction.result['tasks'][0] self.assertEqual(len(subworkflow['result']['tasks']), 1) self.assertEqual(subworkflow['state'], action_constants.LIVEACTION_STATUS_PAUSED) # Request parent workflow to resume. liveaction, execution = action_service.request_resume(liveaction, USERNAME) # Wait until the liveaction is completed. liveaction = self._wait_for_status(liveaction, action_constants.LIVEACTION_STATUS_SUCCEEDED) self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) # Wait for non-blocking threads to complete. MockLiveActionPublisherNonBlocking.wait_all() # Check liveaction result. self.assertIn('tasks', liveaction.result) self.assertEqual(len(liveaction.result['tasks']), 2) subworkflow = liveaction.result['tasks'][0] self.assertEqual(len(subworkflow['result']['tasks']), 2) self.assertEqual(subworkflow['state'], action_constants.LIVEACTION_STATUS_SUCCEEDED)
def is_execution_canceled(execution_id): try: execution = ActionExecution.get_by_id(execution_id) return execution.status == LIVEACTION_STATUS_CANCELED except: return False # XXX: What to do here?
def test_chain_pause_resume_cascade_to_parent_workflow(self): # A temp file is created during test setup. Ensure the temp file exists. # The test action chain will stall until this file is deleted. This gives # the unit test a moment to run any test related logic. path = self.temp_file_path self.assertTrue(os.path.exists(path)) action = TEST_PACK + "." + "test_pause_resume_with_subworkflow" params = {"tempfile": path, "message": "foobar"} liveaction = LiveActionDB(action=action, parameters=params) liveaction, execution = action_service.request(liveaction) liveaction = LiveAction.get_by_id(str(liveaction.id)) # Wait until the liveaction is running. liveaction = self._wait_for_status( liveaction, action_constants.LIVEACTION_STATUS_RUNNING) self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_RUNNING) # Wait for subworkflow to register. execution = self._wait_for_children(execution) self.assertEqual(len(execution.children), 1) # Wait until the subworkflow is running. task1_exec = ActionExecution.get_by_id(execution.children[0]) task1_live = LiveAction.get_by_id(task1_exec.liveaction["id"]) task1_live = self._wait_for_status( task1_live, action_constants.LIVEACTION_STATUS_RUNNING) self.assertEqual(task1_live.status, action_constants.LIVEACTION_STATUS_RUNNING) # Request subworkflow to pause. task1_live, task1_exec = action_service.request_pause( task1_live, USERNAME) # Wait until the subworkflow is pausing. task1_exec = ActionExecution.get_by_id(execution.children[0]) task1_live = LiveAction.get_by_id(task1_exec.liveaction["id"]) task1_live = self._wait_for_status( task1_live, action_constants.LIVEACTION_STATUS_PAUSING) extra_info = str(task1_live) self.assertEqual(task1_live.status, action_constants.LIVEACTION_STATUS_PAUSING, extra_info) # Delete the temporary file that the action chain is waiting on. os.remove(path) self.assertFalse(os.path.exists(path)) # Wait until the subworkflow is paused. task1_exec = ActionExecution.get_by_id(execution.children[0]) task1_live = LiveAction.get_by_id(task1_exec.liveaction["id"]) task1_live = self._wait_for_status( task1_live, action_constants.LIVEACTION_STATUS_PAUSED) extra_info = str(task1_live) self.assertEqual(task1_live.status, action_constants.LIVEACTION_STATUS_PAUSED, extra_info) # Wait until the parent liveaction is paused. liveaction = self._wait_for_status( liveaction, action_constants.LIVEACTION_STATUS_PAUSED) extra_info = str(liveaction) self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_PAUSED, extra_info) self.assertEqual(len(execution.children), 1) # Wait for non-blocking threads to complete. Ensure runner is not running. MockLiveActionPublisherNonBlocking.wait_all() # Check liveaction result. self.assertIn("tasks", liveaction.result) self.assertEqual(len(liveaction.result["tasks"]), 1) subworkflow = liveaction.result["tasks"][0] self.assertEqual(len(subworkflow["result"]["tasks"]), 1) self.assertEqual(subworkflow["state"], action_constants.LIVEACTION_STATUS_PAUSED) # Request subworkflow to resume. task1_live, task1_exec = action_service.request_resume( task1_live, USERNAME) # Wait until the subworkflow is paused. task1_exec = ActionExecution.get_by_id(execution.children[0]) task1_live = LiveAction.get_by_id(task1_exec.liveaction["id"]) task1_live = self._wait_for_status( task1_live, action_constants.LIVEACTION_STATUS_SUCCEEDED) self.assertEqual(task1_live.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) # The parent workflow will stay paused. liveaction = self._wait_for_status( liveaction, action_constants.LIVEACTION_STATUS_PAUSED) self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_PAUSED) # Wait for non-blocking threads to complete. MockLiveActionPublisherNonBlocking.wait_all() # Check liveaction result of the parent, which should stay the same # because only the subworkflow was resumed. self.assertIn("tasks", liveaction.result) self.assertEqual(len(liveaction.result["tasks"]), 1) subworkflow = liveaction.result["tasks"][0] self.assertEqual(len(subworkflow["result"]["tasks"]), 1) self.assertEqual(subworkflow["state"], action_constants.LIVEACTION_STATUS_PAUSED) # Request parent workflow to resume. liveaction, execution = action_service.request_resume( liveaction, USERNAME) # Wait until the liveaction is completed. liveaction = self._wait_for_status( liveaction, action_constants.LIVEACTION_STATUS_SUCCEEDED) self.assertEqual(liveaction.status, action_constants.LIVEACTION_STATUS_SUCCEEDED) # Wait for non-blocking threads to complete. MockLiveActionPublisherNonBlocking.wait_all() # Check liveaction result. self.assertIn("tasks", liveaction.result) self.assertEqual(len(liveaction.result["tasks"]), 2) subworkflow = liveaction.result["tasks"][0] self.assertEqual(len(subworkflow["result"]["tasks"]), 2) self.assertEqual(subworkflow["state"], action_constants.LIVEACTION_STATUS_SUCCEEDED)
def test_chain_cancel_cascade_to_parent_workflow(self): # A temp file is created during test setup. Ensure the temp file exists. # The test action chain will stall until this file is deleted. This gives # the unit test a moment to run any test related logic. path = self.temp_file_path self.assertTrue(os.path.exists(path)) action = TEST_PACK + '.' + 'test_cancel_with_subworkflow' params = {'tempfile': path, 'message': 'foobar'} liveaction = LiveActionDB(action=action, parameters=params) liveaction, execution = action_service.request(liveaction) liveaction = LiveAction.get_by_id(str(liveaction.id)) # Wait until the liveaction is running. liveaction = self._wait_on_status( liveaction, action_constants.LIVEACTION_STATUS_RUNNING) # Wait for subworkflow to register. execution = self._wait_for_children(execution) self.assertEqual(len(execution.children), 1) # Wait until the subworkflow is running. task1_exec = ActionExecution.get_by_id(execution.children[0]) task1_live = LiveAction.get_by_id(task1_exec.liveaction['id']) task1_live = self._wait_on_status( task1_live, action_constants.LIVEACTION_STATUS_RUNNING) # Request subworkflow to cancel. task1_live, task1_exec = action_service.request_cancellation( task1_live, USERNAME) # Wait until the subworkflow is canceling. task1_exec = ActionExecution.get_by_id(execution.children[0]) task1_live = LiveAction.get_by_id(task1_exec.liveaction['id']) task1_live = self._wait_on_status( task1_live, action_constants.LIVEACTION_STATUS_CANCELING) # Delete the temporary file that the action chain is waiting on. os.remove(path) self.assertFalse(os.path.exists(path)) # Wait until the subworkflow is canceled. task1_exec = ActionExecution.get_by_id(execution.children[0]) task1_live = LiveAction.get_by_id(task1_exec.liveaction['id']) task1_live = self._wait_on_status( task1_live, action_constants.LIVEACTION_STATUS_CANCELED) # Wait until the parent liveaction is canceled. liveaction = self._wait_on_status( liveaction, action_constants.LIVEACTION_STATUS_CANCELED) self.assertEqual(len(execution.children), 1) # Wait for non-blocking threads to complete. Ensure runner is not running. MockLiveActionPublisherNonBlocking.wait_all() # Check liveaction result. self.assertIn('tasks', liveaction.result) self.assertEqual(len(liveaction.result['tasks']), 1) subworkflow = liveaction.result['tasks'][0] self.assertEqual(len(subworkflow['result']['tasks']), 1) self.assertEqual(subworkflow['state'], action_constants.LIVEACTION_STATUS_CANCELED)
def test_migrate_executions(self): ActionExecutionDB._meta["allow_inheritance"] = True LiveActionDB._meta["allow_inheritance"] = True class ActionExecutionDB_OldFieldType(ActionExecutionDB): result = stormbase.EscapedDynamicField(default={}) class LiveActionDB_OldFieldType(LiveActionDB): result = stormbase.EscapedDynamicField(default={}) execution_dbs = ActionExecution.query( __raw__={"result": { "$not": { "$type": "binData", }, }}) self.assertEqual(len(execution_dbs), 0) execution_dbs = ActionExecution.query(__raw__={ "result": { "$type": "object", }, }) self.assertEqual(len(execution_dbs), 0) # 1. Insert data in old format liveaction_1_db = LiveActionDB_OldFieldType() liveaction_1_db.action = "foo.bar" liveaction_1_db.status = action_constants.LIVEACTION_STATUS_FAILED liveaction_1_db.result = MOCK_RESULT_1 liveaction_1_db.start_timestamp = datetime.datetime.utcnow().replace( tzinfo=datetime.timezone.utc) liveaction_1_db = LiveAction.add_or_update(liveaction_1_db, publish=False) execution_1_db = ActionExecutionDB_OldFieldType() execution_1_db.action = {"a": 1} execution_1_db.runner = {"a": 1} execution_1_db.liveaction = {"id": liveaction_1_db.id} execution_1_db.status = action_constants.LIVEACTION_STATUS_FAILED execution_1_db.result = MOCK_RESULT_1 execution_1_db.start_timestamp = datetime.datetime.utcnow().replace( tzinfo=datetime.timezone.utc) execution_1_db = ActionExecution.add_or_update(execution_1_db, publish=False) # This execution is not in a final state yet so it should not be migrated liveaction_2_db = LiveActionDB_OldFieldType() liveaction_2_db.action = "foo.bar2" liveaction_2_db.status = action_constants.LIVEACTION_STATUS_RUNNING liveaction_2_db.result = MOCK_RESULT_2 liveaction_2_db.start_timestamp = datetime.datetime.utcnow().replace( tzinfo=datetime.timezone.utc) liveaction_2_db = LiveAction.add_or_update(liveaction_2_db, publish=False) execution_2_db = ActionExecutionDB_OldFieldType() execution_2_db.action = {"a": 2} execution_2_db.runner = {"a": 2} execution_2_db.liveaction = {"id": liveaction_2_db.id} execution_2_db.status = action_constants.LIVEACTION_STATUS_RUNNING execution_2_db.result = MOCK_RESULT_2 execution_2_db.start_timestamp = datetime.datetime.utcnow().replace( tzinfo=datetime.timezone.utc) execution_2_db = ActionExecution.add_or_update(execution_2_db, publish=False) # This object is older than the default threshold so it should not be migrated execution_3_db = ActionExecutionDB_OldFieldType() execution_3_db.action = {"a": 2} execution_3_db.runner = {"a": 2} execution_3_db.liveaction = {"id": liveaction_2_db.id} execution_3_db.status = action_constants.LIVEACTION_STATUS_SUCCEEDED execution_3_db.result = MOCK_RESULT_1 execution_3_db.start_timestamp = datetime.datetime.utcfromtimestamp( 0).replace(tzinfo=datetime.timezone.utc) execution_3_db = ActionExecution.add_or_update(execution_3_db, publish=False) # Verify data has been inserted in old format execution_dbs = ActionExecution.query(__raw__={ "result": { "$type": "object", }, }) self.assertEqual(len(execution_dbs), 3) execution_dbs = ActionExecution.query( __raw__={"result": { "$not": { "$type": "binData", }, }}) self.assertEqual(len(execution_dbs), 3) execution_dbs = ActionExecution.query(__raw__={ "result": { "$type": "binData", }, }) self.assertEqual(len(execution_dbs), 0) liveaction_dbs = LiveAction.query(__raw__={ "result": { "$type": "object", }, }) self.assertEqual(len(liveaction_dbs), 2) liveaction_dbs = LiveAction.query( __raw__={"result": { "$not": { "$type": "binData", }, }}) self.assertEqual(len(liveaction_dbs), 2) liveaction_dbs = LiveAction.query(__raw__={ "result": { "$type": "binData", }, }) self.assertEqual(len(liveaction_dbs), 0) # Update inserted documents and remove special _cls field added by mongoengine. We need to # do that here due to how mongoengine works with subclasses. ActionExecution.query(__raw__={ "result": { "$type": "object", }, }).update(set___cls="ActionExecutionDB") LiveAction.query(__raw__={ "result": { "$type": "object", }, }).update(set___cls="LiveActionDB") # 2. Run migration start_dt = datetime.datetime.utcnow().replace( tzinfo=datetime.timezone.utc) - datetime.timedelta(hours=2) end_dt = datetime.datetime.utcnow().replace( tzinfo=datetime.timezone.utc) migration_module.migrate_executions(start_dt=start_dt, end_dt=end_dt) # 3. Verify data has been migrated - only 1 item should have been migrated since it's in a # completed state execution_dbs = ActionExecution.query(__raw__={ "result": { "$type": "object", }, }) self.assertEqual(len(execution_dbs), 2) execution_dbs = ActionExecution.query(__raw__={ "result": { "$type": "binData", }, }) self.assertEqual(len(execution_dbs), 1) execution_db_1_retrieved = ActionExecution.get_by_id(execution_1_db.id) self.assertEqual(execution_db_1_retrieved.result, MOCK_RESULT_1) execution_db_2_retrieved = ActionExecution.get_by_id(execution_2_db.id) self.assertEqual(execution_db_2_retrieved.result, MOCK_RESULT_2) liveaction_db_1_retrieved = LiveAction.get_by_id(liveaction_1_db.id) self.assertEqual(liveaction_db_1_retrieved.result, MOCK_RESULT_1) liveaction_db_2_retrieved = LiveAction.get_by_id(liveaction_2_db.id) self.assertEqual(liveaction_db_2_retrieved.result, MOCK_RESULT_2)
def _get_rerun_reference(self, context): execution_id = context.get('re-run', {}).get('ref') return ActionExecution.get_by_id( execution_id) if execution_id else None
def _get_rerun_reference(self, context): execution_id = context.get('re-run', {}).get('ref') return ActionExecution.get_by_id(execution_id) if execution_id else None