From d6ef83021e2d8ea4ff7efc5acf7e40f7227a8a26 Mon Sep 17 00:00:00 2001 From: Alistair Coles <alistair.coles@hpe.com> Date: Wed, 3 Feb 2016 13:44:53 +0000 Subject: [PATCH] Support --os-identity-api-version option Add support for the auth-version to be specified using --os-identity-api-version or OS_IDENTITY_API_VERSION for compatibility with other openstack client command line options. The auth version used will be selected as follows: - if either --auth-version or --os-identity-api-version is set, use that value - otherwise use the value of ST_AUTH_VERSION, if set - otherwise use the value of OS_AUTH_VERSION, if set - otherwise (new behaviour) use the value of OS_IDENTITY_API_VERSION, if set - otherwise default to 1.0 Note that before this change the auth version might have defaulted to 1.0 despite OS_IDENTITY_API_VERSION being set, but with this change OS_IDENTITY_API_VERSION is preferred. Change-Id: Ifba4c4e43560ede3013337b8cdbc77dc2de6e8ff Closes-Bug: #1541273 --- swiftclient/shell.py | 23 ++++++--- tests/unit/test_shell.py | 104 +++++++++++++++++++++++++++++++++++---- 2 files changed, 112 insertions(+), 15 deletions(-) diff --git a/swiftclient/shell.py b/swiftclient/shell.py index e427a893..4cad5741 100755 --- a/swiftclient/shell.py +++ b/swiftclient/shell.py @@ -1193,7 +1193,9 @@ def main(arguments=None): usage=''' usage: %prog [--version] [--help] [--os-help] [--snet] [--verbose] [--debug] [--info] [--quiet] [--auth <auth_url>] - [--auth-version <auth_version>] [--user <username>] + [--auth-version <auth_version> | + --os-identity-api-version <auth_version> ] + [--user <username>] [--key <api_key>] [--retries <num_retries>] [--os-username <auth-user-name>] [--os-password <auth-password>] [--os-user-id <auth-user-id>] @@ -1254,6 +1256,15 @@ Examples: %prog list --lh '''.strip('\n')) + + default_auth_version = '1.0' + for k in ('ST_AUTH_VERSION', 'OS_AUTH_VERSION', 'OS_IDENTITY_API_VERSION'): + try: + default_auth_version = environ[k] + break + except KeyError: + pass + parser.add_option('--os-help', action='store_true', dest='os_help', help='Show OpenStack authentication options.') parser.add_option('--os_help', action='store_true', help=SUPPRESS_HELP) @@ -1272,14 +1283,14 @@ Examples: parser.add_option('-A', '--auth', dest='auth', default=environ.get('ST_AUTH'), help='URL for obtaining an auth token.') - parser.add_option('-V', '--auth-version', + parser.add_option('-V', '--auth-version', '--os-identity-api-version', dest='auth_version', - default=environ.get('ST_AUTH_VERSION', - (environ.get('OS_AUTH_VERSION', - '1.0'))), + default=default_auth_version, type=str, help='Specify a version for authentication. ' - 'Defaults to 1.0.') + 'Defaults to env[ST_AUTH_VERSION], ' + 'env[OS_AUTH_VERSION], env[OS_IDENTITY_API_VERSION]' + ' or 1.0.') parser.add_option('-U', '--user', dest='user', default=environ.get('ST_USER'), help='User name for obtaining an auth token.') diff --git a/tests/unit/test_shell.py b/tests/unit/test_shell.py index 00546f6b..6bb97c58 100644 --- a/tests/unit/test_shell.py +++ b/tests/unit/test_shell.py @@ -1291,22 +1291,25 @@ class TestParsing(TestBase): result[0], result[1] = swiftclient.shell.parse_args(parser, args) return fake_command - def _verify_opts(self, actual_opts, opts, os_opts={}, os_opts_dict={}): + def _verify_opts(self, actual_opts, expected_opts, expected_os_opts=None, + expected_os_opts_dict=None): """ Check parsed options are correct. - :param opts: v1 style options. - :param os_opts: openstack style options. - :param os_opts_dict: openstack options that should be found in the - os_options dict. + :param expected_opts: v1 style options. + :param expected_os_opts: openstack style options. + :param expected_os_opts_dict: openstack options that should be found in + the os_options dict. """ + expected_os_opts = expected_os_opts or {} + expected_os_opts_dict = expected_os_opts_dict or {} # check the expected opts are set - for key, v in opts.items(): + for key, v in expected_opts.items(): actual = getattr(actual_opts, key) self.assertEqual(v, actual, 'Expected %s for key %s, found %s' % (v, key, actual)) - for key, v in os_opts.items(): + for key, v in expected_os_opts.items(): actual = getattr(actual_opts, "os_" + key) self.assertEqual(v, actual, 'Expected %s for key %s, found %s' % (v, key, actual)) @@ -1327,8 +1330,8 @@ class TestParsing(TestBase): if key == 'object_storage_url': # exceptions to the pattern... cli_key = 'storage_url' - if cli_key in os_opts_dict: - expect = os_opts_dict[cli_key] + if cli_key in expected_os_opts_dict: + expect = expected_os_opts_dict[cli_key] else: expect = None actual = actual_os_opts_dict[key] @@ -1386,6 +1389,89 @@ class TestParsing(TestBase): swiftclient.shell.main(args) self._verify_opts(result[0], opts, os_opts, os_opts_dict) + def test_os_identity_api_version(self): + os_opts = {"password": "secret", + "username": "user", + "auth_url": "http://example.com:5000/v3", + "identity-api-version": "3"} + + # check os_identity_api_version is sufficient in place of auth_version + args = _make_args("stat", {}, os_opts, '-') + result = [None, None] + fake_command = self._make_fake_command(result) + with mock.patch.dict(os.environ, {}): + with mock.patch('swiftclient.shell.st_stat', fake_command): + swiftclient.shell.main(args) + expected_opts = {'auth_version': '3'} + expected_os_opts = {"password": "secret", + "username": "user", + "auth_url": "http://example.com:5000/v3"} + self._verify_opts(result[0], expected_opts, expected_os_opts, {}) + + # check again using environment variables + args = _make_args("stat", {}, {}) + env = _make_env({}, os_opts) + result = [None, None] + fake_command = self._make_fake_command(result) + with mock.patch.dict(os.environ, env): + with mock.patch('swiftclient.shell.st_stat', fake_command): + swiftclient.shell.main(args) + self._verify_opts(result[0], expected_opts, expected_os_opts, {}) + + # check that last of auth-version, os-identity-api-version is preferred + args = _make_args("stat", {}, os_opts, '-') + ['--auth-version', '2.0'] + result = [None, None] + fake_command = self._make_fake_command(result) + with mock.patch.dict(os.environ, {}): + with mock.patch('swiftclient.shell.st_stat', fake_command): + swiftclient.shell.main(args) + expected_opts = {'auth_version': '2.0'} + self._verify_opts(result[0], expected_opts, expected_os_opts, {}) + + # now put auth_version ahead of os-identity-api-version + args = _make_args("stat", {"auth_version": "2.0"}, os_opts, '-') + result = [None, None] + fake_command = self._make_fake_command(result) + with mock.patch.dict(os.environ, {}): + with mock.patch('swiftclient.shell.st_stat', fake_command): + swiftclient.shell.main(args) + expected_opts = {'auth_version': '3'} + self._verify_opts(result[0], expected_opts, expected_os_opts, {}) + + # check that OS_AUTH_VERSION overrides OS_IDENTITY_API_VERSION + args = _make_args("stat", {}, {}) + env = _make_env({}, os_opts) + env.update({'OS_AUTH_VERSION': '2.0'}) + result = [None, None] + fake_command = self._make_fake_command(result) + with mock.patch.dict(os.environ, env): + with mock.patch('swiftclient.shell.st_stat', fake_command): + swiftclient.shell.main(args) + expected_opts = {'auth_version': '2.0'} + self._verify_opts(result[0], expected_opts, expected_os_opts, {}) + + # check that ST_AUTH_VERSION overrides OS_IDENTITY_API_VERSION + args = _make_args("stat", {}, {}) + env = _make_env({}, os_opts) + env.update({'ST_AUTH_VERSION': '2.0'}) + result = [None, None] + fake_command = self._make_fake_command(result) + with mock.patch.dict(os.environ, env): + with mock.patch('swiftclient.shell.st_stat', fake_command): + swiftclient.shell.main(args) + self._verify_opts(result[0], expected_opts, expected_os_opts, {}) + + # check that ST_AUTH_VERSION overrides OS_AUTH_VERSION + args = _make_args("stat", {}, {}) + env = _make_env({}, os_opts) + env.update({'ST_AUTH_VERSION': '2.0', 'OS_AUTH_VERSION': '3'}) + result = [None, None] + fake_command = self._make_fake_command(result) + with mock.patch.dict(os.environ, env): + with mock.patch('swiftclient.shell.st_stat', fake_command): + swiftclient.shell.main(args) + self._verify_opts(result[0], expected_opts, expected_os_opts, {}) + def test_args_v3(self): opts = {"auth_version": "3"} os_opts = {"password": "secret",