diff --git a/novaclient/__init__.py b/novaclient/__init__.py index 76a83fa75..6b728d1f9 100644 --- a/novaclient/__init__.py +++ b/novaclient/__init__.py @@ -25,4 +25,4 @@ API_MIN_VERSION = api_versions.APIVersion("2.1") # when client supported the max version, and bumped sequentially, otherwise # the client may break due to server side new version may include some # backward incompatible change. -API_MAX_VERSION = api_versions.APIVersion("2.34") +API_MAX_VERSION = api_versions.APIVersion("2.35") diff --git a/novaclient/tests/functional/v2/test_keypairs.py b/novaclient/tests/functional/v2/test_keypairs.py index c55333e92..dba132c51 100644 --- a/novaclient/tests/functional/v2/test_keypairs.py +++ b/novaclient/tests/functional/v2/test_keypairs.py @@ -91,3 +91,30 @@ class TestKeypairsNovaClientV210(base.TenantTestBase): self.assertRaises( ValueError, self._get_column_value_from_single_row_table, output, "Name") + + +class TestKeypairsNovaClientV235(base.TenantTestBase): + """Keypairs functional tests for v2.35 nova-api microversion.""" + + COMPUTE_API_VERSION = "2.35" + + def test_create_and_list_keypair_with_marker_and_limit(self): + names = [] + for i in range(3): + names.append(self.name_generate("v2_35")) + self.nova("keypair-add %s --user %s" % (names[i], self.user_id)) + self.addCleanup(self.another_nova, "keypair-delete %s" % names[i]) + + # sort keypairs before pagination + names = sorted(names) + + # list only one keypair after the first + output_1 = self.another_nova("keypair-list --limit 1 --marker %s" % + names[0]) + output_2 = self.nova("keypair-list --limit 1 --marker %s --user %s" % + (names[0], self.user_id)) + self.assertEqual(output_1, output_2) + # it should be table with only one second key-pair + self.assertEqual( + names[1], self._get_column_value_from_single_row_table(output_1, + "Name")) diff --git a/novaclient/tests/unit/v2/fakes.py b/novaclient/tests/unit/v2/fakes.py index edaeafb23..b4b671ffd 100644 --- a/novaclient/tests/unit/v2/fakes.py +++ b/novaclient/tests/unit/v2/fakes.py @@ -1190,7 +1190,7 @@ class FakeHTTPClient(base_client.HTTPClient): return (200, {}, {'keypair': self.get_os_keypairs()[2]['keypairs'][0]['keypair']}) - def get_os_keypairs(self, *kw): + def get_os_keypairs(self, user_id=None, limit=None, marker=None, *kw): return (200, {}, { "keypairs": [{"keypair": { "public_key": "FAKE_SSH_RSA", diff --git a/novaclient/tests/unit/v2/test_keypairs.py b/novaclient/tests/unit/v2/test_keypairs.py index 19570c76a..cf310b0ef 100644 --- a/novaclient/tests/unit/v2/test_keypairs.py +++ b/novaclient/tests/unit/v2/test_keypairs.py @@ -111,3 +111,19 @@ class KeypairsV22TestCase(KeypairsTest): 'public_key': pub_key, 'type': 'ssh'}}) self.assertIsInstance(kp, keypairs.Keypair) + + +class KeypairsV35TestCase(KeypairsTest): + def setUp(self): + super(KeypairsV35TestCase, self).setUp() + self.cs.api_version = api_versions.APIVersion("2.35") + + def test_list_keypairs(self): + kps = self.cs.keypairs.list(user_id='test_user', marker='test_kp', + limit=3) + self.assert_request_id(kps, fakes.FAKE_REQUEST_ID_LIST) + self.assert_called('GET', + '/%s?limit=3&marker=test_kp&user_id=test_user' + % self.keypair_prefix) + for kp in kps: + self.assertIsInstance(kp, keypairs.Keypair) diff --git a/novaclient/tests/unit/v2/test_shell.py b/novaclient/tests/unit/v2/test_shell.py index 4fcd295b4..96a26c8ab 100644 --- a/novaclient/tests/unit/v2/test_shell.py +++ b/novaclient/tests/unit/v2/test_shell.py @@ -2873,6 +2873,21 @@ class ShellTest(utils.TestCase): self.run_command('keypair-list') self.assert_called('GET', '/os-keypairs') + def test_keypair_list_with_user_id(self): + self.run_command('keypair-list --user test_user', api_version='2.10') + self.assert_called('GET', '/os-keypairs?user_id=test_user') + + def test_keypair_list_with_limit_and_marker(self): + self.run_command('keypair-list --marker test_kp --limit 3', + api_version='2.35') + self.assert_called('GET', '/os-keypairs?limit=3&marker=test_kp') + + def test_keypair_list_with_user_id_limit_and_marker(self): + self.run_command('keypair-list --user test_user --marker test_kp ' + '--limit 3', api_version='2.35') + self.assert_called( + 'GET', '/os-keypairs?limit=3&marker=test_kp&user_id=test_user') + def test_keypair_show(self): self.run_command('keypair-show test') self.assert_called('GET', '/os-keypairs/test') diff --git a/novaclient/v2/keypairs.py b/novaclient/v2/keypairs.py index 505435c6c..9ac05eda2 100644 --- a/novaclient/v2/keypairs.py +++ b/novaclient/v2/keypairs.py @@ -19,6 +19,7 @@ Keypair interface (1.1 extension). from novaclient import api_versions from novaclient import base +from novaclient import utils class Keypair(base.Resource): @@ -162,7 +163,7 @@ class KeypairManager(base.ManagerWithFind): """ return self._list('/%s' % self.keypair_prefix, 'keypairs') - @api_versions.wraps("2.10") + @api_versions.wraps("2.10", "2.34") def list(self, user_id=None): """ Get a list of keypairs. @@ -172,3 +173,25 @@ class KeypairManager(base.ManagerWithFind): query_string = "?user_id=%s" % user_id if user_id else "" url = '/%s%s' % (self.keypair_prefix, query_string) return self._list(url, 'keypairs') + + @api_versions.wraps("2.35") + def list(self, user_id=None, marker=None, limit=None): + """ + Get a list of keypairs. + + :param user_id: Id of key-pairs owner (Admin only). + :param marker: Begin returning keypairs that appear later in the + keypair list than that represented by this keypair name + (optional). + :param limit: maximum number of keypairs to return (optional). + """ + params = {} + if user_id: + params['user_id'] = user_id + if limit: + params['limit'] = int(limit) + if marker: + params['marker'] = str(marker) + query_string = utils.prepare_query_string(params) + url = '/%s%s' % (self.keypair_prefix, query_string) + return self._list(url, 'keypairs') diff --git a/novaclient/v2/shell.py b/novaclient/v2/shell.py index d873740b4..09dc47b16 100644 --- a/novaclient/v2/shell.py +++ b/novaclient/v2/shell.py @@ -3119,7 +3119,7 @@ def do_keypair_list(cs, args): utils.print_list(keypairs, columns) -@api_versions.wraps("2.10") +@api_versions.wraps("2.10", "2.34") @utils.arg( '--user', metavar='', @@ -3132,6 +3132,36 @@ def do_keypair_list(cs, args): utils.print_list(keypairs, columns) +@api_versions.wraps("2.35") +@utils.arg( + '--user', + metavar='', + default=None, + help=_('List key-pairs of specified user ID (Admin only).')) +@utils.arg( + '--marker', + dest='marker', + metavar='', + default=None, + help=_('The last keypair of the previous page; displays list of keypairs ' + 'after "marker".')) +@utils.arg( + '--limit', + dest='limit', + metavar='', + type=int, + default=None, + help=_("Maximum number of keypairs to display. If limit == -1, all " + "keypairs will be displayed. If limit is bigger than " + "'osapi_max_limit' option of Nova API, limit 'osapi_max_limit' " + "will be used instead.")) +def do_keypair_list(cs, args): + """Print a list of keypairs for a user""" + keypairs = cs.keypairs.list(args.user, args.marker, args.limit) + columns = _get_keypairs_list_columns(cs, args) + utils.print_list(keypairs, columns) + + def _print_keypair(keypair): kp = keypair._info.copy() pk = kp.pop('public_key') diff --git a/releasenotes/notes/microversion-v2_35-537619a43278fbb5.yaml b/releasenotes/notes/microversion-v2_35-537619a43278fbb5.yaml new file mode 100644 index 000000000..0b220a4db --- /dev/null +++ b/releasenotes/notes/microversion-v2_35-537619a43278fbb5.yaml @@ -0,0 +1,5 @@ +--- +features: + - Added microversion v2.35 that adds pagination support for keypairs with + the help of new optional parameters 'limit' and 'marker' which were added + to keypair-list command. \ No newline at end of file