예제 #1
0
 def make_response():
     listener = get_listener(name='stream')
     app_iter = format(
         listener.generator(events=events,
                            action_refs=action_refs,
                            execution_ids=execution_ids))
     res = Response(content_type='text/event-stream', app_iter=app_iter)
     return res
예제 #2
0
 def make_response():
     listener = get_listener(name='stream')
     app_iter = format(listener.generator(events=events,
         action_refs=action_refs,
         end_event=end_event,
         end_statuses=action_constants.LIVEACTION_COMPLETED_STATES,
         end_execution_id=end_execution_id,
         execution_ids=execution_ids))
     res = Response(headerlist=[("X-Accel-Buffering", "no"),
         ('Cache-Control', 'no-cache'),
         ("Content-Type", "text/event-stream; charset=UTF-8")],
         app_iter=app_iter)
     return res
예제 #3
0
        def new_output_iter():
            def noop_gen():
                yield six.binary_type(NO_MORE_DATA_EVENT.encode("utf-8"))

            # Bail out if execution has already completed / been paused
            if execution_db.status in self.CLOSE_STREAM_LIVEACTION_STATES:
                return noop_gen()

            # Wait for and return any new line which may come in
            execution_ids = [execution_id]
            listener = get_listener(
                name="execution_output"
            )  # pylint: disable=no-member
            gen = listener.generator(execution_ids=execution_ids)

            def format(gen):
                for pack in gen:
                    if not pack:
                        continue
                    else:
                        (_, model_api) = pack

                        # Note: gunicorn wsgi handler expect bytes, not unicode
                        # pylint: disable=no-member
                        if isinstance(model_api, ActionExecutionOutputAPI):
                            if (
                                output_type
                                and output_type != "all"
                                and model_api.output_type != output_type
                            ):
                                continue

                            output = format_output_object(model_api).encode("utf-8")
                            yield six.binary_type(output)
                        elif isinstance(model_api, ActionExecutionAPI):
                            if model_api.status in self.CLOSE_STREAM_LIVEACTION_STATES:
                                yield six.binary_type(
                                    NO_MORE_DATA_EVENT.encode("utf-8")
                                )
                                break
                        else:
                            LOG.debug("Unrecognized message type: %s" % (model_api))

            gen = format(gen)
            return gen
예제 #4
0
파일: executions.py 프로젝트: nzlosh/st2
        def new_output_iter():
            def noop_gen():
                yield six.binary_type(NO_MORE_DATA_EVENT.encode('utf-8'))

            # Bail out if execution has already completed / been paused
            if execution_db.status in self.CLOSE_STREAM_LIVEACTION_STATES:
                return noop_gen()

            # Wait for and return any new line which may come in
            execution_ids = [execution_id]
            listener = get_listener(name='execution_output')  # pylint: disable=no-member
            gen = listener.generator(execution_ids=execution_ids)

            def format(gen):
                for pack in gen:
                    if not pack:
                        continue
                    else:
                        (_, model_api) = pack

                        # Note: gunicorn wsgi handler expect bytes, not unicode
                        # pylint: disable=no-member
                        if isinstance(model_api, ActionExecutionOutputAPI):
                            if output_type and output_type != 'all' and \
                               model_api.output_type != output_type:
                                continue

                            output = format_output_object(model_api).encode('utf-8')
                            yield six.binary_type(output)
                        elif isinstance(model_api, ActionExecutionAPI):
                            if model_api.status in self.CLOSE_STREAM_LIVEACTION_STATES:
                                yield six.binary_type(NO_MORE_DATA_EVENT.encode('utf-8'))
                                break
                        else:
                            LOG.debug('Unrecognized message type: %s' % (model_api))

            gen = format(gen)
            return gen
예제 #5
0
    def test_get_output_running_execution(self):
        # Retrieve lister instance to avoid race with listener connection not being established
        # early enough for tests to pass.
        # NOTE: This only affects tests where listeners are not pre-initialized.
        listener = get_listener(name='execution_output')
        eventlet.sleep(1.0)

        # Test the execution output API endpoint for execution which is running (blocking)
        status = action_constants.LIVEACTION_STATUS_RUNNING
        timestamp = date_utils.get_datetime_utc_now()
        action_execution_db = ActionExecutionDB(
            start_timestamp=timestamp,
            end_timestamp=timestamp,
            status=status,
            action={'ref': 'core.local'},
            runner={'name': 'local-shell-cmd'},
            liveaction={'ref': 'foo'})
        action_execution_db = ActionExecution.add_or_update(
            action_execution_db)

        output_params = dict(execution_id=str(action_execution_db.id),
                             action_ref='core.local',
                             runner_ref='dummy',
                             timestamp=timestamp,
                             output_type='stdout',
                             data='stdout before start\n')

        # Insert mock output object
        output_db = ActionExecutionOutputDB(**output_params)
        ActionExecutionOutput.add_or_update(output_db, publish=False)

        def insert_mock_data():
            output_params['data'] = 'stdout mid 1\n'
            output_db = ActionExecutionOutputDB(**output_params)
            ActionExecutionOutput.add_or_update(output_db)

        # Since the API endpoint is blocking (connection is kept open until action finishes), we
        # spawn an eventlet which eventually finishes the action.
        def publish_action_finished(action_execution_db):
            # Insert mock output object
            output_params['data'] = 'stdout pre finish 1\n'
            output_db = ActionExecutionOutputDB(**output_params)
            ActionExecutionOutput.add_or_update(output_db)

            eventlet.sleep(1.0)

            # Transition execution to completed state so the connection closes
            action_execution_db.status = action_constants.LIVEACTION_STATUS_SUCCEEDED
            action_execution_db = ActionExecution.add_or_update(
                action_execution_db)

        eventlet.spawn_after(0.2, insert_mock_data)
        eventlet.spawn_after(1.5, publish_action_finished, action_execution_db)

        # Retrieve data while execution is running - endpoint return new data once it's available
        # and block until the execution finishes
        resp = self.app.get('/v1/executions/%s/output' %
                            (str(action_execution_db.id)),
                            expect_errors=False)
        self.assertEqual(resp.status_int, 200)

        events = self._parse_response(resp.text)
        self.assertEqual(len(events), 4)
        self.assertEqual(events[0][1]['data'], 'stdout before start\n')
        self.assertEqual(events[1][1]['data'], 'stdout mid 1\n')
        self.assertEqual(events[2][1]['data'], 'stdout pre finish 1\n')
        self.assertEqual(events[3][0], 'EOF')

        # Once the execution is in completed state, existing output should be returned immediately
        resp = self.app.get('/v1/executions/%s/output' %
                            (str(action_execution_db.id)),
                            expect_errors=False)
        self.assertEqual(resp.status_int, 200)

        events = self._parse_response(resp.text)
        self.assertEqual(len(events), 4)
        self.assertEqual(events[0][1]['data'], 'stdout before start\n')
        self.assertEqual(events[1][1]['data'], 'stdout mid 1\n')
        self.assertEqual(events[2][1]['data'], 'stdout pre finish 1\n')
        self.assertEqual(events[3][0], 'EOF')

        listener.shutdown()
