Skip to content

Commit 4855fef

Browse files
Huihuihhstephenfin
authored andcommitted
Compute: Add 'keypair create --type' parameter
Change-Id: I2d251e1b97fb9a8069431c867fb7fc5f42d1fd6e Story: 2002606 Task: 22225
1 parent a48c05b commit 4855fef

4 files changed

Lines changed: 161 additions & 31 deletions

File tree

openstackclient/compute/v2/keypair.py

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import os
2121
import sys
2222

23+
from novaclient import api_versions
2324
from osc_lib.command import command
2425
from osc_lib import exceptions
2526
from osc_lib import utils
@@ -53,6 +54,15 @@ def get_parser(self, prog_name):
5354
help=_("Filename for private key to save. If not used, "
5455
"print private key in console.")
5556
)
57+
parser.add_argument(
58+
'--type',
59+
metavar='<type>',
60+
choices=['ssh', 'x509'],
61+
help=_(
62+
"Keypair type. Can be ssh or x509. "
63+
"(Supported by API versions '2.2' - '2.latest')"
64+
),
65+
)
5666
return parser
5767

5868
def take_action(self, parsed_args):
@@ -70,17 +80,28 @@ def take_action(self, parsed_args):
7080
"exception": e}
7181
)
7282

73-
keypair = compute_client.keypairs.create(
74-
parsed_args.name,
75-
public_key=public_key,
76-
)
83+
kwargs = {
84+
'name': parsed_args.name,
85+
'public_key': public_key,
86+
}
87+
if parsed_args.type:
88+
if compute_client.api_version < api_versions.APIVersion('2.2'):
89+
msg = _(
90+
'--os-compute-api-version 2.2 or greater is required to '
91+
'support the --type option.'
92+
)
93+
raise exceptions.CommandError(msg)
94+
95+
kwargs['key_type'] = parsed_args.type
96+
97+
keypair = compute_client.keypairs.create(**kwargs)
7798

7899
private_key = parsed_args.private_key
79100
# Save private key into specified file
80101
if private_key:
81102
try:
82103
with io.open(
83-
os.path.expanduser(parsed_args.private_key), 'w+'
104+
os.path.expanduser(parsed_args.private_key), 'w+'
84105
) as p:
85106
p.write(keypair.private_key)
86107
except IOError as e:
@@ -150,10 +171,13 @@ def take_action(self, parsed_args):
150171
)
151172
data = compute_client.keypairs.list()
152173

153-
return (columns,
154-
(utils.get_item_properties(
155-
s, columns,
156-
) for s in data))
174+
if compute_client.api_version >= api_versions.APIVersion('2.2'):
175+
columns += ("Type", )
176+
177+
return (
178+
columns,
179+
(utils.get_item_properties(s, columns) for s in data),
180+
)
157181

158182

159183
class ShowKeypair(command.ShowOne):

openstackclient/tests/unit/compute/v2/fakes.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -877,6 +877,7 @@ def create_one_keypair(attrs=None, no_pri=False):
877877
# Set default attributes.
878878
keypair_info = {
879879
'name': 'keypair-name-' + uuid.uuid4().hex,
880+
'type': 'ssh',
880881
'fingerprint': 'dummy',
881882
'public_key': 'dummy',
882883
'user_id': 'user'

openstackclient/tests/unit/compute/v2/test_keypair.py

Lines changed: 122 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from unittest.mock import call
1818
import uuid
1919

20+
from novaclient import api_versions
2021
from osc_lib import exceptions
2122
from osc_lib import utils
2223

@@ -45,11 +46,13 @@ def setUp(self):
4546
self.columns = (
4647
'fingerprint',
4748
'name',
49+
'type',
4850
'user_id'
4951
)
5052
self.data = (
5153
self.keypair.fingerprint,
5254
self.keypair.name,
55+
self.keypair.type,
5356
self.keypair.user_id
5457
)
5558

@@ -71,7 +74,7 @@ def test_key_pair_create_no_options(self):
7174
columns, data = self.cmd.take_action(parsed_args)
7275

7376
self.keypairs_mock.create.assert_called_with(
74-
self.keypair.name,
77+
name=self.keypair.name,
7578
public_key=None
7679
)
7780

@@ -87,6 +90,7 @@ def test_keypair_create_public_key(self):
8790
self.data = (
8891
self.keypair.fingerprint,
8992
self.keypair.name,
93+
self.keypair.type,
9094
self.keypair.user_id
9195
)
9296

@@ -96,7 +100,7 @@ def test_keypair_create_public_key(self):
96100
]
97101
verifylist = [
98102
('public_key', self.keypair.public_key),
99-
('name', self.keypair.name)
103+
('name', self.keypair.name),
100104
]
101105

