Example #1
0
    def test_get_events_incorrect_content_type(self):
        """
        When a request is made to Marathon's event stream, and the content-type
        header value returned is not "text/event-stream", an error should be
        raised.
        """
        data = []
        d = self.cleanup_d(self.client.get_events({'test': data.append}))

        request = yield self.requests.get()
        self.assertThat(request, HasRequestProperties(
            method='GET', url=self.uri('/v2/events')))
        self.assertThat(request.requestHeaders,
                        HasHeader('accept', ['text/event-stream']))

        request.setResponseCode(200)
        request.setHeader('Content-Type', 'application/json')

        json_data = {'hello': 'world'}
        request.write(b'event: test\n')
        request.write(b'data: %s\n' % (json.dumps(json_data).encode('utf-8'),))
        request.write(b'\n')

        yield wait0()
        self.assertThat(d, failed(WithErrorTypeAndMessage(
            HTTPError,
            'Expected header "Content-Type" to be "text/event-stream" but '
            'found "application/json" instead')))

        self.assertThat(data, Equals([]))

        request.finish()
        yield d
Example #2
0
    def test_json_content_missing_content_type(self):
        """
        When a request is made with the json_content callback and the
        content-type header is not set in the response headers then an error
        should be raised.
        """
        d = self.cleanup_d(self.client.request('GET', path='/hello'))
        d.addCallback(json_content)

        request = yield self.requests.get()
        self.assertThat(request, HasRequestProperties(
            method='GET', url=self.uri('/hello')))
        self.assertThat(request.requestHeaders,
                        HasHeader('accept', ['application/json']))

        request.setResponseCode(200)
        # Twisted will set the content type to "text/html" by default but this
        # can be disabled by setting the default content type to None:
        # https://twistedmatrix.com/documents/current/api/twisted.web.server.Request.html#defaultContentType
        request.defaultContentType = None
        request.write(json.dumps({}).encode('utf-8'))
        request.finish()

        yield wait0()
        self.assertThat(d, failed(WithErrorTypeAndMessage(
            HTTPError, 'Expected header "Content-Type" to be '
                       '"application/json" but header not found in response')))
Example #3
0
    def test_get_events_non_200(self):
        """
        When a request is made to Marathon's event stream, and a non-200
        response code is returned, an error should be raised.
        """
        data = []
        d = self.cleanup_d(self.client.get_events({'test': data.append}))

        request = yield self.requests.get()
        self.assertThat(request, HasRequestProperties(
            method='GET', url=self.uri('/v2/events')))
        self.assertThat(request.requestHeaders,
                        HasHeader('accept', ['text/event-stream']))

        request.setResponseCode(202)
        request.setHeader('Content-Type', 'text/event-stream')

        json_data = {'hello': 'world'}
        request.write(b'event: test\n')
        request.write(b'data: %s\n' % (json.dumps(json_data).encode('utf-8'),))
        request.write(b'\n')

        yield wait0()
        self.assertThat(d, failed(WithErrorTypeAndMessage(
            HTTPError, 'Non-200 response code (202) for url: '
                       'http://localhost:8080/v2/events')))

        self.assertThat(data, Equals([]))

        request.finish()
        yield d
Example #4
0
    def test_json_content_incorrect_content_type(self):
        """
        When a request is made with the json_content callback and the
        content-type header is set to a value other than 'application/json' in
        the response headers then an error should be raised.
        """
        d = self.cleanup_d(self.client.request('GET', path='/hello'))
        d.addCallback(json_content)

        request = yield self.requests.get()
        self.assertThat(request, HasRequestProperties(
            method='GET', url=self.uri('/hello')))
        self.assertThat(request.requestHeaders,
                        HasHeader('accept', ['application/json']))

        request.setResponseCode(200)
        request.setHeader('Content-Type', 'application/octet-stream')
        request.write(json.dumps({}).encode('utf-8'))
        request.finish()

        yield wait0()
        self.assertThat(d, failed(WithErrorTypeAndMessage(
            HTTPError,
            'Expected header "Content-Type" to be "application/json" but '
            'found "application/octet-stream" instead')))