예제 #6
0
파일: stream.py 프로젝트: lyandut/st2
 def make_response():
     listener = get_listener(name='stream')
     app_iter = format(listener.generator(events=events, action_refs=action_refs,
                                          execution_ids=execution_ids))
     res = Response(content_type='text/event-stream', app_iter=app_iter)
     return res
예제 #7
0
    def test_get_output_running_execution(self):
        # Retrieve lister instance to avoid race with listener connection not being established
        # early enough for tests to pass.
        # NOTE: This only affects tests where listeners are not pre-initialized.
        listener = get_listener(name='execution_output')
        eventlet.sleep(1.0)

        # Test the execution output API endpoint for execution which is running (blocking)
        status = action_constants.LIVEACTION_STATUS_RUNNING
        timestamp = date_utils.get_datetime_utc_now()
        action_execution_db = ActionExecutionDB(start_timestamp=timestamp,
                                                end_timestamp=timestamp,
                                                status=status,
                                                action={'ref': 'core.local'},
                                                runner={'name': 'local-shell-cmd'},
                                                liveaction={'ref': 'foo'})
        action_execution_db = ActionExecution.add_or_update(action_execution_db)

        output_params = dict(execution_id=str(action_execution_db.id),
                             action_ref='core.local',
                             runner_ref='dummy',
                             timestamp=timestamp,
                             output_type='stdout',
                             data='stdout before start\n')

        # Insert mock output object
        output_db = ActionExecutionOutputDB(**output_params)
        ActionExecutionOutput.add_or_update(output_db, publish=False)

        def insert_mock_data():
            output_params['data'] = 'stdout mid 1\n'
            output_db = ActionExecutionOutputDB(**output_params)
            ActionExecutionOutput.add_or_update(output_db)

        # Since the API endpoint is blocking (connection is kept open until action finishes), we
        # spawn an eventlet which eventually finishes the action.
        def publish_action_finished(action_execution_db):
            # Insert mock output object
            output_params['data'] = 'stdout pre finish 1\n'
            output_db = ActionExecutionOutputDB(**output_params)
            ActionExecutionOutput.add_or_update(output_db)

            eventlet.sleep(1.0)

            # Transition execution to completed state so the connection closes
            action_execution_db.status = action_constants.LIVEACTION_STATUS_SUCCEEDED
            action_execution_db = ActionExecution.add_or_update(action_execution_db)

        eventlet.spawn_after(0.2, insert_mock_data)
        eventlet.spawn_after(1.5, publish_action_finished, action_execution_db)

        # Retrieve data while execution is running - endpoint return new data once it's available
        # and block until the execution finishes
        resp = self.app.get('/v1/executions/%s/output' % (str(action_execution_db.id)),
                            expect_errors=False)
        self.assertEqual(resp.status_int, 200)

        events = self._parse_response(resp.text)
        self.assertEqual(len(events), 4)
        self.assertEqual(events[0][1]['data'], 'stdout before start\n')
        self.assertEqual(events[1][1]['data'], 'stdout mid 1\n')
        self.assertEqual(events[2][1]['data'], 'stdout pre finish 1\n')
        self.assertEqual(events[3][0], 'EOF')

        # Once the execution is in completed state, existing output should be returned immediately
        resp = self.app.get('/v1/executions/%s/output' % (str(action_execution_db.id)),
                            expect_errors=False)
        self.assertEqual(resp.status_int, 200)

        events = self._parse_response(resp.text)
        self.assertEqual(len(events), 4)
        self.assertEqual(events[0][1]['data'], 'stdout before start\n')
        self.assertEqual(events[1][1]['data'], 'stdout mid 1\n')
        self.assertEqual(events[2][1]['data'], 'stdout pre finish 1\n')
        self.assertEqual(events[3][0], 'EOF')

        listener.shutdown()