def mock_status_instance_side_effect(service,
                                     instance):  # pragma: no cover (gevent)
    if instance in ['instance1', 'instance6', 'notaninstance', 'api_error']:
        # valid completed instance
        mock_mstatus = Mock(app_count=1,
                            deploy_status='Running',
                            expected_instance_count=2,
                            running_instance_count=2)
    if instance == 'instance2':
        # too many marathon apps
        mock_mstatus = Mock(app_count=2,
                            deploy_status='Running',
                            expected_instance_count=2,
                            running_instance_count=2)
    if instance == 'instance3':
        # too many running instances
        mock_mstatus = Mock(app_count=1,
                            deploy_status='Running',
                            expected_instance_count=2,
                            running_instance_count=4)
    if instance == 'instance4':
        # still Deploying
        mock_mstatus = Mock(app_count=1,
                            deploy_status='Deploying',
                            expected_instance_count=2,
                            running_instance_count=2)
    if instance == 'instance5':
        # not a marathon instance
        mock_mstatus = None
    if instance == 'instance7':
        # paasta stop'd
        mock_mstatus = Mock(app_count=1,
                            deploy_status='Stopped',
                            expected_instance_count=0,
                            running_instance_count=0,
                            desired_state='stop')
    if instance == 'instance8':
        # paasta has autoscaled to 0
        mock_mstatus = Mock(app_count=1,
                            deploy_status='Stopped',
                            expected_instance_count=0,
                            running_instance_count=0)
    mock_status = Mock()
    mock_status.git_sha = 'somesha'
    if instance == 'instance6':
        # running the wrong version
        mock_status.git_sha = 'anothersha'
    mock_status.marathon = mock_mstatus
    mock_result = mock_status
    mock_status_instance = Mock()
    mock_status_instance.result.return_value = mock_result
    if instance == 'notaninstance':
        # not an instance paasta can find
        mock_status_instance.result.side_effect = \
            HTTPError(response=Mock(status_code=404))
    if instance == 'api_error':
        # not an instance paasta can find
        mock_status_instance.result.side_effect = \
            HTTPError(response=Mock(status_code=500))
    return mock_status_instance
예제 #2
0
def test_scheduler_requeues_on_rwc_failure(in_memory_queue_connection,
                                           default_in_memory_producer,
                                           consume_queue):
    """Test scheduler requeues requests if RWC fails to start workflows."""
    scheduler = WorkflowExecutionScheduler(
        connection=in_memory_queue_connection)

    in_memory_wsp = WorkflowSubmissionPublisher(
        connection=in_memory_queue_connection)
    in_memory_wsp.publish_workflow_submission("1", "workflow.1", {})
    mock_rwc_api_client = Mock()
    mock_result_obj = Mock()
    mock_response = Mock()
    mock_response.status_code = 502
    mock_result_obj.result = Mock(side_effect=HTTPError(
        mock_response, message="DB connection timed out."))
    mock_rwc_api_client.api.set_workflow_status.return_value = mock_result_obj
    with patch.multiple(
            "reana_server.scheduler",
            reana_ready=Mock(return_value=True),
            current_rwc_api_client=mock_rwc_api_client,
            current_workflow_submission_publisher=in_memory_wsp,
    ):
        consume_queue(scheduler, limit=1)
        assert (not in_memory_queue_connection.channel().
                queues["workflow-submission"].empty())
예제 #3
0
def test_response_and_message_and_swagger_result(response_500):
    incoming_response = RequestsResponseAdapter(response_500)
    actual = str(
        HTTPError(incoming_response,
                  message="Holy moly!",
                  swagger_result={'msg': 'Kaboom'}))
    assert actual == "500 Server Error: Holy moly!: {'msg': 'Kaboom'}"
예제 #4
0
def response_callback(incoming_response, operation):
    """
    So the http_client is finished with its part of processing the response.
    This hands the response over to bravado_core for validation and
    unmarshalling.

    :type incoming_response: :class:`bravado_core.response.IncomingResponse`
    :type operation: :class:`bravado_core.operation.Operation`
    :return: Response spec's return value.
    :raises: HTTPError
        - On 5XX status code, the HTTPError has minimal information.
        - On non-2XX status code with no matching response, the HTTPError
            contains a detailed error message.
        - On non-2XX status code with a matching response, the HTTPError
            contains the return value.
    """
    raise_on_unexpected(incoming_response)

    try:
        swagger_return_value = unmarshal_response(incoming_response, operation)
    except MatchingResponseNotFound as e:
        six.reraise(HTTPError,
                    HTTPError(response=incoming_response, message=str(e)),
                    sys.exc_info()[2])

    raise_on_expected(incoming_response, swagger_return_value)
    return swagger_return_value
