diff options
| author | Dean Troyer <dtroyer@gmail.com> | 2016-06-23 17:51:54 -0500 |
|---|---|---|
| committer | Dean Troyer <dtroyer@gmail.com> | 2016-08-05 13:48:55 -0500 |
| commit | 6a15f90daed6514e30b4af0ebb52c7864acaafcc (patch) | |
| tree | d42939bc69a82362ba1020be833a8bc97ba7ea7d /openstackclient/tests/test_shell.py | |
| parent | a42664ccaa9860c34fcd91cb4c3dbdf6805b3eb0 (diff) | |
| download | python-openstackclient-6a15f90daed6514e30b4af0ebb52c7864acaafcc.tar.gz | |
osc-lib: shell
Convert to using ClientManager and OpenStackShell from osc-lib.
* Change all internal uses of ClientManager private attributes that are
now public in osc-lib's ClientManager. Leave back-compat copies in
place in OSC's clientManager so we don't break plugins.
* Put some work-arounds in place for changes in osc-lib that we need until
a new release makes it through the g-r and u-c change process.
* Add a test for Unicode decoding of argv in shell.main() to parallel
the one in osc-lib.
Change-Id: I85289740d4ca081f2aca8c9b40ec422ad25d302c
Diffstat (limited to 'openstackclient/tests/test_shell.py')
| -rw-r--r-- | openstackclient/tests/test_shell.py | 588 |
1 files changed, 103 insertions, 485 deletions
diff --git a/openstackclient/tests/test_shell.py b/openstackclient/tests/test_shell.py index 7d0bbd12..87cd7f51 100644 --- a/openstackclient/tests/test_shell.py +++ b/openstackclient/tests/test_shell.py @@ -13,14 +13,15 @@ # under the License. # -import copy -import fixtures import mock import os -import testtools +import sys + +from osc_lib.tests import utils as osc_lib_test_utils +from oslo_utils import importutils +import wrapt from openstackclient import shell -from openstackclient.tests import utils DEFAULT_AUTH_URL = "http://127.0.0.1:5000/v2.0/" @@ -116,173 +117,97 @@ global_options = { '--os-interface': (DEFAULT_INTERFACE, True, True) } -auth_options = { - '--os-auth-url': (DEFAULT_AUTH_URL, True, True), - '--os-project-id': (DEFAULT_PROJECT_ID, True, True), - '--os-project-name': (DEFAULT_PROJECT_NAME, True, True), - '--os-domain-id': (DEFAULT_DOMAIN_ID, True, True), - '--os-domain-name': (DEFAULT_DOMAIN_NAME, True, True), - '--os-user-domain-id': (DEFAULT_USER_DOMAIN_ID, True, True), - '--os-user-domain-name': (DEFAULT_USER_DOMAIN_NAME, True, True), - '--os-project-domain-id': (DEFAULT_PROJECT_DOMAIN_ID, True, True), - '--os-project-domain-name': (DEFAULT_PROJECT_DOMAIN_NAME, True, True), - '--os-username': (DEFAULT_USERNAME, True, True), - '--os-password': (DEFAULT_PASSWORD, True, True), - '--os-region-name': (DEFAULT_REGION_NAME, True, True), - '--os-trust-id': ("1234", True, True), - '--os-auth-type': ("v2password", True, True), - '--os-token': (DEFAULT_TOKEN, True, True), - '--os-url': (DEFAULT_SERVICE_URL, True, True), - '--os-interface': (DEFAULT_INTERFACE, True, True), -} - - -def opt2attr(opt): - if opt.startswith('--os-'): - attr = opt[5:] - elif opt.startswith('--'): - attr = opt[2:] - else: - attr = opt - return attr.lower().replace('-', '_') - - -def opt2env(opt): - return opt[2:].upper().replace('-', '_') - - -def make_shell(): - """Create a new command shell and mock out some bits.""" - _shell = shell.OpenStackShell() - _shell.command_manager = mock.Mock() - - return _shell +# Wrap the osc_lib make_shell() function to set the shell class since +# osc-lib's TestShell class doesn't allow us to specify it yet. +# TODO(dtroyer): remove this once the shell_class_patch patch is released +# in osc-lib +def make_shell_wrapper(func, inst, args, kwargs): + if 'shell_class' not in kwargs: + kwargs['shell_class'] = shell.OpenStackShell + return func(*args, **kwargs) -def fake_execute(shell, cmd): - """Pretend to execute shell commands.""" - return shell.run(cmd.split()) +wrapt.wrap_function_wrapper( + osc_lib_test_utils, + 'make_shell', + make_shell_wrapper, +) -class EnvFixture(fixtures.Fixture): - """Environment Fixture. - This fixture replaces os.environ with provided env or an empty env. - """ +class TestShell(osc_lib_test_utils.TestShell): - def __init__(self, env=None): - self.new_env = env or {} + # Full name of the OpenStackShell class to test (cliff.app.App subclass) + shell_class_name = "openstackclient.shell.OpenStackShell" - def _setUp(self): - self.orig_env, os.environ = os.environ, self.new_env - self.addCleanup(self.revert) - - def revert(self): - os.environ = self.orig_env - - -class TestShell(utils.TestCase): + # TODO(dtroyer): remove this once the shell_class_patch patch is released + # in osc-lib + app_patch = shell_class_name def setUp(self): super(TestShell, self).setUp() - patch = "openstackclient.shell.OpenStackShell.run_subcommand" - self.cmd_patch = mock.patch(patch) - self.cmd_save = self.cmd_patch.start() - self.addCleanup(self.cmd_patch.stop) - self.app = mock.Mock("Test Shell") - - def _assert_initialize_app_arg(self, cmd_options, default_args): - """Check the args passed to initialize_app() - - The argv argument to initialize_app() is the remainder from parsing - global options declared in both cliff.app and - openstackclient.OpenStackShell build_option_parser(). Any global - options passed on the commmad line should not be in argv but in - _shell.options. - """ + # TODO(dtroyer): remove this once the shell_class_patch patch is + # released in osc-lib + self.shell_class = importutils.import_class(self.shell_class_name) + def _assert_token_endpoint_auth(self, cmd_options, default_args): with mock.patch( - "openstackclient.shell.OpenStackShell.initialize_app", + self.shell_class_name + ".initialize_app", self.app, ): - _shell, _cmd = make_shell(), cmd_options + " list project" - fake_execute(_shell, _cmd) - - self.app.assert_called_with(["list", "project"]) - for k in default_args.keys(): - self.assertEqual( - default_args[k], - vars(_shell.options)[k], - "%s does not match" % k, - ) - - def _assert_cloud_config_arg(self, cmd_options, default_args): - """Check the args passed to cloud_config.get_one_cloud() - - The argparse argument to get_one_cloud() is an argparse.Namespace - object that contains all of the options processed to this point in - initialize_app(). - """ - - cloud = mock.Mock(name="cloudy") - cloud.config = {} - self.occ_get_one = mock.Mock(return_value=cloud) - with mock.patch( - "os_client_config.config.OpenStackConfig.get_one_cloud", - self.occ_get_one, - ): - _shell, _cmd = make_shell(), cmd_options + " list project" - fake_execute(_shell, _cmd) - - opts = self.occ_get_one.call_args[1]['argparse'] - for k in default_args.keys(): - self.assertEqual( - default_args[k], - vars(opts)[k], - "%s does not match" % k, - ) - - def _assert_token_auth(self, cmd_options, default_args): - with mock.patch("openstackclient.shell.OpenStackShell.initialize_app", - self.app): - _shell, _cmd = make_shell(), cmd_options + " list role" - fake_execute(_shell, _cmd) + _shell = osc_lib_test_utils.make_shell( + shell_class=self.shell_class, + ) + _cmd = cmd_options + " list role" + osc_lib_test_utils.fake_execute(_shell, _cmd) + print("_shell: %s" % _shell) self.app.assert_called_with(["list", "role"]) self.assertEqual( default_args.get("token", ''), _shell.options.token, - "token" + "token", ) self.assertEqual( - default_args.get("auth_url", ''), - _shell.options.auth_url, - "auth_url" + default_args.get("url", ''), + _shell.options.url, + "url", ) - def _assert_token_endpoint_auth(self, cmd_options, default_args): - with mock.patch("openstackclient.shell.OpenStackShell.initialize_app", - self.app): - _shell, _cmd = make_shell(), cmd_options + " list role" - fake_execute(_shell, _cmd) + def _assert_token_auth(self, cmd_options, default_args): + with mock.patch( + self.app_patch + ".initialize_app", + self.app, + ): + _shell = osc_lib_test_utils.make_shell( + shell_class=self.shell_class, + ) + _cmd = cmd_options + " list role" + osc_lib_test_utils.fake_execute(_shell, _cmd) + print("_shell: %s" % _shell) self.app.assert_called_with(["list", "role"]) self.assertEqual( default_args.get("token", ''), _shell.options.token, - "token", + "token" ) self.assertEqual( - default_args.get("url", ''), - _shell.options.url, - "url", + default_args.get("auth_url", ''), + _shell.options.auth_url, + "auth_url" ) def _assert_cli(self, cmd_options, default_args): - with mock.patch("openstackclient.shell.OpenStackShell.initialize_app", - self.app): - _shell, _cmd = make_shell(), cmd_options + " list server" - fake_execute(_shell, _cmd) + with mock.patch( + self.shell_class_name + ".initialize_app", + self.app, + ): + _shell = osc_lib_test_utils.make_shell( + shell_class=self.shell_class, + ) + _cmd = cmd_options + " list server" + osc_lib_test_utils.fake_execute(_shell, _cmd) self.app.assert_called_with(["list", "server"]) self.assertEqual(default_args["compute_api_version"], @@ -297,39 +222,17 @@ class TestShell(utils.TestCase): _shell.options.os_network_api_version) -class TestShellHelp(TestShell): - """Test the deferred help flag""" - - def setUp(self): - super(TestShellHelp, self).setUp() - self.useFixture(EnvFixture()) - - @testtools.skip("skip until bug 1444983 is resolved") - def test_help_options(self): - flag = "-h list server" - kwargs = { - "deferred_help": True, - } - with mock.patch("openstackclient.shell.OpenStackShell.initialize_app", - self.app): - _shell, _cmd = make_shell(), flag - fake_execute(_shell, _cmd) - - self.assertEqual(kwargs["deferred_help"], - _shell.options.deferred_help) - - class TestShellOptions(TestShell): def setUp(self): super(TestShellOptions, self).setUp() - self.useFixture(EnvFixture()) + self.useFixture(osc_lib_test_utils.EnvFixture()) def _test_options_init_app(self, test_opts): for opt in test_opts.keys(): if not test_opts[opt][1]: continue - key = opt2attr(opt) + key = osc_lib_test_utils.opt2attr(opt) if isinstance(test_opts[opt][0], str): cmd = opt + " " + test_opts[opt][0] else: @@ -343,7 +246,7 @@ class TestShellOptions(TestShell): for opt in test_opts.keys(): if not test_opts[opt][1]: continue - key = opt2attr(opt) + key = osc_lib_test_utils.opt2attr(opt) if isinstance(test_opts[opt][0], str): cmd = opt + " " + test_opts[opt][0] else: @@ -357,12 +260,12 @@ class TestShellOptions(TestShell): for opt in test_opts.keys(): if not test_opts[opt][2]: continue - key = opt2attr(opt) + key = osc_lib_test_utils.opt2attr(opt) kwargs = { key: test_opts[opt][0], } env = { - opt2env(opt): test_opts[opt][0], + osc_lib_test_utils.opt2env(opt): test_opts[opt][0], } os.environ = env.copy() self._assert_initialize_app_arg("", kwargs) @@ -371,37 +274,16 @@ class TestShellOptions(TestShell): for opt in test_opts.keys(): if not test_opts[opt][2]: continue - key = opt2attr(opt) + key = osc_lib_test_utils.opt2attr(opt) kwargs = { key: test_opts[opt][0], } env = { - opt2env(opt): test_opts[opt][0], + osc_lib_test_utils.opt2env(opt): test_opts[opt][0], } os.environ = env.copy() self._assert_cloud_config_arg("", kwargs) - def test_empty_auth(self): - os.environ = {} - self._assert_initialize_app_arg("", {}) - self._assert_cloud_config_arg("", {}) - - def test_global_options(self): - self._test_options_init_app(global_options) - self._test_options_get_one_cloud(global_options) - - def test_auth_options(self): - self._test_options_init_app(auth_options) - self._test_options_get_one_cloud(auth_options) - - def test_global_env(self): - self._test_env_init_app(global_options) - self._test_env_get_one_cloud(global_options) - - def test_auth_env(self): - self._test_env_init_app(auth_options) - self._test_env_get_one_cloud(auth_options) - class TestShellTokenAuthEnv(TestShell): @@ -411,7 +293,7 @@ class TestShellTokenAuthEnv(TestShell): "OS_TOKEN": DEFAULT_TOKEN, "OS_AUTH_URL": DEFAULT_AUTH_URL, } - self.useFixture(EnvFixture(env.copy())) + self.useFixture(osc_lib_test_utils.EnvFixture(env.copy())) def test_env(self): flag = "" @@ -455,7 +337,7 @@ class TestShellTokenEndpointAuthEnv(TestShell): "OS_TOKEN": DEFAULT_TOKEN, "OS_URL": DEFAULT_SERVICE_URL, } - self.useFixture(EnvFixture(env.copy())) + self.useFixture(osc_lib_test_utils.EnvFixture(env.copy())) def test_env(self): flag = "" @@ -463,7 +345,7 @@ class TestShellTokenEndpointAuthEnv(TestShell): "token": DEFAULT_TOKEN, "url": DEFAULT_SERVICE_URL, } - self._assert_token_auth(flag, kwargs) + self._assert_token_endpoint_auth(flag, kwargs) def test_only_token(self): flag = "--os-token xyzpdq" @@ -502,85 +384,7 @@ class TestShellCli(TestShell): "OS_VOLUME_API_VERSION": DEFAULT_VOLUME_API_VERSION, "OS_NETWORK_API_VERSION": DEFAULT_NETWORK_API_VERSION, } - self.useFixture(EnvFixture(env.copy())) - - def test_shell_args_no_options(self): - _shell = make_shell() - with mock.patch("openstackclient.shell.OpenStackShell.initialize_app", - self.app): - fake_execute(_shell, "list user") - self.app.assert_called_with(["list", "user"]) - - def test_shell_args_ca_options(self): - _shell = make_shell() - - # NOTE(dtroyer): The commented out asserts below are the desired - # behaviour and will be uncommented when the - # handling for --verify and --insecure is fixed. - - # Default - fake_execute(_shell, "list user") - self.assertIsNone(_shell.options.verify) - self.assertIsNone(_shell.options.insecure) - self.assertEqual('', _shell.options.cacert) - self.assertTrue(_shell.verify) - - # --verify - fake_execute(_shell, "--verify list user") - self.assertTrue(_shell.options.verify) - self.assertIsNone(_shell.options.insecure) - self.assertEqual('', _shell.options.cacert) - self.assertTrue(_shell.verify) - - # --insecure - fake_execute(_shell, "--insecure list user") - self.assertIsNone(_shell.options.verify) - self.assertTrue(_shell.options.insecure) - self.assertEqual('', _shell.options.cacert) - self.assertFalse(_shell.verify) - - # --os-cacert - fake_execute(_shell, "--os-cacert foo list user") - self.assertIsNone(_shell.options.verify) - self.assertIsNone(_shell.options.insecure) - self.assertEqual('foo', _shell.options.cacert) - self.assertTrue(_shell.verify) - - # --os-cacert and --verify - fake_execute(_shell, "--os-cacert foo --verify list user") - self.assertTrue(_shell.options.verify) - self.assertIsNone(_shell.options.insecure) - self.assertEqual('foo', _shell.options.cacert) - self.assertTrue(_shell.verify) - - # --os-cacert and --insecure - # NOTE(dtroyer): Per bug https://bugs.launchpad.net/bugs/1447784 - # in this combination --insecure now overrides any - # --os-cacert setting, where before --insecure - # was ignored if --os-cacert was set. - fake_execute(_shell, "--os-cacert foo --insecure list user") - self.assertIsNone(_shell.options.verify) - self.assertTrue(_shell.options.insecure) - self.assertEqual('foo', _shell.options.cacert) - self.assertFalse(_shell.verify) - - def test_shell_args_cert_options(self): - _shell = make_shell() - - # Default - fake_execute(_shell, "list user") - self.assertEqual('', _shell.options.cert) - self.assertEqual('', _shell.options.key) - - # --os-cert - fake_execute(_shell, "--os-cert mycert list user") - self.assertEqual('mycert', _shell.options.cert) - self.assertEqual('', _shell.options.key) - - # --os-key - fake_execute(_shell, "--os-key mickey list user") - self.assertEqual('', _shell.options.cert) - self.assertEqual('mickey', _shell.options.key) + self.useFixture(osc_lib_test_utils.EnvFixture(env.copy())) def test_default_env(self): flag = "" @@ -605,220 +409,34 @@ class TestShellCli(TestShell): } self._assert_cli(flag, kwargs) - @mock.patch("os_client_config.config.OpenStackConfig._load_config_file") - def test_shell_args_cloud_no_vendor(self, config_mock): - config_mock.return_value = ('file.yaml', copy.deepcopy(CLOUD_1)) - _shell = make_shell() - - fake_execute( - _shell, - "--os-cloud scc list user", - ) - self.assertEqual( - 'scc', - _shell.cloud.name, - ) - - # These come from clouds.yaml - self.assertEqual( - DEFAULT_AUTH_URL, - _shell.cloud.config['auth']['auth_url'], - ) - self.assertEqual( - DEFAULT_PROJECT_NAME, - _shell.cloud.config['auth']['project_name'], - ) - self.assertEqual( - 'zaphod', - _shell.cloud.config['auth']['username'], - ) - self.assertEqual( - 'occ-cloud', - _shell.cloud.config['region_name'], - ) - self.assertEqual( - 'glazed', - _shell.cloud.config['donut'], - ) - self.assertEqual( - 'public', - _shell.cloud.config['interface'], - ) - - @mock.patch("os_client_config.config.OpenStackConfig._load_vendor_file") - @mock.patch("os_client_config.config.OpenStackConfig._load_config_file") - def test_shell_args_cloud_public(self, config_mock, public_mock): - config_mock.return_value = ('file.yaml', copy.deepcopy(CLOUD_2)) - public_mock.return_value = ('file.yaml', copy.deepcopy(PUBLIC_1)) - _shell = make_shell() - - fake_execute( - _shell, - "--os-cloud megacloud list user", - ) - self.assertEqual( - 'megacloud', - _shell.cloud.name, - ) - - # These come from clouds-public.yaml - self.assertEqual( - DEFAULT_AUTH_URL, - _shell.cloud.config['auth']['auth_url'], - ) - self.assertEqual( - 'cake', - _shell.cloud.config['donut'], - ) - - # These come from clouds.yaml - self.assertEqual( - 'heart-o-gold', - _shell.cloud.config['auth']['project_name'], - ) - self.assertEqual( - 'zaphod', - _shell.cloud.config['auth']['username'], - ) - self.assertEqual( - 'occ-cloud', - _shell.cloud.config['region_name'], - ) - - self.assertEqual('mycert', _shell.cloud.config['cert']) - self.assertEqual('mickey', _shell.cloud.config['key']) - - @mock.patch("os_client_config.config.OpenStackConfig._load_vendor_file") - @mock.patch("os_client_config.config.OpenStackConfig._load_config_file") - def test_shell_args_precedence(self, config_mock, vendor_mock): - config_mock.return_value = ('file.yaml', copy.deepcopy(CLOUD_2)) - vendor_mock.return_value = ('file.yaml', copy.deepcopy(PUBLIC_1)) - _shell = make_shell() - - # Test command option overriding config file value - fake_execute( - _shell, - "--os-cloud megacloud --os-region-name krikkit list user", - ) - self.assertEqual( - 'megacloud', - _shell.cloud.name, - ) - - # These come from clouds-public.yaml - self.assertEqual( - DEFAULT_AUTH_URL, - _shell.cloud.config['auth']['auth_url'], - ) - self.assertEqual( - 'cake', - _shell.cloud.config['donut'], - ) - - # These come from clouds.yaml - self.assertEqual( - 'heart-o-gold', - _shell.cloud.config['auth']['project_name'], - ) - self.assertEqual( - 'zaphod', - _shell.cloud.config['auth']['username'], - ) - self.assertEqual( - 'krikkit', - _shell.cloud.config['region_name'], - ) - - -class TestShellCliEnv(TestShell): + +class TestShellArgV(TestShell): + """Test the deferred help flag""" def setUp(self): - super(TestShellCliEnv, self).setUp() - env = { - 'OS_REGION_NAME': 'occ-env', - } - self.useFixture(EnvFixture(env.copy())) - - @mock.patch("os_client_config.config.OpenStackConfig._load_vendor_file") - @mock.patch("os_client_config.config.OpenStackConfig._load_config_file") - def test_shell_args_precedence_1(self, config_mock, vendor_mock): - config_mock.return_value = ('file.yaml', copy.deepcopy(CLOUD_2)) - vendor_mock.return_value = ('file.yaml', copy.deepcopy(PUBLIC_1)) - _shell = make_shell() - - # Test env var - fake_execute( - _shell, - "--os-cloud megacloud list user", - ) - self.assertEqual( - 'megacloud', - _shell.cloud.name, - ) - - # These come from clouds-public.yaml - self.assertEqual( - DEFAULT_AUTH_URL, - _shell.cloud.config['auth']['auth_url'], - ) - self.assertEqual( - 'cake', - _shell.cloud.config['donut'], - ) - - # These come from clouds.yaml - self.assertEqual( - 'heart-o-gold', - _shell.cloud.config['auth']['project_name'], - ) - self.assertEqual( - 'zaphod', - _shell.cloud.config['auth']['username'], - ) - self.assertEqual( - 'occ-env', - _shell.cloud.config['region_name'], - ) - - @mock.patch("os_client_config.config.OpenStackConfig._load_vendor_file") - @mock.patch("os_client_config.config.OpenStackConfig._load_config_file") - def test_shell_args_precedence_2(self, config_mock, vendor_mock): - config_mock.return_value = ('file.yaml', copy.deepcopy(CLOUD_2)) - vendor_mock.return_value = ('file.yaml', copy.deepcopy(PUBLIC_1)) - _shell = make_shell() - - # Test command option overriding config file value - fake_execute( - _shell, - "--os-cloud megacloud --os-region-name krikkit list user", - ) - self.assertEqual( - 'megacloud', - _shell.cloud.name, - ) - - # These come from clouds-public.yaml - self.assertEqual( - DEFAULT_AUTH_URL, - _shell.cloud.config['auth']['auth_url'], - ) - self.assertEqual( - 'cake', - _shell.cloud.config['donut'], - ) - - # These come from clouds.yaml - self.assertEqual( - 'heart-o-gold', - _shell.cloud.config['auth']['project_name'], - ) - self.assertEqual( - 'zaphod', - _shell.cloud.config['auth']['username'], - ) - - # These come from the command line - self.assertEqual( - 'krikkit', - _shell.cloud.config['region_name'], - ) + super(TestShellArgV, self).setUp() + + def test_shell_argv(self): + """Test argv decoding + + Python 2 does nothing with argv while Python 3 decodes it into + Unicode before we ever see it. We manually decode when running + under Python 2 so verify that we get the right argv types. + + Use the argv supplied by the test runner so we get actual Python + runtime behaviour; we only need to check the type of argv[0] + which will alwyas be present. + """ + + with mock.patch( + self.shell_class_name + ".run", + self.app, + ): + # Ensure type gets through unmolested through shell.main() + argv = sys.argv + shell.main(sys.argv) + self.assertEqual(type(argv[0]), type(self.app.call_args[0][0][0])) + + # When shell.main() gets sys.argv itself it should be decoded + shell.main() + self.assertEqual(type(u'x'), type(self.app.call_args[0][0][0])) |
