예제 #1
0
    def test_action_stdout_and_stderr_is_stored_in_the_db(
            self, mock_spawn, mock_popen):
        # Feature is enabled
        cfg.CONF.set_override(name="stream_output",
                              group="actionrunner",
                              override=True)

        values = {"delimiter": ACTION_OUTPUT_RESULT_DELIMITER}

        # Note: We need to mock spawn function so we can test everything in single event loop
        # iteration
        mock_spawn.side_effect = blocking_eventlet_spawn

        # No output to stdout and no result (implicit None)
        mock_stdout = [
            "pre result line 1\n",
            "pre result line 2\n",
            "%(delimiter)sTrue%(delimiter)s" % values,
            "post result line 1",
        ]
        mock_stderr = ["stderr line 1\n", "stderr line 2\n", "stderr line 3\n"]

        mock_process = mock.Mock()
        mock_process.returncode = 0
        mock_popen.return_value = mock_process
        mock_process.stdout.closed = False
        mock_process.stderr.closed = False
        mock_process.stdout.readline = make_mock_stream_readline(
            mock_process.stdout, mock_stdout, stop_counter=4)
        mock_process.stderr.readline = make_mock_stream_readline(
            mock_process.stderr, mock_stderr, stop_counter=3)

        runner = self._get_mock_runner_obj()
        runner.entry_point = PASCAL_ROW_ACTION_PATH
        runner.pre_run()
        (_, output, _) = runner.run({"row_index": 4})

        self.assertMultiLineEqual(
            output["stdout"],
            "pre result line 1\npre result line 2\npost result line 1")
        self.assertMultiLineEqual(
            output["stderr"], "stderr line 1\nstderr line 2\nstderr line 3\n")
        self.assertEqual(output["result"], "True")
        self.assertEqual(output["exit_code"], 0)

        # Verify stdout and stderr lines have been correctly stored in the db
        # Note - result delimiter should not be stored in the db
        output_dbs = ActionExecutionOutput.query(output_type="stdout")
        self.assertEqual(len(output_dbs), 3)
        self.assertEqual(output_dbs[0].runner_ref, "python-script")
        self.assertEqual(output_dbs[0].data, mock_stdout[0])
        self.assertEqual(output_dbs[1].data, mock_stdout[1])
        self.assertEqual(output_dbs[2].data, mock_stdout[3])

        output_dbs = ActionExecutionOutput.query(output_type="stderr")
        self.assertEqual(len(output_dbs), 3)
        self.assertEqual(output_dbs[0].runner_ref, "python-script")
        self.assertEqual(output_dbs[0].data, mock_stderr[0])
        self.assertEqual(output_dbs[1].data, mock_stderr[1])
        self.assertEqual(output_dbs[2].data, mock_stderr[2])
예제 #2
0
    def test_no_timestamp_doesnt_delete_things(self):
        now = date_utils.get_datetime_utc_now()
        exec_model = copy.deepcopy(self.models['executions']['execution1.yaml'])
        exec_model['start_timestamp'] = now - timedelta(days=15)
        exec_model['end_timestamp'] = now - timedelta(days=14)
        exec_model['status'] = action_constants.LIVEACTION_STATUS_SUCCEEDED
        exec_model['id'] = bson.ObjectId()
        ActionExecution.add_or_update(exec_model)

        # Insert corresponding stdout and stderr db mock models
        self._insert_mock_stdout_and_stderr_objects_for_execution(exec_model['id'], count=3)

        execs = ActionExecution.get_all()
        self.assertEqual(len(execs), 1)
        stdout_dbs = ActionExecutionOutput.query(output_type='stdout')
        self.assertEqual(len(stdout_dbs), 3)
        stderr_dbs = ActionExecutionOutput.query(output_type='stderr')
        self.assertEqual(len(stderr_dbs), 3)

        expected_msg = 'Specify a valid timestamp'
        self.assertRaisesRegexp(ValueError, expected_msg, purge_executions,
                                logger=LOG, timestamp=None)
        execs = ActionExecution.get_all()
        self.assertEqual(len(execs), 1)
        stdout_dbs = ActionExecutionOutput.query(output_type='stdout')
        self.assertEqual(len(stdout_dbs), 3)
        stderr_dbs = ActionExecutionOutput.query(output_type='stderr')
        self.assertEqual(len(stderr_dbs), 3)
예제 #3
0
    def test_no_timestamp_doesnt_delete_things(self):
        now = date_utils.get_datetime_utc_now()
        exec_model = copy.deepcopy(
            self.models['executions']['execution1.yaml'])
        exec_model['start_timestamp'] = now - timedelta(days=15)
        exec_model['end_timestamp'] = now - timedelta(days=14)
        exec_model['status'] = action_constants.LIVEACTION_STATUS_SUCCEEDED
        exec_model['id'] = bson.ObjectId()
        ActionExecution.add_or_update(exec_model)

        # Insert corresponding stdout and stderr db mock models
        self._insert_mock_stdout_and_stderr_objects_for_execution(
            exec_model['id'], count=3)

        execs = ActionExecution.get_all()
        self.assertEqual(len(execs), 1)
        stdout_dbs = ActionExecutionOutput.query(output_type='stdout')
        self.assertEqual(len(stdout_dbs), 3)
        stderr_dbs = ActionExecutionOutput.query(output_type='stderr')
        self.assertEqual(len(stderr_dbs), 3)

        expected_msg = 'Specify a valid timestamp'
        self.assertRaisesRegexp(ValueError,
                                expected_msg,
                                purge_executions,
                                logger=LOG,
                                timestamp=None)
        execs = ActionExecution.get_all()
        self.assertEqual(len(execs), 1)
        stdout_dbs = ActionExecutionOutput.query(output_type='stdout')
        self.assertEqual(len(stdout_dbs), 3)
        stderr_dbs = ActionExecutionOutput.query(output_type='stderr')
        self.assertEqual(len(stderr_dbs), 3)
    def test_action_stdout_and_stderr_is_stored_in_the_db(
            self, mock_spawn, mock_popen):
        # Feature is enabled
        cfg.CONF.set_override(name='stream_output',
                              group='actionrunner',
                              override=True)

        values = {'delimiter': ACTION_OUTPUT_RESULT_DELIMITER}

        # Note: We need to mock spawn function so we can test everything in single event loop
        # iteration
        mock_spawn.side_effect = blocking_eventlet_spawn

        # No output to stdout and no result (implicit None)
        mock_stdout = [
            'pre result line 1\n', 'pre result line 2\n',
            '%(delimiter)sTrue%(delimiter)s' % values, 'post result line 1'
        ]
        mock_stderr = ['stderr line 1\n', 'stderr line 2\n', 'stderr line 3\n']

        mock_process = mock.Mock()
        mock_process.returncode = 0
        mock_popen.return_value = mock_process
        mock_process.stdout.closed = False
        mock_process.stderr.closed = False
        mock_process.stdout.readline = make_mock_stream_readline(
            mock_process.stdout, mock_stdout, stop_counter=4)
        mock_process.stderr.readline = make_mock_stream_readline(
            mock_process.stderr, mock_stderr, stop_counter=3)

        runner = self._get_mock_runner_obj()
        runner.entry_point = PASCAL_ROW_ACTION_PATH
        runner.container_service = service.RunnerContainerService()
        runner.pre_run()
        (_, output, _) = runner.run({'row_index': 4})

        self.assertEqual(
            output['stdout'],
            'pre result line 1\npre result line 2\npost result line 1')
        self.assertEqual(output['stderr'],
                         'stderr line 1\nstderr line 2\nstderr line 3\n')
        self.assertEqual(output['result'], 'True')
        self.assertEqual(output['exit_code'], 0)

        # Verify stdout and stderr lines have been correctly stored in the db
        # Note - result delimiter should not be stored in the db
        output_dbs = ActionExecutionOutput.query(output_type='stdout')
        self.assertEqual(len(output_dbs), 3)
        self.assertEqual(output_dbs[0].runner_ref, 'python-script')
        self.assertEqual(output_dbs[0].data, mock_stdout[0])
        self.assertEqual(output_dbs[1].data, mock_stdout[1])
        self.assertEqual(output_dbs[2].data, mock_stdout[3])

        output_dbs = ActionExecutionOutput.query(output_type='stderr')
        self.assertEqual(len(output_dbs), 3)
        self.assertEqual(output_dbs[0].runner_ref, 'python-script')
        self.assertEqual(output_dbs[0].data, mock_stderr[0])
        self.assertEqual(output_dbs[1].data, mock_stderr[1])
        self.assertEqual(output_dbs[2].data, mock_stderr[2])