102106
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -109,8 +113,8 @@ def test_keypair_create_public_key(self):
109113
columns, data = self.cmd.take_action(parsed_args)
110114

111115
self.keypairs_mock.create.assert_called_with(
112-
self.keypair.name,
113-
public_key=self.keypair.public_key
116+
name=self.keypair.name,
117+
public_key=self.keypair.public_key,
114118
)
115119

116120
self.assertEqual(self.columns, columns)
@@ -124,7 +128,7 @@ def test_keypair_create_private_key(self):
124128
]
125129
verifylist = [
126130
('private_key', tmp_pk_file),
127-
('name', self.keypair.name)
131+
('name', self.keypair.name),
128132
]
129133

130134
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -136,8 +140,8 @@ def test_keypair_create_private_key(self):
136140
columns, data = self.cmd.take_action(parsed_args)
137141

138142
self.keypairs_mock.create.assert_called_with(
139-
self.keypair.name,
140-
public_key=None
143+
name=self.keypair.name,
144+
public_key=None,
141145
)
142146

143147
mock_open.assert_called_once_with(tmp_pk_file, 'w+')
@@ -146,6 +150,79 @@ def test_keypair_create_private_key(self):
146150
self.assertEqual(self.columns, columns)
147151
self.assertEqual(self.data, data)
148152

153+
def test_keypair_create_with_key_type(self):
154+
self.app.client_manager.compute.api_version = api_versions.APIVersion(
155+
'2.2')
156+
157+
for key_type in ['x509', 'ssh']:
158+
self.keypair = compute_fakes.FakeKeypair.create_one_keypair(
159+
no_pri=True)
160+
self.keypairs_mock.create.return_value = self.keypair
161+
162+
self.data = (
163+
self.keypair.fingerprint,
164+
self.keypair.name,
165+
self.keypair.type,
166+
self.keypair.user_id,
167+
)
168+
arglist = [
169+
'--public-key', self.keypair.public_key,
170+
self.keypair.name,
171+
'--type', key_type,
172+
]
173+
verifylist = [
174+
('public_key', self.keypair.public_key),
175+
('name', self.keypair.name),
176+
('type', key_type),
177+
]
178+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
179+
180+
with mock.patch('io.open') as mock_open:
181+
mock_open.return_value = mock.MagicMock()
182+
m_file = mock_open.return_value.__enter__.return_value
183+
m_file.read.return_value = 'dummy'
184+
columns, data = self.cmd.take_action(parsed_args)
185+
186+
self.keypairs_mock.create.assert_called_with(
187+
name=self.keypair.name,
188+
public_key=self.keypair.public_key,
189+
key_type=key_type,
190+
)
191+
192+
self.assertEqual(self.columns, columns)
193+
self.assertEqual(self.data, data)
194+
195+
def test_keypair_create_with_key_type_pre_v22(self):
196+
self.app.client_manager.compute.api_version = api_versions.APIVersion(
197+
'2.1')
198+
199+
for key_type in ['x509', 'ssh']:
200+
arglist = [
201+
'--public-key', self.keypair.public_key,
202+
self.keypair.name,
203+
'--type', 'ssh',
204+
]
205+
verifylist = [
206+
('public_key', self.keypair.public_key),
207+
('name', self.keypair.name),
208+
('type', 'ssh'),
209+
]
210+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
211+
212+
with mock.patch('io.open') as mock_open:
213+
mock_open.return_value = mock.MagicMock()
214+
m_file = mock_open.return_value.__enter__.return_value
215+
m_file.read.return_value = 'dummy'
216+
217+
ex = self.assertRaises(
218+
exceptions.CommandError,
219+
self.cmd.take_action,
220+
parsed_args)
221+
222+
self.assertIn(
223+
'--os-compute-api-version 2.2 or greater is required',
224+
str(ex))
225+
149226

