HTTP errors have full error message
If HTTP error contains error message in json response, it is appended to an exception raised. exceptions_decorator is not used in fuel2, cliff has it's own error handling Change-Id: I8582e67e2061f5c941a22d32b0f4339f30142be2 Closes-bug: 1514906
This commit is contained in:
@@ -14,16 +14,18 @@
|
||||
|
||||
from functools import wraps
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
from keystoneclient.exceptions import Unauthorized
|
||||
import requests
|
||||
import sys
|
||||
import textwrap
|
||||
|
||||
|
||||
def exit_with_error(message):
|
||||
"""exit_with_error - writes message to stderr and exits with exit code 1.
|
||||
"""
|
||||
sys.stderr.write(message + "\n")
|
||||
sys.stderr.write("{}{}".format(message, os.linesep))
|
||||
exit(1)
|
||||
|
||||
|
||||
@@ -101,6 +103,10 @@ class InvalidFileException(FuelClientException):
|
||||
pass
|
||||
|
||||
|
||||
class HTTPError(FuelClientException):
|
||||
pass
|
||||
|
||||
|
||||
class EnvironmentException(Exception):
|
||||
pass
|
||||
|
||||
@@ -116,8 +122,8 @@ def exceptions_decorator(func):
|
||||
|
||||
# when server returns to us bad request check that
|
||||
# and print meaningful reason
|
||||
except requests.HTTPError as exc:
|
||||
exit_with_error("{0} ({1})".format(exc, get_error_body(exc)))
|
||||
except HTTPError as exc:
|
||||
exit_with_error(exc)
|
||||
except requests.ConnectionError:
|
||||
message = """
|
||||
Can't connect to Nailgun server!
|
||||
@@ -143,3 +149,7 @@ def get_error_body(error):
|
||||
error_body = error.response.text
|
||||
|
||||
return error_body
|
||||
|
||||
|
||||
def get_full_error_message(error):
|
||||
return "{} ({})".format(error, get_error_body(error))
|
||||
|
||||
@@ -19,6 +19,7 @@ import requests
|
||||
from keystoneclient.v2_0 import client as auth_client
|
||||
from six.moves.urllib import parse as urlparse
|
||||
|
||||
from fuelclient.cli import error
|
||||
from fuelclient import fuelclient_settings
|
||||
from fuelclient.logs import NullHandler
|
||||
|
||||
@@ -109,7 +110,7 @@ class Client(object):
|
||||
if self._auth_required is None:
|
||||
url = self.api_root + 'version'
|
||||
resp = requests.get(url)
|
||||
resp.raise_for_status()
|
||||
self._raise_for_status_with_info(resp)
|
||||
|
||||
self._auth_required = resp.json().get('auth_required', False)
|
||||
return self._auth_required
|
||||
@@ -150,7 +151,7 @@ class Client(object):
|
||||
self.print_debug('DELETE {0}'.format(url))
|
||||
|
||||
resp = self.session.delete(url)
|
||||
resp.raise_for_status()
|
||||
self._raise_for_status_with_info(resp)
|
||||
|
||||
if resp.status_code == 204:
|
||||
return {}
|
||||
@@ -166,7 +167,7 @@ class Client(object):
|
||||
self.print_debug('PUT {0} data={1}'.format(url, data_json))
|
||||
|
||||
resp = self.session.put(url, data=data_json)
|
||||
resp.raise_for_status()
|
||||
self._raise_for_status_with_info(resp)
|
||||
|
||||
return resp.json()
|
||||
|
||||
@@ -189,7 +190,7 @@ class Client(object):
|
||||
params = params or {}
|
||||
|
||||
resp = self.get_request_raw(api, ostf, params)
|
||||
resp.raise_for_status()
|
||||
self._raise_for_status_with_info(resp)
|
||||
|
||||
return resp.json()
|
||||
|
||||
@@ -212,13 +213,19 @@ class Client(object):
|
||||
"""Make POST request to specific API with some data
|
||||
"""
|
||||
resp = self.post_request_raw(api, data, ostf=ostf)
|
||||
resp.raise_for_status()
|
||||
self._raise_for_status_with_info(resp)
|
||||
|
||||
return resp.json()
|
||||
|
||||
def get_fuel_version(self):
|
||||
return self.get_request("version")
|
||||
|
||||
def _raise_for_status_with_info(self, response):
|
||||
try:
|
||||
response.raise_for_status()
|
||||
except requests.exceptions.HTTPError as e:
|
||||
raise error.HTTPError(error.get_full_error_message(e))
|
||||
|
||||
# This line is single point of instantiation for 'Client' class,
|
||||
# which intended to implement Singleton design pattern.
|
||||
APIClient = Client()
|
||||
|
||||
@@ -19,7 +19,6 @@ from cliff import app
|
||||
from cliff.commandmanager import CommandManager
|
||||
|
||||
from fuelclient.actions import fuel_version
|
||||
from fuelclient.cli.error import exceptions_decorator
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
@@ -67,7 +66,6 @@ class FuelClient(app.App):
|
||||
logging.getLogger(logger_name).setLevel(logging.WARNING)
|
||||
|
||||
|
||||
@exceptions_decorator
|
||||
def main(argv=sys.argv[1:]):
|
||||
fuelclient_app = FuelClient(
|
||||
description='Command line interface and Python API wrapper for Fuel.',
|
||||
|
||||
@@ -23,6 +23,7 @@ import mock
|
||||
import requests
|
||||
|
||||
from fuelclient.cli import error
|
||||
from fuelclient import client
|
||||
from fuelclient.common import data_utils
|
||||
from fuelclient.tests.unit.v1 import base
|
||||
from fuelclient import utils
|
||||
@@ -242,3 +243,14 @@ class TestUtils(base.UnitTestCase):
|
||||
result = utils.str_to_unicode(test_data)
|
||||
self.assertIsInstance(result, six.text_type)
|
||||
self.assertEqual(result, expected_data)
|
||||
|
||||
def test_HTTP_error_message(self):
|
||||
text = 'message text'
|
||||
|
||||
self.m_request.post('/api/v1/address',
|
||||
json={'message': text},
|
||||
status_code=403)
|
||||
|
||||
with self.assertRaisesRegexp(error.HTTPError,
|
||||
'403.*{}'.format(text)):
|
||||
client.Client().post_request('address')
|
||||
|
||||
@@ -21,7 +21,6 @@ import mock
|
||||
from oslotest import base as oslo_base
|
||||
|
||||
import fuelclient
|
||||
from fuelclient.cli import error
|
||||
from fuelclient.commands import environment as env
|
||||
from fuelclient import main as main_mod
|
||||
|
||||
@@ -72,19 +71,6 @@ class BaseCLITest(oslo_base.BaseTestCase):
|
||||
self.exec_command(*args)
|
||||
m_run_command.assert_called_once_with(args)
|
||||
|
||||
@mock.patch.object(sys, 'stderr')
|
||||
@mock.patch('cliff.app.App.run_subcommand')
|
||||
def test_exec_command_error_handle(self, m_run, m_stderr):
|
||||
error_msg = 'Test error'
|
||||
expected_output = error_msg + '\n'
|
||||
|
||||
m_run.side_effect = error.FuelClientException(error_msg)
|
||||
|
||||
self.assertRaises(SystemExit,
|
||||
self.exec_command,
|
||||
'some command --fail True')
|
||||
m_stderr.write.assert_called_once_with(expected_output)
|
||||
|
||||
@mock.patch('cliff.commandmanager.CommandManager.find_command')
|
||||
def test_command_interactive(self, m_find_command):
|
||||
commands = ['quit']
|
||||
|
||||
Reference in New Issue
Block a user