From 479bbc2c206cecabd88f88c1ec16630feae4eb59 Mon Sep 17 00:00:00 2001 From: ZhiQiang Fan Date: Mon, 2 May 2016 22:41:18 +0800 Subject: [PATCH] fix KeyError when credential is invalid We assume the keystoneauth1.exceptions.HttpError.response has a field named `description`, however, it doesn't.[1] We should use `details` instead. [2] [1]. https://github.com/openstack/keystoneauth/blob/2.6.0/keystoneauth1/exceptions/http.py#L65-L85 [2]. https://github.com/openstack/keystoneauth/blob/2.6.0/keystoneauth1/exceptions/http.py#L391 Change-Id: I77846c6cafc0f73a1c6cf20a17fe44ba1284eef1 Closes-Bug: #1577290 --- aodhclient/shell.py | 11 +++----- aodhclient/tests/unit/test_shell.py | 39 +++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 aodhclient/tests/unit/test_shell.py diff --git a/aodhclient/shell.py b/aodhclient/shell.py index 8025f9e..261d97f 100644 --- a/aodhclient/shell.py +++ b/aodhclient/shell.py @@ -13,6 +13,8 @@ # License for the specific language governing permissions and limitations # under the License. +from __future__ import print_function + import logging import os import sys @@ -129,13 +131,8 @@ class AodhShell(app.App): return self._client def clean_up(self, cmd, result, err): - if err and isinstance(err, exceptions.HttpError): - try: - error = err.response.json() - except Exception: - pass - else: - print(error['description']) + if isinstance(err, exceptions.HttpError) and err.details: + print(err.details, file=sys.stderr) def configure_logging(self): if self.options.debug: diff --git a/aodhclient/tests/unit/test_shell.py b/aodhclient/tests/unit/test_shell.py new file mode 100644 index 0000000..a172690 --- /dev/null +++ b/aodhclient/tests/unit/test_shell.py @@ -0,0 +1,39 @@ +# Copyright 2016 Hewlett Packard Enterprise Development Company, L.P. +# +# 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. + +import sys + +from keystoneauth1 import exceptions +import mock +import six +import testtools + +from aodhclient import shell + + +class CliTest(testtools.TestCase): + + @mock.patch('sys.stderr', six.StringIO()) + def test_cli_http_error_with_details(self): + shell.AodhShell().clean_up( + None, None, exceptions.HttpError('foo', details='bar')) + stderr_lines = sys.stderr.getvalue().splitlines() + self.assertEqual(1, len(stderr_lines)) + self.assertEqual('bar', stderr_lines[0]) + + @mock.patch('sys.stderr', six.StringIO()) + def test_cli_http_error_without_details(self): + shell.AodhShell().clean_up(None, None, exceptions.HttpError('foo')) + stderr_lines = sys.stderr.getvalue().splitlines() + self.assertEqual(0, len(stderr_lines))