more robust insights error handling

This commit is contained in:
Chris Meyers
2017-05-22 17:32:17 -04:00
parent 3793f1ec09
commit 4461c8fe91
2 changed files with 53 additions and 3 deletions

View File

@@ -14,6 +14,7 @@ import subprocess
import sys import sys
import logging import logging
import requests import requests
import urlparse
from base64 import b64encode from base64 import b64encode
from collections import OrderedDict from collections import OrderedDict
@@ -2087,9 +2088,11 @@ class HostInsights(GenericAPIView):
try: try:
res = self._get_insights(url, username, password) res = self._get_insights(url, username, password)
except requests.exceptions.SSLError: except requests.exceptions.SSLError:
return (dict(error='SSLError while trying to connect to https://access.redhat.com/'), status.HTTP_500_INTERNAL_SERVER_ERROR) return (dict(error='SSLError while trying to connect to {}'.format(url)), status.HTTP_500_INTERNAL_SERVER_ERROR)
except requests.exceptions.Timeout: except requests.exceptions.Timeout:
return (dict(error='Request to {} timed out'.format(url)), status.HTTP_504_GATEWAY_TIMEOUT) return (dict(error='Request to {} timed out.'.format(url)), status.HTTP_504_GATEWAY_TIMEOUT)
except requests.exceptions.RequestException as e:
return (dict(error='Unkown exception {} while trying to GET {}'.format(e, url)), status.HTTP_500_INTERNAL_SERVER_ERROR)
if res.status_code != 200: if res.status_code != 200:
return (dict(error='Failed to gather reports and maintenance plans from Insights API. Server responded with {} status code and message {}'.format(res.status_code, res.content)), status.HTTP_500_INTERNAL_SERVER_ERROR) return (dict(error='Failed to gather reports and maintenance plans from Insights API. Server responded with {} status code and message {}'.format(res.status_code, res.content)), status.HTTP_500_INTERNAL_SERVER_ERROR)
@@ -2097,7 +2100,7 @@ class HostInsights(GenericAPIView):
try: try:
return (dict(insights_content=res.json()), status.HTTP_200_OK) return (dict(insights_content=res.json()), status.HTTP_200_OK)
except ValueError: except ValueError:
return (None, status.HTTP_204_NO_CONTENT) return (dict(error='Expected JSON response from Insights but instead got {}'.format(res.content)), status.HTTP_500_INTERNAL_SERVER_ERROR)
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
host = self.get_object() host = self.get_object()

View File

@@ -1,5 +1,6 @@
import mock import mock
import pytest import pytest
import requests
from collections import namedtuple from collections import namedtuple
@@ -8,6 +9,7 @@ from awx.api.views import (
JobTemplateLabelList, JobTemplateLabelList,
JobTemplateSurveySpec, JobTemplateSurveySpec,
InventoryInventorySourcesUpdate, InventoryInventorySourcesUpdate,
HostInsights,
) )
@@ -117,3 +119,48 @@ class TestInventoryInventorySourcesUpdate:
view = InventoryInventorySourcesUpdate() view = InventoryInventorySourcesUpdate()
response = view.post(mock_request) response = view.post(mock_request)
assert response.data == expected assert response.data == expected
class TestHostInsights():
@pytest.fixture
def patch_parent(self, mocker):
mocker.patch('awx.api.generics.GenericAPIView')
@pytest.mark.parametrize("status_code, exception, error, message", [
(500, requests.exceptions.SSLError, 'SSLError while trying to connect to https://myexample.com/whocares/me/', None,),
(504, requests.exceptions.Timeout, 'Request to https://myexample.com/whocares/me/ timed out.', None,),
(500, requests.exceptions.RequestException, 'booo!', 'Unkown exception booo! while trying to GET https://myexample.com/whocares/me/'),
])
def test_get_insights_request_exception(self, patch_parent, mocker, status_code, exception, error, message):
view = HostInsights()
mocker.patch.object(view, '_get_insights', side_effect=exception(error))
(msg, code) = view.get_insights('https://myexample.com/whocares/me/', 'ignore', 'ignore')
assert code == status_code
assert msg['error'] == message or error
def test_get_insights_non_200(self, patch_parent, mocker):
view = HostInsights()
Response = namedtuple('Response', 'status_code content')
mocker.patch.object(view, '_get_insights', return_value=Response(500, 'hello world!'))
(msg, code) = view.get_insights('https://myexample.com/whocares/me/', 'ignore', 'ignore')
assert msg['error'] == 'Failed to gather reports and maintenance plans from Insights API. Server responded with 500 status code and message hello world!'
def test_get_insights_malformed_json_content(self, patch_parent, mocker):
view = HostInsights()
class Response():
status_code = 200
content = 'booo!'
def json(self):
raise ValueError('we do not care what this is')
mocker.patch.object(view, '_get_insights', return_value=Response())
(msg, code) = view.get_insights('https://myexample.com/whocares/me/', 'ignore', 'ignore')
assert msg['error'] == 'Expected JSON response from Insights but instead got booo!'
assert code == 500