예제 #5
0
    def test_action_stdout_and_stderr_is_stored_in_the_db(self, mock_spawn, mock_popen):
        # Feature is enabled
        cfg.CONF.set_override(name='stream_output', group='actionrunner', override=True)

        values = {'delimiter': ACTION_OUTPUT_RESULT_DELIMITER}

        # Note: We need to mock spawn function so we can test everything in single event loop
        # iteration
        mock_spawn.side_effect = blocking_eventlet_spawn

        # No output to stdout and no result (implicit None)
        mock_stdout = [
            'pre result line 1\n',
            'pre result line 2\n',
            '%(delimiter)sTrue%(delimiter)s' % values,
            'post result line 1'
        ]
        mock_stderr = [
            'stderr line 1\n',
            'stderr line 2\n',
            'stderr line 3\n'
        ]

        mock_process = mock.Mock()
        mock_process.returncode = 0
        mock_popen.return_value = mock_process
        mock_process.stdout.closed = False
        mock_process.stderr.closed = False
        mock_process.stdout.readline = make_mock_stream_readline(mock_process.stdout, mock_stdout,
                                                                 stop_counter=4)
        mock_process.stderr.readline = make_mock_stream_readline(mock_process.stderr, mock_stderr,
                                                                 stop_counter=3)

        runner = self._get_mock_runner_obj()
        runner.entry_point = PASCAL_ROW_ACTION_PATH
        runner.pre_run()
        (_, output, _) = runner.run({'row_index': 4})

        self.assertEqual(output['stdout'],
                         'pre result line 1\npre result line 2\npost result line 1')
        self.assertEqual(output['stderr'], 'stderr line 1\nstderr line 2\nstderr line 3\n')
        self.assertEqual(output['result'], 'True')
        self.assertEqual(output['exit_code'], 0)

        # Verify stdout and stderr lines have been correctly stored in the db
        # Note - result delimiter should not be stored in the db
        output_dbs = ActionExecutionOutput.query(output_type='stdout')
        self.assertEqual(len(output_dbs), 3)
        self.assertEqual(output_dbs[0].runner_ref, 'python-script')
        self.assertEqual(output_dbs[0].data, mock_stdout[0])
        self.assertEqual(output_dbs[1].data, mock_stdout[1])
        self.assertEqual(output_dbs[2].data, mock_stdout[3])

        output_dbs = ActionExecutionOutput.query(output_type='stderr')
        self.assertEqual(len(output_dbs), 3)
        self.assertEqual(output_dbs[0].runner_ref, 'python-script')
        self.assertEqual(output_dbs[0].data, mock_stderr[0])
        self.assertEqual(output_dbs[1].data, mock_stderr[1])
        self.assertEqual(output_dbs[2].data, mock_stderr[2])
    def test_action_stdout_and_stderr_is_stored_in_the_db(
            self, mock_spawn, mock_popen):
        # Feature is enabled
        cfg.CONF.set_override(name='stream_output',
                              group='actionrunner',
                              override=True)

        # Note: We need to mock spawn function so we can test everything in single event loop
        # iteration
        mock_spawn.side_effect = blocking_eventlet_spawn

        # No output to stdout and no result (implicit None)
        mock_stdout = [
            'stdout line 1\n',
            'stdout line 2\n',
        ]
        mock_stderr = ['stderr line 1\n', 'stderr line 2\n', 'stderr line 3\n']

        mock_process = mock.Mock()
        mock_process.returncode = 0
        mock_popen.return_value = mock_process
        mock_process.stdout.closed = False
        mock_process.stderr.closed = False
        mock_process.stdout.readline = make_mock_stream_readline(
            mock_process.stdout, mock_stdout, stop_counter=2)
        mock_process.stderr.readline = make_mock_stream_readline(
            mock_process.stderr, mock_stderr, stop_counter=3)

        models = self.fixtures_loader.load_models(
            fixtures_pack='generic', fixtures_dict={'actions': ['local.yaml']})
        action_db = models['actions']['local.yaml']

        runner = self._get_runner(action_db, cmd='echo $ST2_ACTION_API_URL')
        runner.pre_run()
        status, result, _ = runner.run({})
        runner.post_run(status, result)

        self.assertEquals(status, action_constants.LIVEACTION_STATUS_SUCCEEDED)

        self.assertEqual(result['stdout'], 'stdout line 1\nstdout line 2')
        self.assertEqual(result['stderr'],
                         'stderr line 1\nstderr line 2\nstderr line 3')
        self.assertEqual(result['return_code'], 0)

        # Verify stdout and stderr lines have been correctly stored in the db
        output_dbs = ActionExecutionOutput.query(output_type='stdout')
        self.assertEqual(len(output_dbs), 2)
        self.assertEqual(output_dbs[0].data, mock_stdout[0])
        self.assertEqual(output_dbs[1].data, mock_stdout[1])

        output_dbs = ActionExecutionOutput.query(output_type='stderr')
        self.assertEqual(len(output_dbs), 3)
        self.assertEqual(output_dbs[0].data, mock_stderr[0])
        self.assertEqual(output_dbs[1].data, mock_stderr[1])
        self.assertEqual(output_dbs[2].data, mock_stderr[2])
예제 #7
0
    def test_action_stdout_and_stderr_is_stored_in_the_db(self, mock_spawn, mock_popen):
        # Feature is enabled
        cfg.CONF.set_override(name='stream_output', group='actionrunner', override=True)

        # Note: We need to mock spawn function so we can test everything in single event loop
        # iteration
        mock_spawn.side_effect = blocking_eventlet_spawn

        # No output to stdout and no result (implicit None)
        mock_stdout = [
            'stdout line 1\n',
            'stdout line 2\n',
        ]
        mock_stderr = [
            'stderr line 1\n',
            'stderr line 2\n',
            'stderr line 3\n'
        ]

        mock_process = mock.Mock()
        mock_process.returncode = 0
        mock_popen.return_value = mock_process
        mock_process.stdout.closed = False
        mock_process.stderr.closed = False
        mock_process.stdout.readline = make_mock_stream_readline(mock_process.stdout, mock_stdout,
                                                                 stop_counter=2)
        mock_process.stderr.readline = make_mock_stream_readline(mock_process.stderr, mock_stderr,
                                                                 stop_counter=3)

        models = self.fixtures_loader.load_models(
            fixtures_pack='generic', fixtures_dict={'actions': ['local.yaml']})
        action_db = models['actions']['local.yaml']

        runner = self._get_runner(action_db, cmd='echo $ST2_ACTION_API_URL')
        runner.pre_run()
        status, result, _ = runner.run({})
        runner.post_run(status, result)

        self.assertEquals(status, action_constants.LIVEACTION_STATUS_SUCCEEDED)

        self.assertEqual(result['stdout'], 'stdout line 1\nstdout line 2')
        self.assertEqual(result['stderr'], 'stderr line 1\nstderr line 2\nstderr line 3')
        self.assertEqual(result['return_code'], 0)

        # Verify stdout and stderr lines have been correctly stored in the db
        output_dbs = ActionExecutionOutput.query(output_type='stdout')
        self.assertEqual(len(output_dbs), 2)
        self.assertEqual(output_dbs[0].data, mock_stdout[0])
        self.assertEqual(output_dbs[1].data, mock_stdout[1])

        output_dbs = ActionExecutionOutput.query(output_type='stderr')
        self.assertEqual(len(output_dbs), 3)
        self.assertEqual(output_dbs[0].data, mock_stderr[0])
        self.assertEqual(output_dbs[1].data, mock_stderr[1])
        self.assertEqual(output_dbs[2].data, mock_stderr[2])
예제 #8
0
        def existing_output_iter():
            # Consume and return all of the existing lines
            # pylint: disable=no-member
            output_dbs = ActionExecutionOutput.query(execution_id=execution_id, **query_filters)

            output = ''.join([output_db.data for output_db in output_dbs])
            yield six.binary_type(output.encode('utf-8'))
예제 #9
0
        def existing_output_iter():
            # Consume and return all of the existing lines
            # pylint: disable=no-member
            output_dbs = ActionExecutionOutput.query(execution_id=execution_id, **query_filters)

            output = ''.join([output_db.data for output_db in output_dbs])
            yield six.binary_type(output.encode('utf-8'))
예제 #10
0
        def existing_output_iter():
            # Consume and return all of the existing lines
            # pylint: disable=no-member
            output_dbs = ActionExecutionOutput.query(execution_id=execution_id, **query_filters)

            # Note: We return all at once instead of yield line by line to avoid multiple socket
            # writes and to achieve better performance
            output = ''.join([output_db.data for output_db in output_dbs])
            yield six.binary_type(output.encode('utf-8'))
예제 #11
0
파일: executions.py 프로젝트: nzlosh/st2
        def existing_output_iter():
            # Consume and return all of the existing lines
            output_dbs = ActionExecutionOutput.query(execution_id=execution_id, **query_filters)

            # Note: We return all at once instead of yield line by line to avoid multiple socket
            # writes and to achieve better performance
            output = [format_output_object(output_db) for output_db in output_dbs]
            output = ''.join(output)
            yield six.binary_type(output.encode('utf-8'))