예제 #5
0
    def result(self, timeout=None):
        """Blocking call to wait for the HTTP response.

        :param timeout: Number of seconds to wait for a response. Defaults to
            None which means wait indefinitely.
        :type timeout: float
        :return: Depends on the value of also_return_response sent in
            to the constructor.
        """
        inner_response = self.future.result(timeout=timeout)
        incoming_response = self.response_adapter(inner_response)

        if self.operation is not None:
            unmarshal_response(incoming_response, self.operation,
                               self.response_callbacks)

            swagger_result = incoming_response.swagger_result
            if self.also_return_response:
                return swagger_result, incoming_response
            return swagger_result

        if 200 <= incoming_response.status_code < 300:
            return incoming_response

        raise HTTPError(response=incoming_response)
예제 #6
0
def test_secrets_add_already_exist():
    """Test adding secrets when they already exist."""
    status_code = 409
    reana_token = '000000'
    env = {'REANA_SERVER_URL': 'localhost'}
    message = 'One of the secrets already exists. No secrets were added.'
    mock_http_response = Mock(
        status_code=status_code,
        reason='Conflict',
        json=Mock(return_value={'message': 'Conflict'}))
    rs_api_client_mock = Mock()
    rs_api_client_mock.api.add_secrets = Mock(
        side_effect=HTTPError(mock_http_response))
    runner = CliRunner(env=env)
    with runner.isolation():
        with patch(
                "reana_client.api.client.current_rs_api_client",
                rs_api_client_mock):
                result = runner.invoke(
                    cli, ['secrets-add',
                          '-t', reana_token,
                          '--from-literal', 'USER=reanauser']
                )
                assert message in result.output
                assert result.exit_code == 1
예제 #7
0
def test_get_task_from_instance(mock_client):
    mock_client.get_paasta_api_client.return_value = None
    with raises(utils.PaastaTaskNotFound):
        utils.get_task_from_instance('cluster1', 'my-service', 'main')
    mock_client.get_paasta_api_client.assert_called_with(cluster='cluster1')
    mock_api = mock.Mock()
    mock_client.get_paasta_api_client.return_value = mock_api
    mock_task_1 = mock.Mock()
    mock_task_2 = mock.Mock()
    mock_tasks = [mock_task_1, mock_task_2]
    mock_result = mock.Mock(return_value=mock_tasks)
    mock_task_result = mock.Mock(return_value=mock_task_2)
    mock_api.service.tasks_instance.return_value = mock.Mock(result=mock_result)
    mock_api.service.task_instance.return_value = mock.Mock(result=mock_task_result)
    ret = utils.get_task_from_instance('cluster1', 'my-service', 'main', task_id='123')
    assert ret == mock_task_2
    mock_api.service.task_instance.assert_called_with(
        service='my-service',
        instance='main',
        verbose=True,
        task_id='123',
    )

    ret = utils.get_task_from_instance('cluster1', 'my-service', 'main')
    assert ret == mock_task_1
    mock_api.service.tasks_instance.assert_called_with(
        service='my-service',
        instance='main',
        verbose=True,
        slave_hostname=None,
    )

    mock_result = mock.Mock(return_value=[])
    mock_api.service.tasks_instance.return_value = mock.Mock(result=mock_result)
    with raises(utils.PaastaTaskNotFound):
        ret = utils.get_task_from_instance(
            'cluster1', 'my-service', 'main',
            slave_hostname='test',
        )

    mock_api.service.tasks_instance.side_effect = HTTPError(response=mock.Mock(status_code=500))
    with raises(utils.PaastaTaskNotFound):
        ret = utils.get_task_from_instance(
            'cluster1', 'my-service', 'main',
            slave_hostname='test',
        )
    mock_api.service.tasks_instance.assert_called_with(
        service='my-service',
        instance='main',
        verbose=True,
        slave_hostname='test',
    )

    mock_api.service.tasks_instance.side_effect = HTTPNotFound(response=mock.Mock(status_code=404))
    with raises(utils.PaastaTaskNotFound):
        ret = utils.get_task_from_instance(
            'cluster1', 'my-service', 'main',
            slave_hostname='test',
        )