Example #5
0
    def test_get_json_field_error(self):
        """
        When get_json_field is used to make a request but the response code
        indicates an error, an HTTPError should be raised.
        """
        d = self.cleanup_d(
            self.client.get_json_field('field-key', path='/my-path'))

        request = yield self.requests.get()
        self.assertThat(request, HasRequestProperties(
            method='GET', url=self.uri('/my-path')))

        request.setResponseCode(404)
        request.write(b'Not found\n')
        request.finish()

        yield wait0()
        self.assertThat(d, failed(WithErrorTypeAndMessage(
            HTTPError, '404 Client Error for url: %s' % self.uri('/my-path'))))
Example #6
0
    def test_request_fallback_all_failed(self):
        """
        When we make a request and there are multiple Marathon endpoints
        specified, and all the endpoints fail, the last failure should be
        returned.
        """
        agent = PerLocationAgent()
        agent.add_agent(b'localhost:8080', FailingAgent(RuntimeError('8080')))
        agent.add_agent(b'localhost:9090', FailingAgent(RuntimeError('9090')))
        client = MarathonClient(
            ['http://localhost:8080', 'http://localhost:9090'],
            client=treq_HTTPClient(agent))

        d = self.cleanup_d(client.request('GET', path='/my-path'))

        yield wait0()
        self.assertThat(d, failed(WithErrorTypeAndMessage(
            RuntimeError, '9090')))

        flush_logged_errors(RuntimeError)
Example #7
0
    def test_server_error_response(self):
        """
        When a request is made and the raise_for_status callback is added and a
        5xx response code is returned, a HTTPError should be raised to indicate
        a server error.
        """
        d = self.cleanup_d(self.client.request('GET', path='/hello'))
        d.addCallback(raise_for_status)

        request = yield self.requests.get()
        self.assertThat(request, HasRequestProperties(
            method='GET', url=self.uri('/hello')))

        request.setResponseCode(502)
        request.write(b'Bad gateway\n')
        request.finish()

        yield wait0()
        self.assertThat(d, failed(WithErrorTypeAndMessage(
            HTTPError, '502 Server Error for url: %s' % self.uri('/hello'))))
Example #8
0
    def test_get_json_field_missing(self):
        """
        When get_json_field is used to make a request, the response is
        deserialized from JSON and if the specified field is missing, an error
        is raised.
        """
        d = self.cleanup_d(
            self.client.get_json_field('field-key', path='/my-path'))

        request = yield self.requests.get()
        self.assertThat(request, HasRequestProperties(
            method='GET', url=self.uri('/my-path')))

        json_response(request, {'other-field-key': 'do-not-care'})

        yield wait0()
        self.assertThat(d, failed(WithErrorTypeAndMessage(
            KeyError,
            '\'Unable to get value for "field-key" from Marathon response: '
            '"{"other-field-key": "do-not-care"}"\''
        )))
Example #9
0
    def test_request_failure(self):
        """
        When the requests to all the marathon-lb instances have a bad status
        code then an error should be raised.
        """
        d = self.cleanup_d(self.client.request('GET', path='/my-path'))

        for lb in ['lb1', 'lb2']:
            request = yield self.requests.get()
            self.assertThat(request, HasRequestProperties(
                method='GET', url='http://%s:9090/my-path' % (lb,)))

            request.setResponseCode(500)
            request.setHeader('content-type', 'text/plain')
            request.write(b'Internal Server Error')
            request.finish()

        yield wait0()
        self.assertThat(d, failed(WithErrorTypeAndMessage(
            RuntimeError,
            'Failed to make a request to all marathon-lb instances'
        )))

        flush_logged_errors(HTTPError)