예제 #12
0
    def test_purge_executions_with_timestamp(self):
        now = date_utils.get_datetime_utc_now()

        # Write one execution after cut-off threshold
        exec_model = copy.deepcopy(
            self.models['executions']['execution1.yaml'])
        exec_model['start_timestamp'] = now - timedelta(days=15)
        exec_model['end_timestamp'] = now - timedelta(days=14)
        exec_model['status'] = action_constants.LIVEACTION_STATUS_SUCCEEDED
        exec_model['id'] = bson.ObjectId()
        ActionExecution.add_or_update(exec_model)

        # Insert corresponding stdout and stderr db mock models
        self._insert_mock_stdout_and_stderr_objects_for_execution(
            exec_model['id'], count=3)

        # Write one execution before cut-off threshold
        exec_model = copy.deepcopy(
            self.models['executions']['execution1.yaml'])
        exec_model['start_timestamp'] = now - timedelta(days=22)
        exec_model['end_timestamp'] = now - timedelta(days=21)
        exec_model['status'] = action_constants.LIVEACTION_STATUS_SUCCEEDED
        exec_model['id'] = bson.ObjectId()
        ActionExecution.add_or_update(exec_model)

        # Insert corresponding stdout and stderr db mock models
        self._insert_mock_stdout_and_stderr_objects_for_execution(
            exec_model['id'], count=3)

        execs = ActionExecution.get_all()
        self.assertEqual(len(execs), 2)
        stdout_dbs = ActionExecutionOutput.query(output_type='stdout')
        self.assertEqual(len(stdout_dbs), 6)
        stderr_dbs = ActionExecutionOutput.query(output_type='stderr')
        self.assertEqual(len(stderr_dbs), 6)

        purge_executions(logger=LOG, timestamp=now - timedelta(days=20))
        execs = ActionExecution.get_all()
        self.assertEqual(len(execs), 1)
        stdout_dbs = ActionExecutionOutput.query(output_type='stdout')
        self.assertEqual(len(stdout_dbs), 3)
        stderr_dbs = ActionExecutionOutput.query(output_type='stderr')
        self.assertEqual(len(stderr_dbs), 3)
예제 #13
0
        def existing_output_iter():
            # Consume and return all of the existing lines
            output_dbs = ActionExecutionOutput.query(
                execution_id=execution_id, **query_filters
            )

            # Note: We return all at once instead of yield line by line to avoid multiple socket
            # writes and to achieve better performance
            output = [format_output_object(output_db) for output_db in output_dbs]
            output = "".join(output)
            yield six.binary_type(output.encode("utf-8"))
예제 #14
0
    def test_purge_executions_with_timestamp(self):
        now = date_utils.get_datetime_utc_now()

        # Write one execution after cut-off threshold
        exec_model = copy.deepcopy(self.models['executions']['execution1.yaml'])
        exec_model['start_timestamp'] = now - timedelta(days=15)
        exec_model['end_timestamp'] = now - timedelta(days=14)
        exec_model['status'] = action_constants.LIVEACTION_STATUS_SUCCEEDED
        exec_model['id'] = bson.ObjectId()
        ActionExecution.add_or_update(exec_model)

        # Insert corresponding stdout and stderr db mock models
        self._insert_mock_stdout_and_stderr_objects_for_execution(exec_model['id'], count=3)

        # Write one execution before cut-off threshold
        exec_model = copy.deepcopy(self.models['executions']['execution1.yaml'])
        exec_model['start_timestamp'] = now - timedelta(days=22)
        exec_model['end_timestamp'] = now - timedelta(days=21)
        exec_model['status'] = action_constants.LIVEACTION_STATUS_SUCCEEDED
        exec_model['id'] = bson.ObjectId()
        ActionExecution.add_or_update(exec_model)

        # Insert corresponding stdout and stderr db mock models
        self._insert_mock_stdout_and_stderr_objects_for_execution(exec_model['id'], count=3)

        execs = ActionExecution.get_all()
        self.assertEqual(len(execs), 2)
        stdout_dbs = ActionExecutionOutput.query(output_type='stdout')
        self.assertEqual(len(stdout_dbs), 6)
        stderr_dbs = ActionExecutionOutput.query(output_type='stderr')
        self.assertEqual(len(stderr_dbs), 6)

        purge_executions(logger=LOG, timestamp=now - timedelta(days=20))
        execs = ActionExecution.get_all()
        self.assertEqual(len(execs), 1)
        stdout_dbs = ActionExecutionOutput.query(output_type='stdout')
        self.assertEqual(len(stdout_dbs), 3)
        stderr_dbs = ActionExecutionOutput.query(output_type='stderr')
        self.assertEqual(len(stderr_dbs), 3)
예제 #15
0
    def test_purge_executions_with_action_ref(self):
        now = date_utils.get_datetime_utc_now()
        exec_model = copy.deepcopy(
            self.models['executions']['execution1.yaml'])
        exec_model['start_timestamp'] = now - timedelta(days=15)
        exec_model['end_timestamp'] = now - timedelta(days=14)
        exec_model['status'] = action_constants.LIVEACTION_STATUS_SUCCEEDED
        exec_model['id'] = bson.ObjectId()
        ActionExecution.add_or_update(exec_model)

        # Insert corresponding stdout and stderr db mock models
        self._insert_mock_stdout_and_stderr_objects_for_execution(
            exec_model['id'], count=3)

        execs = ActionExecution.get_all()
        self.assertEqual(len(execs), 1)
        stdout_dbs = ActionExecutionOutput.query(output_type='stdout')
        self.assertEqual(len(stdout_dbs), 3)
        stderr_dbs = ActionExecutionOutput.query(output_type='stderr')
        self.assertEqual(len(stderr_dbs), 3)

        # Invalid action reference, nothing should be deleted
        purge_executions(logger=LOG,
                         action_ref='core.localzzz',
                         timestamp=now - timedelta(days=10))

        execs = ActionExecution.get_all()
        self.assertEqual(len(execs), 1)
        stdout_dbs = ActionExecutionOutput.query(output_type='stdout')
        self.assertEqual(len(stdout_dbs), 3)
        stderr_dbs = ActionExecutionOutput.query(output_type='stderr')
        self.assertEqual(len(stderr_dbs), 3)

        purge_executions(logger=LOG,
                         action_ref='core.local',
                         timestamp=now - timedelta(days=10))

        execs = ActionExecution.get_all()
        self.assertEqual(len(execs), 0)
        stdout_dbs = ActionExecutionOutput.query(output_type='stdout')
        self.assertEqual(len(stdout_dbs), 0)
        stderr_dbs = ActionExecutionOutput.query(output_type='stderr')
        self.assertEqual(len(stderr_dbs), 0)
