Improve import related error handling
If there was a problem importing a library we would incorrectly raise an unsupported version error: $ glance --os-image-api-version 1 image-list "1" is not a supported API version. Example values are "1" or "2". We should change this to provide information on the failed import, eg: $ glance --os-image-api-version 1 image-list No module named badimport We also now raise the full stacktrace in this case if '--debug' is passed on the command line. Change-Id: I1c687ae6c5da239090b0b7a4a855b3271a9076da Related-bug: 1402632
This commit is contained in:
parent
9fac2a557e
commit
1f89beb609
glanceclient
@ -47,6 +47,8 @@ from keystoneclient import session
|
|||||||
osprofiler_profiler = importutils.try_import("osprofiler.profiler")
|
osprofiler_profiler = importutils.try_import("osprofiler.profiler")
|
||||||
_ = _i18n._
|
_ = _i18n._
|
||||||
|
|
||||||
|
SUPPORTED_VERSIONS = [1, 2]
|
||||||
|
|
||||||
|
|
||||||
class OpenStackImagesShell(object):
|
class OpenStackImagesShell(object):
|
||||||
|
|
||||||
@ -291,12 +293,7 @@ class OpenStackImagesShell(object):
|
|||||||
|
|
||||||
self.subcommands = {}
|
self.subcommands = {}
|
||||||
subparsers = parser.add_subparsers(metavar='<subcommand>')
|
subparsers = parser.add_subparsers(metavar='<subcommand>')
|
||||||
try:
|
submodule = utils.import_versioned_module(version, 'shell')
|
||||||
submodule = utils.import_versioned_module(version, 'shell')
|
|
||||||
except ImportError:
|
|
||||||
print('"%s" is not a supported API version. Example '
|
|
||||||
'values are "1" or "2".' % version)
|
|
||||||
utils.exit()
|
|
||||||
|
|
||||||
self._find_actions(subparsers, submodule)
|
self._find_actions(subparsers, submodule)
|
||||||
self._find_actions(subparsers, self)
|
self._find_actions(subparsers, self)
|
||||||
@ -602,14 +599,32 @@ class OpenStackImagesShell(object):
|
|||||||
# build available subcommands based on version
|
# build available subcommands based on version
|
||||||
try:
|
try:
|
||||||
api_version = int(options.os_image_api_version or url_version or 1)
|
api_version = int(options.os_image_api_version or url_version or 1)
|
||||||
|
if api_version not in SUPPORTED_VERSIONS:
|
||||||
|
raise ValueError
|
||||||
except ValueError:
|
except ValueError:
|
||||||
print("Invalid API version parameter")
|
msg = ("Invalid API version parameter. "
|
||||||
utils.exit()
|
"Supported values are %s" % SUPPORTED_VERSIONS)
|
||||||
|
utils.exit(msg=msg)
|
||||||
|
|
||||||
if api_version == 2:
|
if api_version == 2:
|
||||||
self._cache_schemas(options)
|
self._cache_schemas(options)
|
||||||
|
|
||||||
subcommand_parser = self.get_subcommand_parser(api_version)
|
try:
|
||||||
|
subcommand_parser = self.get_subcommand_parser(api_version)
|
||||||
|
except ImportError as e:
|
||||||
|
if options.debug:
|
||||||
|
traceback.print_exc()
|
||||||
|
if not str(e):
|
||||||
|
# Add a generic import error message if the raised ImportError
|
||||||
|
# has none.
|
||||||
|
raise ImportError('Unable to import module. Re-run '
|
||||||
|
'with --debug for more info.')
|
||||||
|
raise
|
||||||
|
except Exception:
|
||||||
|
if options.debug:
|
||||||
|
traceback.print_exc()
|
||||||
|
raise
|
||||||
|
|
||||||
self.parser = subcommand_parser
|
self.parser = subcommand_parser
|
||||||
|
|
||||||
# Handle top-level --help/-h before attempting to parse
|
# Handle top-level --help/-h before attempting to parse
|
||||||
|
@ -27,10 +27,11 @@ import requests
|
|||||||
from requests_mock.contrib import fixture as rm_fixture
|
from requests_mock.contrib import fixture as rm_fixture
|
||||||
import six
|
import six
|
||||||
|
|
||||||
|
from glanceclient.common import utils
|
||||||
from glanceclient import exc
|
from glanceclient import exc
|
||||||
from glanceclient import shell as openstack_shell
|
from glanceclient import shell as openstack_shell
|
||||||
|
from glanceclient.tests import utils as testutils
|
||||||
|
|
||||||
from glanceclient.tests import utils
|
|
||||||
#NOTE (esheffield) Used for the schema caching tests
|
#NOTE (esheffield) Used for the schema caching tests
|
||||||
from glanceclient.v2 import schemas as schemas
|
from glanceclient.v2 import schemas as schemas
|
||||||
import json
|
import json
|
||||||
@ -75,7 +76,7 @@ _s = V3_TOKEN.add_service('image', name='glance')
|
|||||||
_s.add_standard_endpoints(public=DEFAULT_IMAGE_URL)
|
_s.add_standard_endpoints(public=DEFAULT_IMAGE_URL)
|
||||||
|
|
||||||
|
|
||||||
class ShellTest(utils.TestCase):
|
class ShellTest(testutils.TestCase):
|
||||||
# auth environment to use
|
# auth environment to use
|
||||||
auth_env = FAKE_V2_ENV.copy()
|
auth_env = FAKE_V2_ENV.copy()
|
||||||
# expected auth plugin to invoke
|
# expected auth plugin to invoke
|
||||||
@ -311,6 +312,58 @@ class ShellTest(utils.TestCase):
|
|||||||
except SystemExit as ex:
|
except SystemExit as ex:
|
||||||
self.assertEqual(130, ex.code)
|
self.assertEqual(130, ex.code)
|
||||||
|
|
||||||
|
@mock.patch('glanceclient.common.utils.exit', side_effect=utils.exit)
|
||||||
|
def test_shell_illegal_version(self, mock_exit):
|
||||||
|
# Only int versions are allowed on cli
|
||||||
|
shell = openstack_shell.OpenStackImagesShell()
|
||||||
|
argstr = '--os-image-api-version 1.1 image-list'
|
||||||
|
try:
|
||||||
|
shell.main(argstr.split())
|
||||||
|
except SystemExit as ex:
|
||||||
|
self.assertEqual(1, ex.code)
|
||||||
|
msg = ("Invalid API version parameter. "
|
||||||
|
"Supported values are %s" % openstack_shell.SUPPORTED_VERSIONS)
|
||||||
|
mock_exit.assert_called_with(msg=msg)
|
||||||
|
|
||||||
|
@mock.patch('glanceclient.common.utils.exit', side_effect=utils.exit)
|
||||||
|
def test_shell_unsupported_version(self, mock_exit):
|
||||||
|
# Test an integer version which is not supported (-1)
|
||||||
|
shell = openstack_shell.OpenStackImagesShell()
|
||||||
|
argstr = '--os-image-api-version -1 image-list'
|
||||||
|
try:
|
||||||
|
shell.main(argstr.split())
|
||||||
|
except SystemExit as ex:
|
||||||
|
self.assertEqual(1, ex.code)
|
||||||
|
msg = ("Invalid API version parameter. "
|
||||||
|
"Supported values are %s" % openstack_shell.SUPPORTED_VERSIONS)
|
||||||
|
mock_exit.assert_called_with(msg=msg)
|
||||||
|
|
||||||
|
@mock.patch.object(openstack_shell.OpenStackImagesShell,
|
||||||
|
'get_subcommand_parser')
|
||||||
|
def test_shell_import_error_with_mesage(self, mock_parser):
|
||||||
|
msg = 'Unable to import module xxx'
|
||||||
|
mock_parser.side_effect = ImportError('%s' % msg)
|
||||||
|
shell = openstack_shell.OpenStackImagesShell()
|
||||||
|
argstr = '--os-image-api-version 2 image-list'
|
||||||
|
try:
|
||||||
|
shell.main(argstr.split())
|
||||||
|
self.fail('No import error returned')
|
||||||
|
except ImportError as e:
|
||||||
|
self.assertEqual(msg, str(e))
|
||||||
|
|
||||||
|
@mock.patch.object(openstack_shell.OpenStackImagesShell,
|
||||||
|
'get_subcommand_parser')
|
||||||
|
def test_shell_import_error_default_message(self, mock_parser):
|
||||||
|
mock_parser.side_effect = ImportError
|
||||||
|
shell = openstack_shell.OpenStackImagesShell()
|
||||||
|
argstr = '--os-image-api-version 2 image-list'
|
||||||
|
try:
|
||||||
|
shell.main(argstr.split())
|
||||||
|
self.fail('No import error returned')
|
||||||
|
except ImportError as e:
|
||||||
|
msg = 'Unable to import module. Re-run with --debug for more info.'
|
||||||
|
self.assertEqual(msg, str(e))
|
||||||
|
|
||||||
@mock.patch('glanceclient.v1.client.Client')
|
@mock.patch('glanceclient.v1.client.Client')
|
||||||
def test_auth_plugin_invocation_without_username_with_v1(self, v1_client):
|
def test_auth_plugin_invocation_without_username_with_v1(self, v1_client):
|
||||||
self.make_env(exclude='OS_USERNAME')
|
self.make_env(exclude='OS_USERNAME')
|
||||||
@ -419,7 +472,7 @@ class ShellTestWithKeystoneV3Auth(ShellTest):
|
|||||||
self.assertNotIn(r, stdout.split())
|
self.assertNotIn(r, stdout.split())
|
||||||
|
|
||||||
|
|
||||||
class ShellCacheSchemaTest(utils.TestCase):
|
class ShellCacheSchemaTest(testutils.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(ShellCacheSchemaTest, self).setUp()
|
super(ShellCacheSchemaTest, self).setUp()
|
||||||
self._mock_client_setup()
|
self._mock_client_setup()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user