예제 #8
0
def mock_http_err():
    return HTTPError(
        mock.MagicMock(
            spec=IncomingResponse,
            status_code='503',
            text='nothing',
        )
    )
예제 #9
0
def raise_on_unexpected(http_response):
    """Raise an HTTPError if the response is 5XX.

    :param http_response: :class:`bravado_core.response.IncomingResponse`
    :raises: HTTPError
    """
    if 500 <= http_response.status_code <= 599:
        raise HTTPError(response=http_response)
예제 #10
0
def raise_on_expected(http_response):
    """Raise an HTTPError if the response is non-2XX and matches a response
    in the swagger spec.

    :param http_response: :class:`bravado_core.response.IncomingResponse`
    :raises: HTTPError
    """
    if not 200 <= http_response.status_code < 300:
        raise HTTPError(response=http_response,
                        swagger_result=http_response.swagger_result)
예제 #11
0
def raise_on_expected(http_response, swagger_return_value):
    """
    Raise an HTTPError if the response is non-2XX and matches a response in the
    swagger spec.

    :param http_response: :class:`bravado_core.response.IncomingResponse`
    :param swagger_return_value: The return value of a swagger response if it
        has one, None otherwise.
    :raises: HTTPError
    """
    if not 200 <= http_response.status_code < 300:
        raise HTTPError(response=http_response,
                        swagger_result=swagger_return_value)
예제 #12
0
def test_http_error(mock_get_paasta_api_client):
    args = mock.Mock()
    args.cluster = "westeros-prod"

    mock_response = mock.Mock(status_code=500, text="Internal Server Error")
    response_adapter = RequestsResponseAdapter(mock_response)

    mock_api_client = mock_get_paasta_api_client.return_value
    mock_api_client.deploy_queue.deploy_queue.return_value.result.side_effect = HTTPError(
        response_adapter
    )

    assert list_deploy_queue(args) == 500
예제 #13
0
def test_400_service_call(mock_unmarshal_response):
    response_adapter_instance = Mock(spec=IncomingResponse,
                                     status_code=400,
                                     swagger_result={'error': 'Blah'})
    mock_unmarshal_response.side_effect = HTTPError(response_adapter_instance)
    response_adapter_type = Mock(return_value=response_adapter_instance)

    http_future = HttpFuture(future=Mock(spec=FutureAdapter),
                             response_adapter=response_adapter_type,
                             operation=Mock(spec=Operation))

    with pytest.raises(HTTPError) as excinfo:
        http_future.result()
    assert excinfo.value.response.status_code == 400
예제 #14
0
def test_paasta_status_exception(system_paasta_config):
    system_paasta_config = system_paasta_config

    with mock.patch('paasta_tools.cli.cmds.status.get_paasta_api_client',
                    autospec=True) as mock_get_paasta_api_client:
        requests_response = mock.Mock(status_code=500,
                                      reason='Internal Server Error')
        incoming_response = RequestsResponseAdapter(requests_response)

        mock_swagger_client = mock.Mock()
        mock_swagger_client.service.status_instance.side_effect = HTTPError(
            incoming_response)
        mock_get_paasta_api_client.return_value = mock_swagger_client
        paasta_status_on_api_endpoint(
            'fake_cluster',
            'fake_service',
            'fake_instance',
            system_paasta_config,
            verbose=False,
        )
예제 #15
0
    def result(self, timeout=None):
        """Blocking call to wait for API response

        :param timeout: Number of seconds to wait for a response. Defaults to
            None which means wait indefinitely.
        :type timeout: float
        :return: swagger response return value when given a callback or the
            http_response otherwise.
        """
        inner_response = self.future.result(timeout=timeout)
        incoming_response = self.response_adapter(inner_response)

        if self.response_callback:
            swagger_return_value = self.response_callback(incoming_response)
            return swagger_return_value

        if 200 <= incoming_response.status_code < 300:
            return incoming_response

        raise HTTPError(response=incoming_response)
예제 #16
0
def test_secrets_add_already_exist():
    """Test adding secrets when they already exist."""
    status_code = 409
    reana_token = "000000"
    env = {"REANA_SERVER_URL": "localhost"}
    message = "One of the secrets already exists. No secrets were added."
    mock_http_response = Mock(
        status_code=status_code,
        reason="Conflict",
        json=Mock(return_value={"message": "Conflict"}),
    )
    rs_api_client_mock = Mock()
    rs_api_client_mock.api.add_secrets = Mock(side_effect=HTTPError(mock_http_response))
    runner = CliRunner(env=env)
    with runner.isolation():
        with patch("reana_client.api.client.current_rs_api_client", rs_api_client_mock):
            result = runner.invoke(
                cli, ["secrets-add", "-t", reana_token, "--env", "USER=reanauser"]
            )
            assert message in result.output
            assert result.exit_code == 1