예제 #16
0
    def test_purge_executions_with_action_ref(self):
        now = date_utils.get_datetime_utc_now()
        exec_model = copy.deepcopy(self.models['executions']['execution1.yaml'])
        exec_model['start_timestamp'] = now - timedelta(days=15)
        exec_model['end_timestamp'] = now - timedelta(days=14)
        exec_model['status'] = action_constants.LIVEACTION_STATUS_SUCCEEDED
        exec_model['id'] = bson.ObjectId()
        ActionExecution.add_or_update(exec_model)

        # Insert corresponding stdout and stderr db mock models
        self._insert_mock_stdout_and_stderr_objects_for_execution(exec_model['id'], count=3)

        execs = ActionExecution.get_all()
        self.assertEqual(len(execs), 1)
        stdout_dbs = ActionExecutionOutput.query(output_type='stdout')
        self.assertEqual(len(stdout_dbs), 3)
        stderr_dbs = ActionExecutionOutput.query(output_type='stderr')
        self.assertEqual(len(stderr_dbs), 3)

        # Invalid action reference, nothing should be deleted
        purge_executions(logger=LOG, action_ref='core.localzzz', timestamp=now - timedelta(days=10))

        execs = ActionExecution.get_all()
        self.assertEqual(len(execs), 1)
        stdout_dbs = ActionExecutionOutput.query(output_type='stdout')
        self.assertEqual(len(stdout_dbs), 3)
        stderr_dbs = ActionExecutionOutput.query(output_type='stderr')
        self.assertEqual(len(stderr_dbs), 3)

        purge_executions(logger=LOG, action_ref='core.local', timestamp=now - timedelta(days=10))

        execs = ActionExecution.get_all()
        self.assertEqual(len(execs), 0)
        stdout_dbs = ActionExecutionOutput.query(output_type='stdout')
        self.assertEqual(len(stdout_dbs), 0)
        stderr_dbs = ActionExecutionOutput.query(output_type='stderr')
        self.assertEqual(len(stderr_dbs), 0)
    def test_action_stdout_and_stderr_is_stored_in_the_db(
            self, mock_spawn, mock_popen):
        # Feature is enabled
        cfg.CONF.set_override(name='stream_output',
                              group='actionrunner',
                              override=True)

        # Note: We need to mock spawn function so we can test everything in single event loop
        # iteration
        mock_spawn.side_effect = blocking_eventlet_spawn

        # No output to stdout and no result (implicit None)
        mock_stdout = [
            'stdout line 1\n', 'stdout line 2\n', 'stdout line 3\n',
            'stdout line 4\n'
        ]
        mock_stderr = ['stderr line 1\n', 'stderr line 2\n', 'stderr line 3\n']

        mock_process = mock.Mock()
        mock_process.returncode = 0
        mock_popen.return_value = mock_process
        mock_process.stdout.closed = False
        mock_process.stderr.closed = False
        mock_process.stdout.readline = make_mock_stream_readline(
            mock_process.stdout, mock_stdout, stop_counter=4)
        mock_process.stderr.readline = make_mock_stream_readline(
            mock_process.stderr, mock_stderr, stop_counter=3)

        models = self.fixtures_loader.load_models(
            fixtures_pack='generic',
            fixtures_dict={'actions': ['local_script_with_params.yaml']})
        action_db = models['actions']['local_script_with_params.yaml']
        entry_point = os.path.join(
            get_fixtures_base_path(),
            'generic/actions/local_script_with_params.sh')

        action_parameters = {
            'param_string': 'test string',
            'param_integer': 1,
            'param_float': 2.55,
            'param_boolean': True,
            'param_list': ['a', 'b', 'c'],
            'param_object': {
                'foo': 'bar'
            }
        }

        runner = self._get_runner(action_db=action_db, entry_point=entry_point)
        runner.pre_run()
        status, result, _ = runner.run(action_parameters=action_parameters)
        runner.post_run(status, result)

        self.assertEqual(
            result['stdout'],
            'stdout line 1\nstdout line 2\nstdout line 3\nstdout line 4')
        self.assertEqual(result['stderr'],
                         'stderr line 1\nstderr line 2\nstderr line 3')
        self.assertEqual(result['return_code'], 0)

        # Verify stdout and stderr lines have been correctly stored in the db
        output_dbs = ActionExecutionOutput.query(output_type='stdout')
        self.assertEqual(len(output_dbs), 4)
        self.assertEqual(output_dbs[0].data, mock_stdout[0])
        self.assertEqual(output_dbs[1].data, mock_stdout[1])
        self.assertEqual(output_dbs[2].data, mock_stdout[2])
        self.assertEqual(output_dbs[3].data, mock_stdout[3])

        output_dbs = ActionExecutionOutput.query(output_type='stderr')
        self.assertEqual(len(output_dbs), 3)
        self.assertEqual(output_dbs[0].data, mock_stderr[0])
        self.assertEqual(output_dbs[1].data, mock_stderr[1])
        self.assertEqual(output_dbs[2].data, mock_stderr[2])
    def test_script_with_paramters_parameter_serialization(self):
        models = self.fixtures_loader.load_models(
            fixtures_pack='generic',
            fixtures_dict={'actions': ['local_script_with_params.yaml']})
        action_db = models['actions']['local_script_with_params.yaml']
        entry_point = os.path.join(
            get_fixtures_base_path(),
            'generic/actions/local_script_with_params.sh')

        action_parameters = {
            'param_string': 'test string',
            'param_integer': 1,
            'param_float': 2.55,
            'param_boolean': True,
            'param_list': ['a', 'b', 'c'],
            'param_object': {
                'foo': 'bar'
            }
        }

        runner = self._get_runner(action_db=action_db, entry_point=entry_point)
        runner.pre_run()
        status, result, _ = runner.run(action_parameters=action_parameters)
        runner.post_run(status, result)

        self.assertEqual(status, action_constants.LIVEACTION_STATUS_SUCCEEDED)
        self.assertTrue('PARAM_STRING=test string' in result['stdout'])
        self.assertTrue('PARAM_INTEGER=1' in result['stdout'])
        self.assertTrue('PARAM_FLOAT=2.55' in result['stdout'])
        self.assertTrue('PARAM_BOOLEAN=1' in result['stdout'])
        self.assertTrue('PARAM_LIST=a,b,c' in result['stdout'])
        self.assertTrue('PARAM_OBJECT={"foo": "bar"}' in result['stdout'])

        action_parameters = {
            'param_string': 'test string',
            'param_integer': 1,
            'param_float': 2.55,
            'param_boolean': False,
            'param_list': ['a', 'b', 'c'],
            'param_object': {
                'foo': 'bar'
            }
        }

        runner = self._get_runner(action_db=action_db, entry_point=entry_point)
        runner.pre_run()
        status, result, _ = runner.run(action_parameters=action_parameters)
        runner.post_run(status, result)

        self.assertEqual(status, action_constants.LIVEACTION_STATUS_SUCCEEDED)
        self.assertTrue('PARAM_BOOLEAN=0' in result['stdout'])

        action_parameters = {
            'param_string': '',
            'param_integer': None,
            'param_float': None,
        }

        runner = self._get_runner(action_db=action_db, entry_point=entry_point)
        runner.pre_run()
        status, result, _ = runner.run(action_parameters=action_parameters)
        runner.post_run(status, result)

        self.assertEqual(status, action_constants.LIVEACTION_STATUS_SUCCEEDED)
        self.assertTrue('PARAM_STRING=\n' in result['stdout'])
        self.assertTrue('PARAM_INTEGER=\n' in result['stdout'])
        self.assertTrue('PARAM_FLOAT=\n' in result['stdout'])

        # End result should be the same when streaming is enabled
        cfg.CONF.set_override(name='stream_output',
                              group='actionrunner',
                              override=True)

        # Verify initial state
        output_dbs = ActionExecutionOutput.get_all()
        self.assertEqual(len(output_dbs), 0)

        action_parameters = {
            'param_string': 'test string',
            'param_integer': 1,
            'param_float': 2.55,
            'param_boolean': True,
            'param_list': ['a', 'b', 'c'],
            'param_object': {
                'foo': 'bar'
            }
        }

        runner = self._get_runner(action_db=action_db, entry_point=entry_point)
        runner.pre_run()
        status, result, _ = runner.run(action_parameters=action_parameters)
        runner.post_run(status, result)

        self.assertEqual(status, action_constants.LIVEACTION_STATUS_SUCCEEDED)
        self.assertTrue('PARAM_STRING=test string' in result['stdout'])
        self.assertTrue('PARAM_INTEGER=1' in result['stdout'])
        self.assertTrue('PARAM_FLOAT=2.55' in result['stdout'])
        self.assertTrue('PARAM_BOOLEAN=1' in result['stdout'])
        self.assertTrue('PARAM_LIST=a,b,c' in result['stdout'])
        self.assertTrue('PARAM_OBJECT={"foo": "bar"}' in result['stdout'])

        output_dbs = ActionExecutionOutput.query(output_type='stdout')
        self.assertEqual(len(output_dbs), 6)
        self.assertEqual(output_dbs[0].data, 'PARAM_STRING=test string\n')
        self.assertEqual(output_dbs[5].data, 'PARAM_OBJECT={"foo": "bar"}\n')

        output_dbs = ActionExecutionOutput.query(output_type='stderr')
        self.assertEqual(len(output_dbs), 0)
    def test_action_stdout_and_stderr_is_stored_in_the_db_short_running_action(
            self, mock_spawn, mock_popen):
        # Verify that we correctly retrieve all the output and wait for stdout and stderr reading
        # threads for short running actions.
        models = self.fixtures_loader.load_models(
            fixtures_pack='generic', fixtures_dict={'actions': ['local.yaml']})
        action_db = models['actions']['local.yaml']

        # Feature is enabled
        cfg.CONF.set_override(name='stream_output',
                              group='actionrunner',
                              override=True)

        # Note: We need to mock spawn function so we can test everything in single event loop
        # iteration
        mock_spawn.side_effect = blocking_eventlet_spawn

        # No output to stdout and no result (implicit None)
        mock_stdout = ['stdout line 1\n', 'stdout line 2\n']
        mock_stderr = ['stderr line 1\n', 'stderr line 2\n']

        # We add a sleep to simulate action process exiting before we finish reading data from
        mock_process = mock.Mock()
        mock_process.returncode = 0
        mock_popen.return_value = mock_process
        mock_process.stdout.closed = False
        mock_process.stderr.closed = False
        mock_process.stdout.readline = make_mock_stream_readline(
            mock_process.stdout, mock_stdout, stop_counter=2, sleep_delay=1)
        mock_process.stderr.readline = make_mock_stream_readline(
            mock_process.stderr, mock_stderr, stop_counter=2)

        for index in range(1, 4):
            mock_process.stdout.closed = False
            mock_process.stderr.closed = False

            mock_process.stdout.counter = 0
            mock_process.stderr.counter = 0

            runner = self._get_runner(action_db, cmd='echo "foobar"')
            runner.pre_run()
            status, result, _ = runner.run({})

            self.assertEquals(status,
                              action_constants.LIVEACTION_STATUS_SUCCEEDED)

            self.assertEqual(result['stdout'], 'stdout line 1\nstdout line 2')
            self.assertEqual(result['stderr'], 'stderr line 1\nstderr line 2')
            self.assertEqual(result['return_code'], 0)

            # Verify stdout and stderr lines have been correctly stored in the db
            output_dbs = ActionExecutionOutput.query(output_type='stdout')

            if index == 1:
                db_index_1 = 0
                db_index_2 = 1
            elif index == 2:
                db_index_1 = 2
                db_index_2 = 3
            elif index == 3:
                db_index_1 = 4
                db_index_2 = 5
            elif index == 4:
                db_index_1 = 6
                db_index_2 = 7

            self.assertEqual(len(output_dbs), (index * 2))
            self.assertEqual(output_dbs[db_index_1].data, mock_stdout[0])
            self.assertEqual(output_dbs[db_index_2].data, mock_stdout[1])

            output_dbs = ActionExecutionOutput.query(output_type='stderr')
            self.assertEqual(len(output_dbs), (index * 2))
            self.assertEqual(output_dbs[db_index_1].data, mock_stderr[0])
            self.assertEqual(output_dbs[db_index_2].data, mock_stderr[1])
