Skip to content

Commit fd45db1

Browse files
Jenkinsopenstack-gerrit
authored andcommitted
Merge "Handle error response for webob>=1.6.0" into stable/mitaka
2 parents 5bdee97 + 70c35e6 commit fd45db1

File tree

2 files changed

+63
-3
lines changed

2 files changed

+63
-3
lines changed

novaclient/exceptions.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -294,9 +294,21 @@ def from_response(response, body, url, method=None):
294294
details = "n/a"
295295

296296
if hasattr(body, 'keys'):
297-
error = body[list(body)[0]]
298-
message = error.get('message')
299-
details = error.get('details')
297+
# NOTE(mriedem): WebOb<1.6.0 will return a nested dict structure
298+
# where the error keys to the message/details/code. WebOb>=1.6.0
299+
# returns just a response body as a single dict, not nested,
300+
# so we have to handle both cases (since we can't trust what we're
301+
# given with content_type: application/json either way.
302+
if 'message' in body:
303+
# WebOb 1.6.0 case
304+
message = body.get('message')
305+
details = body.get('details')
306+
else:
307+
# WebOb<1.6.0 where we assume there is a single error message
308+
# key to the body that has the message and details.
309+
error = body[list(body)[0]]
310+
message = error.get('message')
311+
details = error.get('details')
300312

301313
kwargs['message'] = message
302314
kwargs['details'] = details
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Copyright 2016 IBM Corp.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
4+
# not use this file except in compliance with the License. You may obtain
5+
# a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12+
# License for the specific language governing permissions and limitations
13+
# under the License.
14+
15+
from novaclient import exceptions
16+
from novaclient.tests.unit import utils as test_utils
17+
18+
19+
class ExceptionsTestCase(test_utils.TestCase):
20+
21+
def _test_from_response(self, body, expected_message):
22+
data = {
23+
'status_code': 404,
24+
'headers': {
25+
'content-type': 'application/json',
26+
'x-openstack-request-id': (
27+
'req-d9df03b0-4150-4b53-8157-7560ccf39f75'),
28+
}
29+
}
30+
response = test_utils.TestResponse(data)
31+
fake_url = 'http://localhost:8774/v2.1/fake/flavors/test'
32+
error = exceptions.from_response(response, body, fake_url, 'GET')
33+
self.assertIsInstance(error, exceptions.NotFound)
34+
self.assertEqual(expected_message, error.message)
35+
36+
def test_from_response_webob_pre_1_6_0(self):
37+
# Tests error responses before webob 1.6.0 where the error details
38+
# are nested in the response body.
39+
message = "Flavor test could not be found."
40+
self._test_from_response(
41+
{"itemNotFound": {"message": message, "code": 404}},
42+
message)
43+
44+
def test_from_response_webob_post_1_6_0(self):
45+
# Tests error responses from webob 1.6.0 where the error details
46+
# are in the response body.
47+
message = "Flavor test could not be found."
48+
self._test_from_response({"message": message, "code": 404}, message)

0 commit comments

Comments
 (0)