Merge lp:~frankban/lpsetup/remove-ssh-args into lp:lpsetup
- remove-ssh-args
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Brad Crittenden |
Approved revision: | 70 |
Merged at revision: | 68 |
Proposed branch: | lp:~frankban/lpsetup/remove-ssh-args |
Merge into: | lp:lpsetup |
Diff against target: |
424 lines (+89/-179) 6 files modified
lpsetup/handlers.py (+7/-62) lpsetup/subcommands/inithost.py (+13/-35) lpsetup/subcommands/initlxc.py (+2/-2) lpsetup/tests/subcommands/test_inithost.py (+28/-40) lpsetup/tests/subcommands/test_initlxc.py (+1/-1) lpsetup/tests/test_handlers.py (+38/-39) |
To merge this branch: | bzr merge lp:~frankban/lpsetup/remove-ssh-args |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Francesco Banconi (community) | Approve | ||
Brad Crittenden (community) | code | Approve | |
Review via email: mp+118330@code.launchpad.net |
Commit message
Removed ssh private and public key arguments.
Description of the change
== Changes ==
Removed ssh private and public key arguments: updated subcommands and tests accordingly.
The handler *handle_ssh_keys* now just adds to namespace the names *ssh_key_path* and *valid_ssh_keys*, and raises an error if a key (of the ssh key pair) is found but not the other.
The integration test `test_install_
Launchpad QA Bot (lpqabot) wrote : | # |
The attempt to merge lp:~frankban/lpsetup/remove-ssh-args into lp:lpsetup failed. Below is the output from the failed tests.
./lpsetup/
179: E111 indentation is not a multiple of four
Francesco Banconi (frankban) : | # |
Launchpad QA Bot (lpqabot) wrote : | # |
The attempt to merge lp:~frankban/lpsetup/remove-ssh-args into lp:lpsetup failed. Below is the output from the failed tests.
nose.plugins.cover: ERROR: Coverage not available: unable to import coverage module
.......
nosetests: error: argument user can not be omitted if the script is run as root.
Eusage: nosetests [-h] {init-repo,help} ...
nosetests: error: argument user can not be omitted if the script is run as root.
Eusage: nosetests [-h] {init-repo,help} ...
nosetests: error: argument user can not be omitted if the script is run as root.
Eusage: nosetests init-repo [-h]
nosetests init-repo: error: argument user can not be omitted if the script is run as root.
Eusage: nosetests init-repo [-h]
nosetests init-repo: error: argument user can not be omitted if the script is run as root.
Eusage: nosetests init-repo [-h]
nosetests init-repo: error: argument user can not be omitted if the script is run as root.
E...usage: nosetests init-host [-h]
nosetests init-host: error: argument user can not be omitted if the script is run as root.
E.usage: nosetests [-h] {update,help} ...
nosetests: error: argument user can not be omitted if the script is run as root.
Eusage: nosetests [-h] {update,help} ...
nosetests: error: argument user can not be omitted if the script is run as root.
Eusage: nosetests [-h] {update,help} ...
nosetests: error: argument user can not ...
Preview Diff
1 | === modified file 'lpsetup/handlers.py' |
2 | --- lpsetup/handlers.py 2012-07-31 09:41:24 +0000 |
3 | +++ lpsetup/handlers.py 2012-08-06 15:14:31 +0000 |
4 | @@ -168,72 +168,17 @@ |
5 | The namespace must contain *home_dir* and *ssh_key_name*. |
6 | It should be invoked after handle_user. |
7 | |
8 | - Keys contained in the namespace are escaped:: |
9 | - |
10 | - >>> import argparse |
11 | - >>> private = r'PRIVATE\nKEY' |
12 | - >>> public = r'PUBLIC\nKEY' |
13 | - >>> namespace = argparse.Namespace( |
14 | - ... private_key=private, public_key=public, |
15 | - ... ssh_key_name='id_rsa', home_dir='/tmp/') |
16 | - >>> handle_ssh_keys(namespace) |
17 | - >>> namespace.private_key == private.decode('string-escape') |
18 | - True |
19 | - >>> namespace.public_key == public.decode('string-escape') |
20 | - True |
21 | - >>> namespace.valid_ssh_keys |
22 | - True |
23 | - |
24 | - After this handler is called, the ssh key path is present as an attribute |
25 | - of the namespace:: |
26 | - |
27 | - >>> namespace.ssh_key_path |
28 | - '/tmp/.ssh/id_rsa' |
29 | - |
30 | - Keys are None if they are not provided and can not be found in the |
31 | - current home directory:: |
32 | - |
33 | - >>> namespace = argparse.Namespace( |
34 | - ... private_key=None, public_key=None, ssh_key_name='id_rsa', |
35 | - ... home_dir='/tmp/__does_not_exists__') |
36 | - >>> handle_ssh_keys(namespace) # doctest: +ELLIPSIS |
37 | - >>> print namespace.private_key |
38 | - None |
39 | - >>> print namespace.public_key |
40 | - None |
41 | - >>> namespace.valid_ssh_keys |
42 | - False |
43 | - |
44 | - If only one of private_key and public_key is provided, a |
45 | - ValidationError will be raised. |
46 | - |
47 | - >>> namespace = argparse.Namespace( |
48 | - ... private_key=private, public_key=None, ssh_key_name='id_rsa', |
49 | - ... home_dir='/tmp/__does_not_exists__') |
50 | - >>> handle_ssh_keys(namespace) # doctest: +ELLIPSIS |
51 | - Traceback (most recent call last): |
52 | - ValidationError: arguments private-key... |
53 | + This handler adds *ssh_key_path* and *valid_ssh_keys* to the namespace. |
54 | """ |
55 | - namespace.valid_ssh_keys = True |
56 | namespace.ssh_key_path = os.path.join( |
57 | namespace.home_dir, '.ssh', namespace.ssh_key_name) |
58 | - for attr, path in ( |
59 | - ('private_key', namespace.ssh_key_path), |
60 | - ('public_key', namespace.ssh_key_path + '.pub')): |
61 | - value = getattr(namespace, attr, None) |
62 | - if value: |
63 | - setattr(namespace, attr, value.decode('string-escape')) |
64 | - else: |
65 | - try: |
66 | - value = open(path).read() |
67 | - except IOError: |
68 | - value = None |
69 | - namespace.valid_ssh_keys = False |
70 | - setattr(namespace, attr, value) |
71 | - if bool(namespace.private_key) != bool(namespace.public_key): |
72 | + namespace.valid_ssh_keys = os.path.isfile(namespace.ssh_key_path) |
73 | + public_key_path = namespace.ssh_key_path + '.pub' |
74 | + # Exits with an error if only one key of the ssh pair is found. |
75 | + if namespace.valid_ssh_keys != os.path.isfile(public_key_path): |
76 | raise ValidationError( |
77 | - "arguments private-key and public-key: " |
78 | - "both must be provided or neither must be provided.") |
79 | + 'ssh private and public keys {0}(.pub): both must exist ' |
80 | + 'or neither must exist.'.format(namespace.ssh_key_path)) |
81 | |
82 | |
83 | def handle_directories(namespace): |
84 | |
85 | === modified file 'lpsetup/subcommands/inithost.py' |
86 | --- lpsetup/subcommands/inithost.py 2012-07-30 12:04:54 +0000 |
87 | +++ lpsetup/subcommands/inithost.py 2012-08-06 15:14:31 +0000 |
88 | @@ -99,7 +99,7 @@ |
89 | os.chmod(filename, 0644) |
90 | |
91 | |
92 | -def setup_ssh(ssh_dir, private_key, public_key, valid_ssh_keys, ssh_key_path): |
93 | +def setup_ssh(ssh_dir, valid_ssh_keys, ssh_key_path): |
94 | """Set up the user's `.ssh` directory. |
95 | |
96 | Also ensure that SSH is configured correctly for the user. |
97 | @@ -107,28 +107,24 @@ |
98 | # Set up the user's ssh directory. The ssh key must be associated |
99 | # with the lpuser's Launchpad account. |
100 | mkdirs(ssh_dir) |
101 | - # Generate user ssh keys if none are supplied. |
102 | + # Generate user ssh keys if they don't exist. |
103 | pub_key_path = ssh_key_path + '.pub' |
104 | if not valid_ssh_keys: |
105 | generate_ssh_keys(ssh_key_path) |
106 | - private_key = open(ssh_key_path).read() |
107 | - public_key = open(pub_key_path).read() |
108 | - auth_file = os.path.join(ssh_dir, 'authorized_keys') |
109 | + # Write the user's public key to `authorized_keys` so that the user can |
110 | + # non-interactively ssh to the container. |
111 | + authorized_keys = os.path.join(ssh_dir, 'authorized_keys') |
112 | + authorized_keys_contents = open(pub_key_path).read() |
113 | + # Add bazaar.launchpad.net to `known_hosts`. |
114 | known_hosts = os.path.join(ssh_dir, 'known_hosts') |
115 | - known_host_content = run( |
116 | + known_host_contents = run( |
117 | 'ssh-keyscan', '-t', 'rsa', 'bazaar.launchpad.net') |
118 | files_to_write = [ |
119 | - (auth_file, public_key, 'a'), |
120 | - (known_hosts, known_host_content, 'a'), |
121 | + (authorized_keys, authorized_keys_contents, 'a'), |
122 | + (known_hosts, known_host_contents, 'a'), |
123 | ] |
124 | - if valid_ssh_keys: |
125 | - # We only write out the SSH keys if we haven't had to |
126 | - # generate them further up this function. |
127 | - files_to_write.append((ssh_key_path, private_key, 'w')) |
128 | - files_to_write.append((pub_key_path, public_key, 'w')) |
129 | for filename, contents, mode in files_to_write: |
130 | write_file_contents(filename, contents, mode, header=get_file_header()) |
131 | - os.chmod(ssh_key_path, 0600) |
132 | |
133 | |
134 | def initialize_base(user): |
135 | @@ -182,9 +178,7 @@ |
136 | """.format(modules=LP_APACHE_MODULES, hosts=HOSTS_FILE) |
137 | |
138 | |
139 | -def setup_home( |
140 | - user, full_name, email, lpuser, private_key, public_key, valid_ssh_keys, |
141 | - ssh_key_path): |
142 | +def setup_home(user, full_name, email, lpuser, valid_ssh_keys, ssh_key_path): |
143 | """Initialize the user home directory. |
144 | |
145 | This is a separate step for several reasons:: |
146 | @@ -198,9 +192,7 @@ |
147 | """ |
148 | with su(user) as env: |
149 | # Set up the `.ssh` directory. |
150 | - setup_ssh( |
151 | - os.path.join(env.home, '.ssh'), private_key, public_key, |
152 | - valid_ssh_keys, ssh_key_path) |
153 | + setup_ssh(os.path.join(env.home, '.ssh'), valid_ssh_keys, ssh_key_path) |
154 | |
155 | # Set up bzr and Launchpad authentication. |
156 | call('bzr', 'whoami', formataddr([full_name, email])) |
157 | @@ -272,7 +264,7 @@ |
158 | |
159 | setup_home_step = (setup_home, |
160 | 'user', 'full_name', 'email', 'lpuser', |
161 | - 'private_key', 'public_key', 'valid_ssh_keys', 'ssh_key_path') |
162 | + 'valid_ssh_keys', 'ssh_key_path') |
163 | |
164 | initialize_lxc_step = (initialize_lxc, ) |
165 | |
166 | @@ -321,20 +313,6 @@ |
167 | 'check out dependencies. If not provided, the system ' |
168 | 'user name is used.') |
169 | parser.add_argument( |
170 | - '-v', '--private-key', |
171 | - help='The SSH private key for the Launchpad user (without ' |
172 | - 'passphrase). If this argument is omitted and a keypair is ' |
173 | - 'not found in the home directory of the system user a new ' |
174 | - 'SSH keypair will be generated and the checkout of the ' |
175 | - 'Launchpad code will use HTTP rather than bzr+ssh.') |
176 | - parser.add_argument( |
177 | - '-b', '--public-key', |
178 | - help='The SSH public key for the Launchpad user. ' |
179 | - 'If this argument is omitted and a keypair is not found ' |
180 | - 'in the home directory of the system user a new SSH ' |
181 | - 'keypair will be generated and the checkout of the ' |
182 | - 'Launchpad code will use HTTP rather than bzr+ssh.') |
183 | - parser.add_argument( |
184 | '-S', '--ssh-key-name', default=SSH_KEY_NAME, |
185 | help='{0} [DEFAULT={1}]'.format( |
186 | 'The ssh key name used to connect to Launchpad.', |
187 | |
188 | === modified file 'lpsetup/subcommands/initlxc.py' |
189 | --- lpsetup/subcommands/initlxc.py 2012-07-31 12:35:51 +0000 |
190 | +++ lpsetup/subcommands/initlxc.py 2012-08-06 15:14:31 +0000 |
191 | @@ -208,7 +208,7 @@ |
192 | |
193 | |
194 | def inithost_in_lxc(lxc_name, ssh_key_path, user, email, full_name, lpuser, |
195 | - private_key, public_key, ssh_key_name, home_dir): |
196 | + ssh_key_name, home_dir): |
197 | """Prepare the Launchpad environment inside an LXC.""" |
198 | # Use ssh to call this script from inside the container. |
199 | args = ['init-host', '--yes', '-u', user, '-E', email, '-f', full_name, |
200 | @@ -244,7 +244,7 @@ |
201 | 'lpsetup_branch') |
202 | inithost_in_lxc_step = (inithost_in_lxc, |
203 | 'lxc_name', 'ssh_key_path', 'user', 'email', 'full_name', 'lpuser', |
204 | - 'private_key', 'public_key', 'ssh_key_name', 'home_dir') |
205 | + 'ssh_key_name', 'home_dir') |
206 | stop_lxc_step = (stop_lxc, |
207 | 'lxc_name', 'ssh_key_path') |
208 | |
209 | |
210 | === modified file 'lpsetup/tests/subcommands/test_inithost.py' |
211 | --- lpsetup/tests/subcommands/test_inithost.py 2012-07-18 10:53:15 +0000 |
212 | +++ lpsetup/tests/subcommands/test_inithost.py 2012-08-06 15:14:31 +0000 |
213 | @@ -21,7 +21,7 @@ |
214 | initialize_step = (inithost.initialize, ['user']) |
215 | setup_home_step = ( |
216 | inithost.setup_home, ['user', 'full_name', 'email', 'lpuser', |
217 | - 'private_key', 'public_key', 'valid_ssh_keys', 'ssh_key_path', |
218 | + 'valid_ssh_keys', 'ssh_key_path', |
219 | ]) |
220 | initialize_lxc_step = (inithost.initialize_lxc, []) |
221 | setup_apt_step = (inithost.setup_apt, []) |
222 | @@ -32,12 +32,9 @@ |
223 | email = get_random_string() |
224 | full_name = get_random_string() + '@example.com' |
225 | lpuser = get_random_string() |
226 | - private_key = get_random_string() |
227 | - public_key = get_random_string() |
228 | ssh_key_name = get_random_string() |
229 | - return ( |
230 | - '-u', user, '-E', email, '-f', full_name, '-l', lpuser, |
231 | - '-v', private_key, '-b', public_key, '-S', ssh_key_name) |
232 | + return ('-u', user, '-E', email, '-f', full_name, '-l', lpuser, |
233 | + '-S', ssh_key_name) |
234 | |
235 | |
236 | class InithostSmokeTest(StepsBasedSubCommandTestMixin, unittest.TestCase): |
237 | @@ -112,7 +109,7 @@ |
238 | '/tmp/foo', 'Hello, world!', 'a+') |
239 | |
240 | |
241 | -class SetupSSHTestCase(unittest.TestCase): |
242 | +class SetupSSHTest(unittest.TestCase): |
243 | """Tests for inithost.setup_ssh().""" |
244 | |
245 | def setUp(self): |
246 | @@ -122,45 +119,36 @@ |
247 | self.ssh_dir = tempfile.mkdtemp() |
248 | self.addCleanup(shutil.rmtree, self.ssh_dir) |
249 | self.addCleanup(os.remove, self.temp_filename) |
250 | - self.addCleanup(os.remove, self.temp_filename + ".pub") |
251 | - |
252 | - def test_setup_ssh_writes_to_ssh_key_path(self): |
253 | - # If inithost.setup_ssh() is told that the keys it has |
254 | - # been passed are valid, it will write them out to the provided |
255 | - # ssh_key_path. |
256 | - public_key = "Public" |
257 | - private_key = "Private" |
258 | - inithost.setup_ssh( |
259 | - self.ssh_dir, private_key, public_key, True, self.temp_filename) |
260 | - with open(self.temp_filename + '.pub', 'r') as pub_file: |
261 | - self.assertIn(public_key, pub_file.read()) |
262 | - with open(self.temp_filename, 'r') as priv_file: |
263 | - self.assertIn(private_key, priv_file.read()) |
264 | - |
265 | - def test_setup_ssh_generates_keys_if_not_passed(self): |
266 | - # If SSH keys aren't passed to setup_ssh(), the function |
267 | - # will generate some. |
268 | - inithost.setup_ssh( |
269 | - self.ssh_dir, None, None, False, self.temp_filename) |
270 | + self.addCleanup(os.remove, self.temp_filename + '.pub') |
271 | + |
272 | + def test_setup_ssh_generates_keys_if_not_present(self): |
273 | + # If SSH keys do not exist, the function will generate some. |
274 | + inithost.setup_ssh(self.ssh_dir, False, self.temp_filename) |
275 | self.assertTrue(os.path.exists(self.temp_filename)) |
276 | - self.assertTrue(os.path.exists(self.temp_filename + ".pub")) |
277 | - |
278 | - def test_setup_ssh_generates_other_files(self): |
279 | - # setup_ssh() also generates an authorized_keys file and a |
280 | - # known_hosts file in the ssh dir. |
281 | - inithost.setup_ssh( |
282 | - self.ssh_dir, None, None, False, self.temp_filename) |
283 | - self.assertTrue( |
284 | - os.path.exists(os.path.join(self.ssh_dir, 'authorized_keys'))) |
285 | - self.assertTrue( |
286 | - os.path.exists(os.path.join(self.ssh_dir, 'known_hosts'))) |
287 | + self.assertTrue(os.path.exists(self.temp_filename + '.pub')) |
288 | + |
289 | + def test_setup_ssh_generates_authorized_keys(self): |
290 | + # setup_ssh() also generates an authorized_keys file containing |
291 | + # the public key. |
292 | + inithost.setup_ssh(self.ssh_dir, False, self.temp_filename) |
293 | + authorized_keys = os.path.join(self.ssh_dir, 'authorized_keys') |
294 | + self.assertTrue(os.path.exists(authorized_keys)) |
295 | + public_key = open(self.temp_filename + '.pub').read() |
296 | + self.assertIn(public_key, open(authorized_keys).read()) |
297 | + |
298 | + def test_setup_ssh_generates_known_hosts(self): |
299 | + # setup_ssh() also generates a `known_host` file containing |
300 | + # 'bazaar.launchpad.net'. |
301 | + inithost.setup_ssh(self.ssh_dir, False, self.temp_filename) |
302 | + known_hosts = os.path.join(self.ssh_dir, 'known_hosts') |
303 | + self.assertTrue(os.path.exists(known_hosts)) |
304 | + self.assertIn('bazaar.launchpad.net', open(known_hosts).read()) |
305 | |
306 | def test_setup_ssh_creates_ssh_dir(self): |
307 | # If the ssh_dir passed to setup_ssh() doesn't exist, it |
308 | # will be created. |
309 | shutil.rmtree(self.ssh_dir) |
310 | - inithost.setup_ssh( |
311 | - self.ssh_dir, None, None, False, self.temp_filename) |
312 | + inithost.setup_ssh(self.ssh_dir, False, self.temp_filename) |
313 | self.assertTrue(os.path.exists(self.ssh_dir)) |
314 | self.assertTrue(os.path.isdir(self.ssh_dir)) |
315 | |
316 | |
317 | === modified file 'lpsetup/tests/subcommands/test_initlxc.py' |
318 | --- lpsetup/tests/subcommands/test_initlxc.py 2012-07-31 09:38:14 +0000 |
319 | +++ lpsetup/tests/subcommands/test_initlxc.py 2012-08-06 15:14:31 +0000 |
320 | @@ -30,7 +30,7 @@ |
321 | inithost_in_lxc_step = ( |
322 | initlxc.inithost_in_lxc, |
323 | ['lxc_name', 'ssh_key_path', 'user', 'email', 'full_name', 'lpuser', |
324 | - 'private_key', 'public_key', 'ssh_key_name', 'home_dir']) |
325 | + 'ssh_key_name', 'home_dir']) |
326 | stop_lxc_step = (initlxc.stop_lxc, ['lxc_name', 'ssh_key_path']) |
327 | |
328 | |
329 | |
330 | === modified file 'lpsetup/tests/test_handlers.py' |
331 | --- lpsetup/tests/test_handlers.py 2012-07-31 09:41:24 +0000 |
332 | +++ lpsetup/tests/test_handlers.py 2012-08-06 15:14:31 +0000 |
333 | @@ -228,53 +228,52 @@ |
334 | |
335 | class HandleSSHKeysTest(HandlersTestMixin, unittest.TestCase): |
336 | |
337 | - home_dir = '/tmp/__does_not_exist__' |
338 | - private = r'PRIVATE\nKEY' |
339 | - public = r'PUBLIC\nKEY' |
340 | - ssh_key_name = 'id_rsa' |
341 | + ssh_key_name = 'my_id_rsa' |
342 | |
343 | - def test_key_escaping(self): |
344 | - # Ensure the keys contained in the namespace are correctly escaped. |
345 | - namespace = argparse.Namespace( |
346 | - private_key=self.private, public_key=self.public, |
347 | + def setUp(self): |
348 | + self.home_dir = tempfile.mkdtemp() |
349 | + self.addCleanup(shutil.rmtree, self.home_dir) |
350 | + self.namespace = argparse.Namespace( |
351 | ssh_key_name=self.ssh_key_name, home_dir=self.home_dir) |
352 | - handle_ssh_keys(namespace) |
353 | - self.assertEqual( |
354 | - self.private.decode('string-escape'), |
355 | - namespace.private_key) |
356 | - self.assertEqual( |
357 | - self.public.decode('string-escape'), |
358 | - namespace.public_key) |
359 | - self.assertTrue(namespace.valid_ssh_keys) |
360 | + |
361 | + def get_ssh_key_path(self): |
362 | + return os.path.join(self.home_dir, '.ssh', self.ssh_key_name) |
363 | + |
364 | + def write_key(self, path): |
365 | + directory = os.path.dirname(path) |
366 | + if not os.path.exists(directory): |
367 | + os.mkdir(os.path.dirname(path)) |
368 | + with open(path, 'w') as f: |
369 | + f.write('KEY CONTENTS') |
370 | |
371 | def test_ssh_key_path_in_namespace(self): |
372 | # After the handler is called, the ssh key path is present |
373 | # as an attribute of the namespace. |
374 | - namespace = argparse.Namespace( |
375 | - private_key=self.private, public_key=self.public, |
376 | - ssh_key_name=self.ssh_key_name, home_dir=self.home_dir) |
377 | - handle_ssh_keys(namespace) |
378 | - expected = self.home_dir + '/.ssh/id_rsa' |
379 | - self.assertEqual(expected, namespace.ssh_key_path) |
380 | - |
381 | - def test_no_keys(self): |
382 | - # Keys are None if they are not provided and can not be found in the |
383 | - # current home directory. |
384 | - namespace = argparse.Namespace( |
385 | - private_key=None, ssh_key_name=self.ssh_key_name, |
386 | - home_dir=self.home_dir) |
387 | - handle_ssh_keys(namespace) |
388 | - self.assertIsNone(namespace.private_key) |
389 | - self.assertIsNone(namespace.public_key) |
390 | - self.assertFalse(namespace.valid_ssh_keys) |
391 | + handle_ssh_keys(self.namespace) |
392 | + self.assertEqual(self.get_ssh_key_path(), self.namespace.ssh_key_path) |
393 | + |
394 | + def test_invalid_keys(self): |
395 | + # Keys are marked as invalid if they can not be found in the |
396 | + # current home directory. |
397 | + handle_ssh_keys(self.namespace) |
398 | + self.assertFalse(self.namespace.valid_ssh_keys) |
399 | + |
400 | + def test_valid_keys(self): |
401 | + # Keys are marked as valid if they are correctly found in the |
402 | + # current home directory. |
403 | + ssh_key_path = self.get_ssh_key_path() |
404 | + self.write_key(ssh_key_path) |
405 | + self.write_key(ssh_key_path + '.pub') |
406 | + handle_ssh_keys(self.namespace) |
407 | + self.assertTrue(self.namespace.valid_ssh_keys) |
408 | |
409 | def test_only_one_key(self): |
410 | - # Ensure a `ValidationError` is raised if only one key is provided. |
411 | - namespace = argparse.Namespace( |
412 | - private_key=self.private, public_key=None, |
413 | - ssh_key_name=self.ssh_key_name, home_dir=self.home_dir) |
414 | - with self.assertNotValid('private-key'): |
415 | - handle_ssh_keys(namespace) |
416 | + # Ensure the handler raises a ValidationError if only one key |
417 | + # of the private/public pair is found. |
418 | + ssh_key_path = self.get_ssh_key_path() |
419 | + self.write_key(ssh_key_path) |
420 | + with self.assertNotValid(ssh_key_path): |
421 | + handle_ssh_keys(self.namespace) |
422 | |
423 | |
424 | class HandleTargetFromRepositoryTest(unittest.TestCase): |
Looks good. Thanks Francesco.