예제 #20
0
    def test_action_stdout_and_stderr_is_stored_in_the_db_short_running_action(self, mock_spawn,
                                                                               mock_popen):
        # Verify that we correctly retrieve all the output and wait for stdout and stderr reading
        # threads for short running actions.
        models = self.fixtures_loader.load_models(
            fixtures_pack='generic', fixtures_dict={'actions': ['local.yaml']})
        action_db = models['actions']['local.yaml']

        # Feature is enabled
        cfg.CONF.set_override(name='stream_output', group='actionrunner', override=True)

        # Note: We need to mock spawn function so we can test everything in single event loop
        # iteration
        mock_spawn.side_effect = blocking_eventlet_spawn

        # No output to stdout and no result (implicit None)
        mock_stdout = [
            'stdout line 1\n',
            'stdout line 2\n'
        ]
        mock_stderr = [
            'stderr line 1\n',
            'stderr line 2\n'
        ]

        # We add a sleep to simulate action process exiting before we finish reading data from
        mock_process = mock.Mock()
        mock_process.returncode = 0
        mock_popen.return_value = mock_process
        mock_process.stdout.closed = False
        mock_process.stderr.closed = False
        mock_process.stdout.readline = make_mock_stream_readline(mock_process.stdout, mock_stdout,
                                                                 stop_counter=2,
                                                                 sleep_delay=1)
        mock_process.stderr.readline = make_mock_stream_readline(mock_process.stderr, mock_stderr,
                                                                 stop_counter=2)

        for index in range(1, 4):
            mock_process.stdout.closed = False
            mock_process.stderr.closed = False

            mock_process.stdout.counter = 0
            mock_process.stderr.counter = 0

            runner = self._get_runner(action_db, cmd='echo "foobar"')
            runner.pre_run()
            status, result, _ = runner.run({})

            self.assertEquals(status, action_constants.LIVEACTION_STATUS_SUCCEEDED)

            self.assertEqual(result['stdout'], 'stdout line 1\nstdout line 2')
            self.assertEqual(result['stderr'], 'stderr line 1\nstderr line 2')
            self.assertEqual(result['return_code'], 0)

            # Verify stdout and stderr lines have been correctly stored in the db
            output_dbs = ActionExecutionOutput.query(output_type='stdout')

            if index == 1:
                db_index_1 = 0
                db_index_2 = 1
            elif index == 2:
                db_index_1 = 2
                db_index_2 = 3
            elif index == 3:
                db_index_1 = 4
                db_index_2 = 5
            elif index == 4:
                db_index_1 = 6
                db_index_2 = 7

            self.assertEqual(len(output_dbs), (index * 2))
            self.assertEqual(output_dbs[db_index_1].data, mock_stdout[0])
            self.assertEqual(output_dbs[db_index_2].data, mock_stdout[1])

            output_dbs = ActionExecutionOutput.query(output_type='stderr')
            self.assertEqual(len(output_dbs), (index * 2))
            self.assertEqual(output_dbs[db_index_1].data, mock_stderr[0])
            self.assertEqual(output_dbs[db_index_2].data, mock_stderr[1])
예제 #21
0
    def test_script_with_parameters_parameter_serialization(self):
        models = self.fixtures_loader.load_models(
            fixtures_pack='generic', fixtures_dict={'actions': ['local_script_with_params.yaml']})
        action_db = models['actions']['local_script_with_params.yaml']
        entry_point = os.path.join(get_fixtures_base_path(),
                                   'generic/actions/local_script_with_params.sh')

        action_parameters = {
            'param_string': 'test string',
            'param_integer': 1,
            'param_float': 2.55,
            'param_boolean': True,
            'param_list': ['a', 'b', 'c'],
            'param_object': {'foo': 'bar'}
        }

        runner = self._get_runner(action_db=action_db, entry_point=entry_point)
        runner.pre_run()
        status, result, _ = runner.run(action_parameters=action_parameters)
        runner.post_run(status, result)
        self.assertEqual(status, action_constants.LIVEACTION_STATUS_SUCCEEDED)
        self.assertTrue('PARAM_STRING=test string' in result['stdout'])
        self.assertTrue('PARAM_INTEGER=1' in result['stdout'])
        self.assertTrue('PARAM_FLOAT=2.55' in result['stdout'])
        self.assertTrue('PARAM_BOOLEAN=1' in result['stdout'])
        self.assertTrue('PARAM_LIST=a,b,c' in result['stdout'])
        self.assertTrue('PARAM_OBJECT={"foo": "bar"}' in result['stdout'])

        action_parameters = {
            'param_string': 'test string',
            'param_integer': 1,
            'param_float': 2.55,
            'param_boolean': False,
            'param_list': ['a', 'b', 'c'],
            'param_object': {'foo': 'bar'}
        }

        runner = self._get_runner(action_db=action_db, entry_point=entry_point)
        runner.pre_run()
        status, result, _ = runner.run(action_parameters=action_parameters)
        runner.post_run(status, result)

        self.assertEqual(status, action_constants.LIVEACTION_STATUS_SUCCEEDED)
        self.assertTrue('PARAM_BOOLEAN=0' in result['stdout'])

        action_parameters = {
            'param_string': '',
            'param_integer': None,
            'param_float': None,
        }

        runner = self._get_runner(action_db=action_db, entry_point=entry_point)
        runner.pre_run()
        status, result, _ = runner.run(action_parameters=action_parameters)
        runner.post_run(status, result)

        self.assertEqual(status, action_constants.LIVEACTION_STATUS_SUCCEEDED)
        self.assertTrue('PARAM_STRING=\n' in result['stdout'])
        self.assertTrue('PARAM_INTEGER=\n' in result['stdout'])
        self.assertTrue('PARAM_FLOAT=\n' in result['stdout'])

        # End result should be the same when streaming is enabled
        cfg.CONF.set_override(name='stream_output', group='actionrunner', override=True)

        # Verify initial state
        output_dbs = ActionExecutionOutput.get_all()
        self.assertEqual(len(output_dbs), 0)

        action_parameters = {
            'param_string': 'test string',
            'param_integer': 1,
            'param_float': 2.55,
            'param_boolean': True,
            'param_list': ['a', 'b', 'c'],
            'param_object': {'foo': 'bar'}
        }

        runner = self._get_runner(action_db=action_db, entry_point=entry_point)
        runner.pre_run()
        status, result, _ = runner.run(action_parameters=action_parameters)
        runner.post_run(status, result)

        self.assertEqual(status, action_constants.LIVEACTION_STATUS_SUCCEEDED)
        self.assertTrue('PARAM_STRING=test string' in result['stdout'])
        self.assertTrue('PARAM_INTEGER=1' in result['stdout'])
        self.assertTrue('PARAM_FLOAT=2.55' in result['stdout'])
        self.assertTrue('PARAM_BOOLEAN=1' in result['stdout'])
        self.assertTrue('PARAM_LIST=a,b,c' in result['stdout'])
        self.assertTrue('PARAM_OBJECT={"foo": "bar"}' in result['stdout'])

        output_dbs = ActionExecutionOutput.query(output_type='stdout')
        self.assertEqual(len(output_dbs), 6)
        self.assertEqual(output_dbs[0].data, 'PARAM_STRING=test string\n')
        self.assertEqual(output_dbs[5].data, 'PARAM_OBJECT={"foo": "bar"}\n')

        output_dbs = ActionExecutionOutput.query(output_type='stderr')
        self.assertEqual(len(output_dbs), 0)
