From 17f641e1c3ac58acdc39d064369395198d2654d2 Mon Sep 17 00:00:00 2001 From: He Jie Xu Date: Tue, 19 Jun 2018 12:19:49 +0000 Subject: [PATCH] Compute: Add user id support for keypair This patch adds functionality of specific the user id when create, delete, show and list keypairs. Change-Id: Ib826f1f4f5a73d1875ba0f02e124b3222c4d05ed Co-Authored-By: tianhui --- openstackclient/compute/v2/keypair.py | 86 ++++++++- .../tests/unit/compute/v2/test_keypair.py | 171 +++++++++++++++++- .../keypair-user-id-db694210695a0ee0.yaml | 6 + 3 files changed, 250 insertions(+), 13 deletions(-) create mode 100644 releasenotes/notes/keypair-user-id-db694210695a0ee0.yaml diff --git a/openstackclient/compute/v2/keypair.py b/openstackclient/compute/v2/keypair.py index ae653e76ee..157dd8cd90 100644 --- a/openstackclient/compute/v2/keypair.py +++ b/openstackclient/compute/v2/keypair.py @@ -64,10 +64,20 @@ class CreateKeypair(command.ShowOne): "(Supported by API versions '2.2' - '2.latest')" ), ) + parser.add_argument( + '--user', + metavar='', + help=_( + 'The owner of the keypair. (admin only) (name or ID). ' + 'Requires ``--os-compute-api-version`` 2.10 or greater.' + ), + ) + identity_common.add_user_domain_option_to_parser(parser) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute + identity_client = self.app.client_manager.identity public_key = parsed_args.public_key if public_key: @@ -89,12 +99,26 @@ class CreateKeypair(command.ShowOne): if compute_client.api_version < api_versions.APIVersion('2.2'): msg = _( '--os-compute-api-version 2.2 or greater is required to ' - 'support the --type option.' + 'support the --type option' ) raise exceptions.CommandError(msg) kwargs['key_type'] = parsed_args.type + if parsed_args.user: + if compute_client.api_version < api_versions.APIVersion('2.10'): + msg = _( + '--os-compute-api-version 2.10 or greater is required to ' + 'support the --user option' + ) + raise exceptions.CommandError(msg) + + kwargs['user_id'] = identity_common.find_user( + identity_client, + parsed_args.user, + parsed_args.user_domain, + ).id + keypair = compute_client.keypairs.create(**kwargs) private_key = parsed_args.private_key @@ -139,16 +163,43 @@ class DeleteKeypair(command.Command): nargs='+', help=_("Name of key(s) to delete (name only)") ) + parser.add_argument( + '--user', + metavar='', + help=_( + 'The owner of the keypair. (admin only) (name or ID). ' + 'Requires ``--os-compute-api-version`` 2.10 or greater.' + ), + ) + identity_common.add_user_domain_option_to_parser(parser) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute + identity_client = self.app.client_manager.identity + + kwargs = {} result = 0 + + if parsed_args.user: + if compute_client.api_version < api_versions.APIVersion('2.10'): + msg = _( + '--os-compute-api-version 2.10 or greater is required to ' + 'support the --user option' + ) + raise exceptions.CommandError(msg) + + kwargs['user_id'] = identity_common.find_user( + identity_client, + parsed_args.user, + parsed_args.user_domain, + ).id + for n in parsed_args.name: try: data = utils.find_resource( compute_client.keypairs, n) - compute_client.keypairs.delete(data.name) + compute_client.keypairs.delete(data.name, **kwargs) except Exception as e: result += 1 LOG.error(_("Failed to delete key with name " @@ -229,12 +280,39 @@ class ShowKeypair(command.ShowOne): default=False, help=_("Show only bare public key paired with the generated key") ) + parser.add_argument( + '--user', + metavar='', + help=_( + 'The owner of the keypair. (admin only) (name or ID). ' + 'Requires ``--os-compute-api-version`` 2.10 or greater.' + ), + ) + identity_common.add_user_domain_option_to_parser(parser) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute - keypair = utils.find_resource(compute_client.keypairs, - parsed_args.name) + identity_client = self.app.client_manager.identity + + kwargs = {} + + if parsed_args.user: + if compute_client.api_version < api_versions.APIVersion('2.10'): + msg = _( + '--os-compute-api-version 2.10 or greater is required to ' + 'support the --user option' + ) + raise exceptions.CommandError(msg) + + kwargs['user_id'] = identity_common.find_user( + identity_client, + parsed_args.user, + parsed_args.user_domain, + ).id + + keypair = utils.find_resource( + compute_client.keypairs, parsed_args.name, **kwargs) info = {} info.update(keypair._info) diff --git a/openstackclient/tests/unit/compute/v2/test_keypair.py b/openstackclient/tests/unit/compute/v2/test_keypair.py index 5e6a47414f..56cbe3f100 100644 --- a/openstackclient/tests/unit/compute/v2/test_keypair.py +++ b/openstackclient/tests/unit/compute/v2/test_keypair.py @@ -38,6 +38,15 @@ class TestKeypair(compute_fakes.TestComputev2): self.keypairs_mock = self.app.client_manager.compute.keypairs self.keypairs_mock.reset_mock() + # Initialize the user mock + self.users_mock = self.app.client_manager.identity.users + self.users_mock.reset_mock() + self.users_mock.get.return_value = fakes.FakeResource( + None, + copy.deepcopy(identity_fakes.USER), + loaded=True, + ) + class TestKeypairCreate(TestKeypair): @@ -226,6 +235,54 @@ class TestKeypairCreate(TestKeypair): '--os-compute-api-version 2.2 or greater is required', str(ex)) + def test_key_pair_create_with_user(self): + + self.app.client_manager.compute.api_version = \ + api_versions.APIVersion('2.10') + + arglist = [ + '--user', identity_fakes.user_name, + self.keypair.name, + ] + verifylist = [ + ('user', identity_fakes.user_name), + ('name', self.keypair.name), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + + self.keypairs_mock.create.assert_called_with( + name=self.keypair.name, + public_key=None, + user_id=identity_fakes.user_id, + ) + + self.assertEqual({}, columns) + self.assertEqual({}, data) + + def test_key_pair_create_with_user_pre_v210(self): + + self.app.client_manager.compute.api_version = \ + api_versions.APIVersion('2.9') + + arglist = [ + '--user', identity_fakes.user_name, + self.keypair.name, + ] + verifylist = [ + ('user', identity_fakes.user_name), + ('name', self.keypair.name), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + ex = self.assertRaises( + exceptions.CommandError, + self.cmd.take_action, + parsed_args) + self.assertIn( + '--os-compute-api-version 2.10 or greater is required', str(ex)) + class TestKeypairDelete(TestKeypair): @@ -301,6 +358,51 @@ class TestKeypairDelete(TestKeypair): self.keypairs[0].name ) + def test_keypair_delete_with_user(self): + + self.app.client_manager.compute.api_version = \ + api_versions.APIVersion('2.10') + + arglist = [ + '--user', identity_fakes.user_name, + self.keypairs[0].name + ] + verifylist = [ + ('user', identity_fakes.user_name), + ('name', [self.keypairs[0].name]), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + ret = self.cmd.take_action(parsed_args) + + self.assertIsNone(ret) + self.keypairs_mock.delete.assert_called_with( + self.keypairs[0].name, + user_id=identity_fakes.user_id, + ) + + def test_keypair_delete_with_user_pre_v210(self): + + self.app.client_manager.compute.api_version = \ + api_versions.APIVersion('2.9') + + arglist = [ + '--user', identity_fakes.user_name, + self.keypairs[0].name + ] + verifylist = [ + ('user', identity_fakes.user_name), + ('name', [self.keypairs[0].name]), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + ex = self.assertRaises( + exceptions.CommandError, + self.cmd.take_action, + parsed_args) + self.assertIn( + '--os-compute-api-version 2.10 or greater is required', str(ex)) + class TestKeypairList(TestKeypair): @@ -310,14 +412,6 @@ class TestKeypairList(TestKeypair): def setUp(self): super(TestKeypairList, self).setUp() - self.users_mock = self.app.client_manager.identity.users - self.users_mock.reset_mock() - self.users_mock.get.return_value = fakes.FakeResource( - None, - copy.deepcopy(identity_fakes.USER), - loaded=True, - ) - self.keypairs_mock.list.return_value = self.keypairs # Get the command object to test @@ -477,11 +571,14 @@ class TestKeypairShow(TestKeypair): verifylist = [ ('name', self.keypair.name) ] - parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) + self.keypairs_mock.get.assert_called_with( + self.keypair.name, + ) + self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) @@ -502,3 +599,59 @@ class TestKeypairShow(TestKeypair): self.assertEqual({}, columns) self.assertEqual({}, data) + + def test_keypair_show_with_user(self): + + # overwrite the setup one because we want to omit private_key + self.keypair = compute_fakes.FakeKeypair.create_one_keypair( + no_pri=True) + self.keypairs_mock.get.return_value = self.keypair + + self.data = ( + self.keypair.fingerprint, + self.keypair.name, + self.keypair.type, + self.keypair.user_id + ) + + self.app.client_manager.compute.api_version = \ + api_versions.APIVersion('2.10') + + arglist = [ + '--user', identity_fakes.user_name, + self.keypair.name, + ] + verifylist = [ + ('user', identity_fakes.user_name), + ('name', self.keypair.name) + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + + self.users_mock.get.assert_called_with(identity_fakes.user_name) + self.keypairs_mock.get.assert_called_with( + self.keypair.name, + ) + + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, data) + + def test_keypair_show_with_user_pre_v210(self): + + arglist = [ + '--user', identity_fakes.user_name, + self.keypair.name, + ] + verifylist = [ + ('user', identity_fakes.user_name), + ('name', self.keypair.name) + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + ex = self.assertRaises( + exceptions.CommandError, + self.cmd.take_action, + parsed_args) + self.assertIn( + '--os-compute-api-version 2.10 or greater is required', str(ex)) diff --git a/releasenotes/notes/keypair-user-id-db694210695a0ee0.yaml b/releasenotes/notes/keypair-user-id-db694210695a0ee0.yaml new file mode 100644 index 0000000000..073973e2cf --- /dev/null +++ b/releasenotes/notes/keypair-user-id-db694210695a0ee0.yaml @@ -0,0 +1,6 @@ +--- +features: + - | + Add ``--user`` option to the ``keypair create``, ``keypair delete``, and + ``keypair show`` commands. Only available starting with + ``--os-compute-api-version 2.10``.