150227
class TestKeypairDelete(TestKeypair):
151228

@@ -227,16 +304,6 @@ class TestKeypairList(TestKeypair):
227304
# Return value of self.keypairs_mock.list().
228305
keypairs = compute_fakes.FakeKeypair.create_keypairs(count=1)
229306

230-
columns = (
231-
"Name",
232-
"Fingerprint"
233-
)
234-
235-
data = ((
236-
keypairs[0].name,
237-
keypairs[0].fingerprint
238-
), )
239-
240307
def setUp(self):
241308
super(TestKeypairList, self).setUp()
242309

@@ -247,8 +314,7 @@ def setUp(self):
247314

248315
def test_keypair_list_no_options(self):
249316
arglist = []
250-
verifylist = [
251-
]
317+
verifylist = []
252318

253319
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
254320

@@ -261,8 +327,39 @@ def test_keypair_list_no_options(self):
261327

262328
self.keypairs_mock.list.assert_called_with()
263329

264-
self.assertEqual(self.columns, columns)
265-
self.assertEqual(tuple(self.data), tuple(data))
330+
self.assertEqual(('Name', 'Fingerprint'), columns)
331+
self.assertEqual(
332+
((self.keypairs[0].name, self.keypairs[0].fingerprint), ),
333+
tuple(data)
334+
)
335+
336+
def test_keypair_list_v22(self):
337+
self.app.client_manager.compute.api_version = api_versions.APIVersion(
338+
'2.2')
339+
340+
arglist = []
341+
verifylist = []
342+
343+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
344+
345+
# In base command class Lister in cliff, abstract method take_action()
346+
# returns a tuple containing the column names and an iterable
347+
# containing the data to be listed.
348+
columns, data = self.cmd.take_action(parsed_args)
349+
350+
# Set expected values
351+
352+
self.keypairs_mock.list.assert_called_with()
353+
354+
self.assertEqual(('Name', 'Fingerprint', 'Type'), columns)
355+
self.assertEqual(
356+
((
357+
self.keypairs[0].name,
358+
self.keypairs[0].fingerprint,
359+
self.keypairs[0].type,
360+
), ),
361+
tuple(data)
362+
)
266363

267364

268365
class TestKeypairShow(TestKeypair):
@@ -279,16 +376,18 @@ def setUp(self):
279376
self.columns = (
280377
"fingerprint",
281378
"name",
379+
"type",
282380
"user_id"
283381
)
284382

285383
self.data = (
286384
self.keypair.fingerprint,
287385
self.keypair.name,
386+
self.keypair.type,
288387
self.keypair.user_id
289388
)
290389

291-
def test_show_no_options(self):
390+
def test_keypair_show_no_options(self):
292391

293392
arglist = []
294393
verifylist = []
@@ -306,6 +405,7 @@ def test_keypair_show(self):
306405
self.data = (
307406
self.keypair.fingerprint,
308407
self.keypair.name,
408+
self.keypair.type,
309409
self.keypair.user_id
310410
)
311411

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
features:
3+
- Add ``--key-type`` option to ``keypair create`` command to set keypair
4+
type. Can be ssh or x509. Note that ``--os-compute-api-version 2.2`` or
5+
later is required.

0 commit comments

Comments
 (0)