예제 #22
0
    def test_action_stdout_and_stderr_is_stored_in_the_db(self, mock_spawn, mock_popen):
        # Feature is enabled
        cfg.CONF.set_override(name='stream_output', group='actionrunner', override=True)

        # Note: We need to mock spawn function so we can test everything in single event loop
        # iteration
        mock_spawn.side_effect = blocking_eventlet_spawn

        # No output to stdout and no result (implicit None)
        mock_stdout = [
            'stdout line 1\n',
            'stdout line 2\n',
            'stdout line 3\n',
            'stdout line 4\n'
        ]
        mock_stderr = [
            'stderr line 1\n',
            'stderr line 2\n',
            'stderr line 3\n'
        ]

        mock_process = mock.Mock()
        mock_process.returncode = 0
        mock_popen.return_value = mock_process
        mock_process.stdout.closed = False
        mock_process.stderr.closed = False
        mock_process.stdout.readline = make_mock_stream_readline(mock_process.stdout, mock_stdout,
                                                                 stop_counter=4)
        mock_process.stderr.readline = make_mock_stream_readline(mock_process.stderr, mock_stderr,
                                                                 stop_counter=3)

        models = self.fixtures_loader.load_models(
            fixtures_pack='generic', fixtures_dict={'actions': ['local_script_with_params.yaml']})
        action_db = models['actions']['local_script_with_params.yaml']
        entry_point = os.path.join(get_fixtures_base_path(),
                                   'generic/actions/local_script_with_params.sh')

        action_parameters = {
            'param_string': 'test string',
            'param_integer': 1,
            'param_float': 2.55,
            'param_boolean': True,
            'param_list': ['a', 'b', 'c'],
            'param_object': {'foo': 'bar'}
        }

        runner = self._get_runner(action_db=action_db, entry_point=entry_point)
        runner.pre_run()
        status, result, _ = runner.run(action_parameters=action_parameters)
        runner.post_run(status, result)

        self.assertEqual(result['stdout'],
                         'stdout line 1\nstdout line 2\nstdout line 3\nstdout line 4')
        self.assertEqual(result['stderr'], 'stderr line 1\nstderr line 2\nstderr line 3')
        self.assertEqual(result['return_code'], 0)

        # Verify stdout and stderr lines have been correctly stored in the db
        output_dbs = ActionExecutionOutput.query(output_type='stdout')
        self.assertEqual(len(output_dbs), 4)
        self.assertEqual(output_dbs[0].data, mock_stdout[0])
        self.assertEqual(output_dbs[1].data, mock_stdout[1])
        self.assertEqual(output_dbs[2].data, mock_stdout[2])
        self.assertEqual(output_dbs[3].data, mock_stdout[3])

        output_dbs = ActionExecutionOutput.query(output_type='stderr')
        self.assertEqual(len(output_dbs), 3)
        self.assertEqual(output_dbs[0].data, mock_stderr[0])
        self.assertEqual(output_dbs[1].data, mock_stderr[1])
        self.assertEqual(output_dbs[2].data, mock_stderr[2])
예제 #23
0
    def test_purge_incomplete(self):
        now = date_utils.get_datetime_utc_now()
        start_ts = now - timedelta(days=15)

        # Write executions before cut-off threshold
        exec_model = copy.deepcopy(
            self.models['executions']['execution1.yaml'])
        exec_model['start_timestamp'] = start_ts
        exec_model['status'] = action_constants.LIVEACTION_STATUS_SCHEDULED
        exec_model['id'] = bson.ObjectId()
        ActionExecution.add_or_update(exec_model)

        # Insert corresponding stdout and stderr db mock models
        self._insert_mock_stdout_and_stderr_objects_for_execution(
            exec_model['id'], count=1)

        exec_model = copy.deepcopy(
            self.models['executions']['execution1.yaml'])
        exec_model['start_timestamp'] = start_ts
        exec_model['status'] = action_constants.LIVEACTION_STATUS_RUNNING
        exec_model['id'] = bson.ObjectId()
        ActionExecution.add_or_update(exec_model)

        # Insert corresponding stdout and stderr db mock models
        self._insert_mock_stdout_and_stderr_objects_for_execution(
            exec_model['id'], count=1)

        exec_model = copy.deepcopy(
            self.models['executions']['execution1.yaml'])
        exec_model['start_timestamp'] = start_ts
        exec_model['status'] = action_constants.LIVEACTION_STATUS_DELAYED
        exec_model['id'] = bson.ObjectId()
        ActionExecution.add_or_update(exec_model)

        # Insert corresponding stdout and stderr db mock models
        self._insert_mock_stdout_and_stderr_objects_for_execution(
            exec_model['id'], count=1)

        exec_model = copy.deepcopy(
            self.models['executions']['execution1.yaml'])
        exec_model['start_timestamp'] = start_ts
        exec_model['status'] = action_constants.LIVEACTION_STATUS_CANCELING
        exec_model['id'] = bson.ObjectId()
        ActionExecution.add_or_update(exec_model)

        # Insert corresponding stdout and stderr db mock models
        self._insert_mock_stdout_and_stderr_objects_for_execution(
            exec_model['id'], count=1)

        exec_model = copy.deepcopy(
            self.models['executions']['execution1.yaml'])
        exec_model['start_timestamp'] = start_ts
        exec_model['status'] = action_constants.LIVEACTION_STATUS_REQUESTED
        exec_model['id'] = bson.ObjectId()
        ActionExecution.add_or_update(exec_model)

        # Insert corresponding stdout and stderr db mock models
        self._insert_mock_stdout_and_stderr_objects_for_execution(
            exec_model['id'], count=1)

        self.assertEqual(len(ActionExecution.get_all()), 5)
        stdout_dbs = ActionExecutionOutput.query(output_type='stdout')
        self.assertEqual(len(stdout_dbs), 5)
        stderr_dbs = ActionExecutionOutput.query(output_type='stderr')
        self.assertEqual(len(stderr_dbs), 5)

        # Incompleted executions shouldnt be purged
        purge_executions(logger=LOG,
                         timestamp=now - timedelta(days=10),
                         purge_incomplete=False)
        self.assertEqual(len(ActionExecution.get_all()), 5)
        stdout_dbs = ActionExecutionOutput.query(output_type='stdout')
        self.assertEqual(len(stdout_dbs), 5)
        stderr_dbs = ActionExecutionOutput.query(output_type='stderr')
        self.assertEqual(len(stderr_dbs), 5)

        purge_executions(logger=LOG,
                         timestamp=now - timedelta(days=10),
                         purge_incomplete=True)
        self.assertEqual(len(ActionExecution.get_all()), 0)
        stdout_dbs = ActionExecutionOutput.query(output_type='stdout')
        self.assertEqual(len(stdout_dbs), 0)
        stderr_dbs = ActionExecutionOutput.query(output_type='stderr')
        self.assertEqual(len(stderr_dbs), 0)
예제 #24
0
    def test_script_with_parameters_parameter_serialization(self):
        models = self.fixtures_loader.load_models(
            fixtures_pack="generic",
            fixtures_dict={"actions": ["local_script_with_params.yaml"]},
        )
        action_db = models["actions"]["local_script_with_params.yaml"]
        entry_point = os.path.join(
            get_fixtures_base_path(),
            "generic/actions/local_script_with_params.sh")

        action_parameters = {
            "param_string": "test string",
            "param_integer": 1,
            "param_float": 2.55,
            "param_boolean": True,
            "param_list": ["a", "b", "c"],
            "param_object": {
                "foo": "bar"
            },
        }

        runner = self._get_runner(action_db=action_db, entry_point=entry_point)
        runner.pre_run()
        status, result, _ = runner.run(action_parameters=action_parameters)
        runner.post_run(status, result)
        self.assertEqual(status, action_constants.LIVEACTION_STATUS_SUCCEEDED)
        self.assertIn("PARAM_STRING=test string", result["stdout"])
        self.assertIn("PARAM_INTEGER=1", result["stdout"])
        self.assertIn("PARAM_FLOAT=2.55", result["stdout"])
        self.assertIn("PARAM_BOOLEAN=1", result["stdout"])
        self.assertIn("PARAM_LIST=a,b,c", result["stdout"])
        self.assertIn('PARAM_OBJECT={"foo":"bar"}', result["stdout"])

        action_parameters = {
            "param_string": "test string",
            "param_integer": 1,
            "param_float": 2.55,
            "param_boolean": False,
            "param_list": ["a", "b", "c"],
            "param_object": {
                "foo": "bar"
            },
        }

        runner = self._get_runner(action_db=action_db, entry_point=entry_point)
        runner.pre_run()
        status, result, _ = runner.run(action_parameters=action_parameters)
        runner.post_run(status, result)

        self.assertEqual(status, action_constants.LIVEACTION_STATUS_SUCCEEDED)
        self.assertIn("PARAM_BOOLEAN=0", result["stdout"])

        action_parameters = {
            "param_string": "",
            "param_integer": None,
            "param_float": None,
        }

        runner = self._get_runner(action_db=action_db, entry_point=entry_point)
        runner.pre_run()
        status, result, _ = runner.run(action_parameters=action_parameters)
        runner.post_run(status, result)

        self.assertEqual(status, action_constants.LIVEACTION_STATUS_SUCCEEDED)
        self.assertIn("PARAM_STRING=\n", result["stdout"])
        self.assertIn("PARAM_INTEGER=\n", result["stdout"])
        self.assertIn("PARAM_FLOAT=\n", result["stdout"])

        # End result should be the same when streaming is enabled
        cfg.CONF.set_override(name="stream_output",
                              group="actionrunner",
                              override=True)

        # Verify initial state
        output_dbs = ActionExecutionOutput.get_all()
        self.assertEqual(len(output_dbs), 0)

        action_parameters = {
            "param_string": "test string",
            "param_integer": 1,
            "param_float": 2.55,
            "param_boolean": True,
            "param_list": ["a", "b", "c"],
            "param_object": {
                "foo": "bar"
            },
        }

        runner = self._get_runner(action_db=action_db, entry_point=entry_point)
        runner.pre_run()
        status, result, _ = runner.run(action_parameters=action_parameters)
        runner.post_run(status, result)

        self.assertEqual(status, action_constants.LIVEACTION_STATUS_SUCCEEDED)
        self.assertIn("PARAM_STRING=test string", result["stdout"])
        self.assertIn("PARAM_INTEGER=1", result["stdout"])
        self.assertIn("PARAM_FLOAT=2.55", result["stdout"])
        self.assertIn("PARAM_BOOLEAN=1", result["stdout"])
        self.assertIn("PARAM_LIST=a,b,c", result["stdout"])
        self.assertIn('PARAM_OBJECT={"foo":"bar"}', result["stdout"])

        output_dbs = ActionExecutionOutput.query(output_type="stdout")
        self.assertEqual(len(output_dbs), 6)
        self.assertEqual(output_dbs[0].data, "PARAM_STRING=test string\n")
        self.assertEqual(output_dbs[5].data, 'PARAM_OBJECT={"foo":"bar"}\n')

        output_dbs = ActionExecutionOutput.query(output_type="stderr")
        self.assertEqual(len(output_dbs), 0)
