summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2016-10-05 00:34:23 +0000
committerGerrit Code Review <review@openstack.org>2016-10-05 00:34:23 +0000
commitfd45db19b6faf11443b893f941f936bd4652e76b (patch)
tree300469f2990385b1c8334f5c3229b80bc71f2b90
parent5bdee97f4843de36669e25aa27874c93451fe05a (diff)
parent70c35e6e3d2aed9f37d5101dafd22c5905ec8583 (diff)
downloadpython-novaclient-stable/mitaka.tar.gz
Merge "Handle error response for webob>=1.6.0" into stable/mitakamitaka-eol3.3.3stable/mitaka
-rw-r--r--novaclient/exceptions.py18
-rw-r--r--novaclient/tests/unit/test_exceptions.py48
2 files changed, 63 insertions, 3 deletions
diff --git a/novaclient/exceptions.py b/novaclient/exceptions.py
index c502e964..31dd4871 100644
--- a/novaclient/exceptions.py
+++ b/novaclient/exceptions.py
@@ -294,9 +294,21 @@ def from_response(response, body, url, method=None):
details = "n/a"
if hasattr(body, 'keys'):
- error = body[list(body)[0]]
- message = error.get('message')
- details = error.get('details')
+ # NOTE(mriedem): WebOb<1.6.0 will return a nested dict structure
+ # where the error keys to the message/details/code. WebOb>=1.6.0
+ # returns just a response body as a single dict, not nested,
+ # so we have to handle both cases (since we can't trust what we're
+ # given with content_type: application/json either way.
+ if 'message' in body:
+ # WebOb 1.6.0 case
+ message = body.get('message')
+ details = body.get('details')
+ else:
+ # WebOb<1.6.0 where we assume there is a single error message
+ # key to the body that has the message and details.
+ error = body[list(body)[0]]
+ message = error.get('message')
+ details = error.get('details')
kwargs['message'] = message
kwargs['details'] = details
diff --git a/novaclient/tests/unit/test_exceptions.py b/novaclient/tests/unit/test_exceptions.py
new file mode 100644
index 00000000..34ce11d1
--- /dev/null
+++ b/novaclient/tests/unit/test_exceptions.py
@@ -0,0 +1,48 @@
+# Copyright 2016 IBM Corp.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from novaclient import exceptions
+from novaclient.tests.unit import utils as test_utils
+
+
+class ExceptionsTestCase(test_utils.TestCase):
+
+ def _test_from_response(self, body, expected_message):
+ data = {
+ 'status_code': 404,
+ 'headers': {
+ 'content-type': 'application/json',
+ 'x-openstack-request-id': (
+ 'req-d9df03b0-4150-4b53-8157-7560ccf39f75'),
+ }
+ }
+ response = test_utils.TestResponse(data)
+ fake_url = 'http://localhost:8774/v2.1/fake/flavors/test'
+ error = exceptions.from_response(response, body, fake_url, 'GET')
+ self.assertIsInstance(error, exceptions.NotFound)
+ self.assertEqual(expected_message, error.message)
+
+ def test_from_response_webob_pre_1_6_0(self):
+ # Tests error responses before webob 1.6.0 where the error details
+ # are nested in the response body.
+ message = "Flavor test could not be found."
+ self._test_from_response(
+ {"itemNotFound": {"message": message, "code": 404}},
+ message)
+
+ def test_from_response_webob_post_1_6_0(self):
+ # Tests error responses from webob 1.6.0 where the error details
+ # are in the response body.
+ message = "Flavor test could not be found."
+ self._test_from_response({"message": message, "code": 404}, message)