예제 #17
0
def unmarshal_response(incoming_response, operation, response_callbacks=None):
    """So the http_client is finished with its part of processing the response.
    This hands the response over to bravado_core for validation and
    unmarshalling and then runs any response callbacks. On success, the
    swagger_result is available as ``incoming_response.swagger_result``.

    :type incoming_response: :class:`bravado_core.response.IncomingResponse`
    :type operation: :class:`bravado_core.operation.Operation`
    :type response_callbacks: list of callable. See
        bravado_core.client.REQUEST_OPTIONS_DEFAULTS.

    :raises: HTTPError
        - On 5XX status code, the HTTPError has minimal information.
        - On non-2XX status code with no matching response, the HTTPError
            contains a detailed error message.
        - On non-2XX status code with a matching response, the HTTPError
            contains the return value.
    """
    response_callbacks = response_callbacks or []

    try:
        raise_on_unexpected(incoming_response)
        incoming_response.swagger_result = \
            bravado_core.response.unmarshal_response(
                incoming_response,
                operation)
    except MatchingResponseNotFound as e:
        six.reraise(
            HTTPError,
            HTTPError(response=incoming_response, message=str(e)),
            sys.exc_info()[2])
    finally:
        # Always run the callbacks regardless of success/failure
        for response_callback in response_callbacks:
            response_callback(incoming_response, operation)

    raise_on_expected(incoming_response)
예제 #18
0
def test_response_and_message(response_500):
    incoming_response = RequestsResponseAdapter(response_500)
    actual = str(HTTPError(incoming_response, message="Kaboom"))
    assert actual == '500 Server Error: Kaboom'
예제 #19
0
def test_response_only(response_500):
    incoming_response = RequestsResponseAdapter(response_500)
    assert str(HTTPError(incoming_response)) == '500 Server Error'
예제 #20
0
def mock_status_instance_side_effect(service, instance, omit_smartstack,
                                     omit_mesos):
    if instance in ["instance1", "instance6", "notaninstance", "api_error"]:
        # valid completed instance
        mock_mstatus = Mock(
            app_count=1,
            deploy_status="Running",
            expected_instance_count=2,
            running_instance_count=2,
        )
    if instance == "instance2":
        # too many marathon apps
        mock_mstatus = Mock(
            app_count=2,
            deploy_status="Running",
            expected_instance_count=2,
            running_instance_count=2,
        )
    if instance == "instance3":
        # too many running instances
        mock_mstatus = Mock(
            app_count=1,
            deploy_status="Running",
            expected_instance_count=2,
            running_instance_count=4,
        )
    if instance == "instance4":
        # still Deploying
        mock_mstatus = Mock(
            app_count=1,
            deploy_status="Deploying",
            expected_instance_count=2,
            running_instance_count=2,
        )
    if instance == "instance4.1":
        # still Deploying
        mock_mstatus = Mock(
            app_count=1,
            deploy_status="Waiting",
            expected_instance_count=2,
            running_instance_count=2,
        )
    if instance == "instance5":
        # not a marathon instance
        mock_mstatus = None
    if instance == "instance7":
        # paasta stop'd
        mock_mstatus = Mock(
            app_count=1,
            deploy_status="Stopped",
            expected_instance_count=0,
            running_instance_count=0,
            desired_state="stop",
        )
    if instance == "instance8":
        # paasta has autoscaled to 0
        mock_mstatus = Mock(
            app_count=1,
            deploy_status="Stopped",
            expected_instance_count=0,
            running_instance_count=0,
        )
    mock_status = Mock()
    mock_status.git_sha = "somesha"
    if instance == "instance6":
        # running the wrong version
        mock_status.git_sha = "anothersha"
    mock_status.marathon = mock_mstatus
    mock_status.kubernetes = None
    mock_result = mock_status
    mock_status_instance = Mock()
    mock_status_instance.result.return_value = mock_result
    if instance == "notaninstance":
        # not an instance paasta can find
        mock_status_instance.result.side_effect = HTTPError(response=Mock(
            status_code=404))
    if instance == "api_error":
        # not an instance paasta can find
        mock_status_instance.result.side_effect = HTTPError(response=Mock(
            status_code=500))
    return mock_status_instance