예제 #25
0
    def test_garbage_collection(self):
        now = date_utils.get_datetime_utc_now()
        status = action_constants.LIVEACTION_STATUS_SUCCEEDED

        # Insert come mock ActionExecutionDB objects with start_timestamp < TTL defined in the
        # config
        old_executions_count = 15
        ttl_days = 30  # > 20
        timestamp = (now - datetime.timedelta(days=ttl_days))
        for index in range(0, old_executions_count):
            action_execution_db = ActionExecutionDB(
                start_timestamp=timestamp,
                end_timestamp=timestamp,
                status=status,
                action={'ref': 'core.local'},
                runner={'name': 'local-shell-cmd'},
                liveaction={'ref': 'foo'})
            ActionExecution.add_or_update(action_execution_db)

            stdout_db = ActionExecutionOutputDB(execution_id=str(
                action_execution_db.id),
                                                action_ref='core.local',
                                                runner_ref='dummy',
                                                timestamp=timestamp,
                                                output_type='stdout',
                                                data='stdout')
            ActionExecutionOutput.add_or_update(stdout_db)

            stderr_db = ActionExecutionOutputDB(execution_id=str(
                action_execution_db.id),
                                                action_ref='core.local',
                                                runner_ref='dummy',
                                                timestamp=timestamp,
                                                output_type='stderr',
                                                data='stderr')
            ActionExecutionOutput.add_or_update(stderr_db)

        # Insert come mock ActionExecutionDB objects with start_timestamp > TTL defined in the
        # config
        new_executions_count = 5
        ttl_days = 2  # < 20
        timestamp = (now - datetime.timedelta(days=ttl_days))
        for index in range(0, new_executions_count):
            action_execution_db = ActionExecutionDB(
                start_timestamp=timestamp,
                end_timestamp=timestamp,
                status=status,
                action={'ref': 'core.local'},
                runner={'name': 'local-shell-cmd'},
                liveaction={'ref': 'foo'})
            ActionExecution.add_or_update(action_execution_db)

            stdout_db = ActionExecutionOutputDB(execution_id=str(
                action_execution_db.id),
                                                action_ref='core.local',
                                                runner_ref='dummy',
                                                timestamp=timestamp,
                                                output_type='stdout',
                                                data='stdout')
            ActionExecutionOutput.add_or_update(stdout_db)

            stderr_db = ActionExecutionOutputDB(execution_id=str(
                action_execution_db.id),
                                                action_ref='core.local',
                                                runner_ref='dummy',
                                                timestamp=timestamp,
                                                output_type='stderr',
                                                data='stderr')
            ActionExecutionOutput.add_or_update(stderr_db)

        # Insert some mock output objects where start_timestamp > action_executions_output_ttl
        new_output_count = 5
        ttl_days = 15  # > 10 and < 20
        timestamp = (now - datetime.timedelta(days=ttl_days))
        for index in range(0, new_output_count):
            action_execution_db = ActionExecutionDB(
                start_timestamp=timestamp,
                end_timestamp=timestamp,
                status=status,
                action={'ref': 'core.local'},
                runner={'name': 'local-shell-cmd'},
                liveaction={'ref': 'foo'})
            ActionExecution.add_or_update(action_execution_db)

            stdout_db = ActionExecutionOutputDB(execution_id=str(
                action_execution_db.id),
                                                action_ref='core.local',
                                                runner_ref='dummy',
                                                timestamp=timestamp,
                                                output_type='stdout',
                                                data='stdout')
            ActionExecutionOutput.add_or_update(stdout_db)

            stderr_db = ActionExecutionOutputDB(execution_id=str(
                action_execution_db.id),
                                                action_ref='core.local',
                                                runner_ref='dummy',
                                                timestamp=timestamp,
                                                output_type='stderr',
                                                data='stderr')
            ActionExecutionOutput.add_or_update(stderr_db)

        execs = ActionExecution.get_all()
        self.assertEqual(
            len(execs),
            (old_executions_count + new_executions_count + new_output_count))

        stdout_dbs = ActionExecutionOutput.query(output_type='stdout')
        self.assertEqual(
            len(stdout_dbs),
            (old_executions_count + new_executions_count + new_output_count))

        stderr_dbs = ActionExecutionOutput.query(output_type='stderr')
        self.assertEqual(
            len(stderr_dbs),
            (old_executions_count + new_executions_count + new_output_count))

        # Start garbage collector
        process = self._start_garbage_collector()

        # Give it some time to perform garbage collection and kill it
        eventlet.sleep(15)
        process.send_signal(signal.SIGKILL)
        self.remove_process(process=process)

        # Old executions and corresponding objects should have been garbage collected
        execs = ActionExecution.get_all()
        self.assertEqual(len(execs), (new_executions_count + new_output_count))

        # Collection for output objects older than 10 days is also enabled, so those objects
        # should be deleted as well
        stdout_dbs = ActionExecutionOutput.query(output_type='stdout')
        self.assertEqual(len(stdout_dbs), (new_executions_count))

        stderr_dbs = ActionExecutionOutput.query(output_type='stderr')
        self.assertEqual(len(stderr_dbs), (new_executions_count))
예제 #26
0
    def test_action_stdout_and_stderr_is_stored_in_the_db(
            self, mock_spawn, mock_popen):
        # Feature is enabled
        cfg.CONF.set_override(name="stream_output",
                              group="actionrunner",
                              override=True)

        # Note: We need to mock spawn function so we can test everything in single event loop
        # iteration
        mock_spawn.side_effect = blocking_eventlet_spawn

        # No output to stdout and no result (implicit None)
        mock_stdout = [
            "stdout line 1\n",
            "stdout line 2\n",
            "stdout line 3\n",
            "stdout line 4\n",
        ]
        mock_stderr = ["stderr line 1\n", "stderr line 2\n", "stderr line 3\n"]

        mock_process = mock.Mock()
        mock_process.returncode = 0
        mock_popen.return_value = mock_process
        mock_process.stdout.closed = False
        mock_process.stderr.closed = False
        mock_process.stdout.readline = make_mock_stream_readline(
            mock_process.stdout, mock_stdout, stop_counter=4)
        mock_process.stderr.readline = make_mock_stream_readline(
            mock_process.stderr, mock_stderr, stop_counter=3)

        models = self.fixtures_loader.load_models(
            fixtures_pack="generic",
            fixtures_dict={"actions": ["local_script_with_params.yaml"]},
        )
        action_db = models["actions"]["local_script_with_params.yaml"]
        entry_point = os.path.join(
            get_fixtures_base_path(),
            "generic/actions/local_script_with_params.sh")

        action_parameters = {
            "param_string": "test string",
            "param_integer": 1,
            "param_float": 2.55,
            "param_boolean": True,
            "param_list": ["a", "b", "c"],
            "param_object": {
                "foo": "bar"
            },
        }

        runner = self._get_runner(action_db=action_db, entry_point=entry_point)
        runner.pre_run()
        status, result, _ = runner.run(action_parameters=action_parameters)
        runner.post_run(status, result)

        self.assertEqual(
            result["stdout"],
            "stdout line 1\nstdout line 2\nstdout line 3\nstdout line 4",
        )
        self.assertEqual(result["stderr"],
                         "stderr line 1\nstderr line 2\nstderr line 3")
        self.assertEqual(result["return_code"], 0)

        # Verify stdout and stderr lines have been correctly stored in the db
        output_dbs = ActionExecutionOutput.query(output_type="stdout")
        self.assertEqual(len(output_dbs), 4)
        self.assertEqual(output_dbs[0].data, mock_stdout[0])
        self.assertEqual(output_dbs[1].data, mock_stdout[1])
        self.assertEqual(output_dbs[2].data, mock_stdout[2])
        self.assertEqual(output_dbs[3].data, mock_stdout[3])

        output_dbs = ActionExecutionOutput.query(output_type="stderr")
        self.assertEqual(len(output_dbs), 3)
        self.assertEqual(output_dbs[0].data, mock_stderr[0])
        self.assertEqual(output_dbs[1].data, mock_stderr[1])
        self.assertEqual(output_dbs[2].data, mock_stderr[2])
예제 #27
0
    def test_purge_incomplete(self):
        now = date_utils.get_datetime_utc_now()
        start_ts = now - timedelta(days=15)

        # Write executions before cut-off threshold
        exec_model = copy.deepcopy(self.models['executions']['execution1.yaml'])
        exec_model['start_timestamp'] = start_ts
        exec_model['status'] = action_constants.LIVEACTION_STATUS_SCHEDULED
        exec_model['id'] = bson.ObjectId()
        ActionExecution.add_or_update(exec_model)

        # Insert corresponding stdout and stderr db mock models
        self._insert_mock_stdout_and_stderr_objects_for_execution(exec_model['id'], count=1)

        exec_model = copy.deepcopy(self.models['executions']['execution1.yaml'])
        exec_model['start_timestamp'] = start_ts
        exec_model['status'] = action_constants.LIVEACTION_STATUS_RUNNING
        exec_model['id'] = bson.ObjectId()
        ActionExecution.add_or_update(exec_model)

        # Insert corresponding stdout and stderr db mock models
        self._insert_mock_stdout_and_stderr_objects_for_execution(exec_model['id'], count=1)

        exec_model = copy.deepcopy(self.models['executions']['execution1.yaml'])
        exec_model['start_timestamp'] = start_ts
        exec_model['status'] = action_constants.LIVEACTION_STATUS_DELAYED
        exec_model['id'] = bson.ObjectId()
        ActionExecution.add_or_update(exec_model)

        # Insert corresponding stdout and stderr db mock models
        self._insert_mock_stdout_and_stderr_objects_for_execution(exec_model['id'], count=1)

        exec_model = copy.deepcopy(self.models['executions']['execution1.yaml'])
        exec_model['start_timestamp'] = start_ts
        exec_model['status'] = action_constants.LIVEACTION_STATUS_CANCELING
        exec_model['id'] = bson.ObjectId()
        ActionExecution.add_or_update(exec_model)

        # Insert corresponding stdout and stderr db mock models
        self._insert_mock_stdout_and_stderr_objects_for_execution(exec_model['id'], count=1)

        exec_model = copy.deepcopy(self.models['executions']['execution1.yaml'])
        exec_model['start_timestamp'] = start_ts
        exec_model['status'] = action_constants.LIVEACTION_STATUS_REQUESTED
        exec_model['id'] = bson.ObjectId()
        ActionExecution.add_or_update(exec_model)

        # Insert corresponding stdout and stderr db mock models
        self._insert_mock_stdout_and_stderr_objects_for_execution(exec_model['id'], count=1)

        self.assertEqual(len(ActionExecution.get_all()), 5)
        stdout_dbs = ActionExecutionOutput.query(output_type='stdout')
        self.assertEqual(len(stdout_dbs), 5)
        stderr_dbs = ActionExecutionOutput.query(output_type='stderr')
        self.assertEqual(len(stderr_dbs), 5)

        # Incompleted executions shouldnt be purged
        purge_executions(logger=LOG, timestamp=now - timedelta(days=10), purge_incomplete=False)
        self.assertEqual(len(ActionExecution.get_all()), 5)
        stdout_dbs = ActionExecutionOutput.query(output_type='stdout')
        self.assertEqual(len(stdout_dbs), 5)
        stderr_dbs = ActionExecutionOutput.query(output_type='stderr')
        self.assertEqual(len(stderr_dbs), 5)

        purge_executions(logger=LOG, timestamp=now - timedelta(days=10), purge_incomplete=True)
        self.assertEqual(len(ActionExecution.get_all()), 0)
        stdout_dbs = ActionExecutionOutput.query(output_type='stdout')
        self.assertEqual(len(stdout_dbs), 0)
        stderr_dbs = ActionExecutionOutput.query(output_type='stderr')
        self.assertEqual(len(stderr_dbs), 0)
예제 #28
0
    def test_garbage_collection(self):
        now = date_utils.get_datetime_utc_now()
        status = action_constants.LIVEACTION_STATUS_SUCCEEDED

        # Insert come mock ActionExecutionDB objects with start_timestamp < TTL defined in the
        # config
        old_executions_count = 15
        ttl_days = 30  # > 20
        timestamp = (now - datetime.timedelta(days=ttl_days))
        for index in range(0, old_executions_count):
            action_execution_db = ActionExecutionDB(start_timestamp=timestamp,
                                                    end_timestamp=timestamp,
                                                    status=status,
                                                    action={'ref': 'core.local'},
                                                    runner={'name': 'local-shell-cmd'},
                                                    liveaction={'ref': 'foo'})
            ActionExecution.add_or_update(action_execution_db)

            stdout_db = ActionExecutionOutputDB(execution_id=str(action_execution_db.id),
                                                action_ref='core.local',
                                                runner_ref='dummy',
                                                timestamp=timestamp,
                                                output_type='stdout',
                                                data='stdout')
            ActionExecutionOutput.add_or_update(stdout_db)

            stderr_db = ActionExecutionOutputDB(execution_id=str(action_execution_db.id),
                                                action_ref='core.local',
                                                runner_ref='dummy',
                                                timestamp=timestamp,
                                                output_type='stderr',
                                                data='stderr')
            ActionExecutionOutput.add_or_update(stderr_db)

        # Insert come mock ActionExecutionDB objects with start_timestamp > TTL defined in the
        # config
        new_executions_count = 5
        ttl_days = 2  # < 20
        timestamp = (now - datetime.timedelta(days=ttl_days))
        for index in range(0, new_executions_count):
            action_execution_db = ActionExecutionDB(start_timestamp=timestamp,
                                                    end_timestamp=timestamp,
                                                    status=status,
                                                    action={'ref': 'core.local'},
                                                    runner={'name': 'local-shell-cmd'},
                                                    liveaction={'ref': 'foo'})
            ActionExecution.add_or_update(action_execution_db)

            stdout_db = ActionExecutionOutputDB(execution_id=str(action_execution_db.id),
                                                action_ref='core.local',
                                                runner_ref='dummy',
                                                timestamp=timestamp,
                                                output_type='stdout',
                                                data='stdout')
            ActionExecutionOutput.add_or_update(stdout_db)

            stderr_db = ActionExecutionOutputDB(execution_id=str(action_execution_db.id),
                                                action_ref='core.local',
                                                runner_ref='dummy',
                                                timestamp=timestamp,
                                                output_type='stderr',
                                                data='stderr')
            ActionExecutionOutput.add_or_update(stderr_db)

        # Insert some mock output objects where start_timestamp > action_executions_output_ttl
        new_output_count = 5
        ttl_days = 15  # > 10 and < 20
        timestamp = (now - datetime.timedelta(days=ttl_days))
        for index in range(0, new_output_count):
            action_execution_db = ActionExecutionDB(start_timestamp=timestamp,
                                                    end_timestamp=timestamp,
                                                    status=status,
                                                    action={'ref': 'core.local'},
                                                    runner={'name': 'local-shell-cmd'},
                                                    liveaction={'ref': 'foo'})
            ActionExecution.add_or_update(action_execution_db)

            stdout_db = ActionExecutionOutputDB(execution_id=str(action_execution_db.id),
                                                action_ref='core.local',
                                                runner_ref='dummy',
                                                timestamp=timestamp,
                                                output_type='stdout',
                                                data='stdout')
            ActionExecutionOutput.add_or_update(stdout_db)

            stderr_db = ActionExecutionOutputDB(execution_id=str(action_execution_db.id),
                                                action_ref='core.local',
                                                runner_ref='dummy',
                                                timestamp=timestamp,
                                                output_type='stderr',
                                                data='stderr')
            ActionExecutionOutput.add_or_update(stderr_db)

        execs = ActionExecution.get_all()
        self.assertEqual(len(execs),
                         (old_executions_count + new_executions_count + new_output_count))

        stdout_dbs = ActionExecutionOutput.query(output_type='stdout')
        self.assertEqual(len(stdout_dbs),
                         (old_executions_count + new_executions_count + new_output_count))

        stderr_dbs = ActionExecutionOutput.query(output_type='stderr')
        self.assertEqual(len(stderr_dbs),
                         (old_executions_count + new_executions_count + new_output_count))

        # Start garbage collector
        process = self._start_garbage_collector()

        # Give it some time to perform garbage collection and kill it
        eventlet.sleep(15)
        process.send_signal(signal.SIGKILL)
        self.remove_process(process=process)

        # Old executions and corresponding objects should have been garbage collected
        execs = ActionExecution.get_all()
        self.assertEqual(len(execs), (new_executions_count + new_output_count))

        # Collection for output objects older than 10 days is also enabled, so those objects
        # should be deleted as well
        stdout_dbs = ActionExecutionOutput.query(output_type='stdout')
        self.assertEqual(len(stdout_dbs), (new_executions_count))

        stderr_dbs = ActionExecutionOutput.query(output_type='stderr')
        self.assertEqual(len(stderr_dbs), (new_executions_count))