diff --git a/spacecmd/spacecmd.changes.blu-base.cryptokey_update b/spacecmd/spacecmd.changes.blu-base.cryptokey_update new file mode 100644 index 000000000000..0ecf1cf295f9 --- /dev/null +++ b/spacecmd/spacecmd.changes.blu-base.cryptokey_update @@ -0,0 +1 @@ +- Add spacecmd function: cryptokey_update diff --git a/spacecmd/src/spacecmd/cryptokey.py b/spacecmd/src/spacecmd/cryptokey.py index a957b8e6f082..61c28530eadf 100644 --- a/spacecmd/src/spacecmd/cryptokey.py +++ b/spacecmd/src/spacecmd/cryptokey.py @@ -51,6 +51,46 @@ def help_cryptokey_create(self): def do_cryptokey_create(self, args): + options = _cryptokey_process_options(self, args) + if options is None: + return 1 + + self.client.kickstart.keys.create(self.session, + options.description, + options.type, + options.contents) + + return 0 + +#################### + + +def help_cryptokey_update(self): + print(_('cryptokey_update: Update a cryptographic key')) + print(_('''usage: cryptokey_update [options]) + +options: + -t GPG or SSL + -d DESCRIPTION + -f KEY_FILE''')) + + +def do_cryptokey_update(self, args): + options = _cryptokey_process_options(self, args) + if options is None: + return 1 + + self.client.kickstart.keys.update(self.session, + options.description, + options.type, + options.contents) + + return 0 + +#################### + + +def _cryptokey_process_options(self, args): arg_parser = get_argument_parser() arg_parser.add_argument('-t', '--type') arg_parser.add_argument('-d', '--description') @@ -74,15 +114,15 @@ def do_cryptokey_create(self, args): else: if not options.type: logging.error(_N('The key type is required')) - return 1 + return None if not options.description: logging.error(_N('A description is required')) - return 1 + return None if not options.file: logging.error(_N('A file containing the key is required')) - return 1 + return None # read the file the user specified if options.file: @@ -90,7 +130,7 @@ def do_cryptokey_create(self, args): if not options.contents: logging.error(_N('No contents of the file')) - return 1 + return None # translate the key type to what the server expects if re.match('G', options.type, re.I): @@ -99,14 +139,9 @@ def do_cryptokey_create(self, args): options.type = 'SSL' else: logging.error(_N('Invalid key type')) - return 1 - - self.client.kickstart.keys.create(self.session, - options.description, - options.type, - options.contents) + return None - return 0 + return options #################### diff --git a/spacecmd/tests/test_cryptokey.py b/spacecmd/tests/test_cryptokey.py index 59c51d4d324c..1294787636e3 100644 --- a/spacecmd/tests/test_cryptokey.py +++ b/spacecmd/tests/test_cryptokey.py @@ -171,6 +171,164 @@ def test_cryptokey_create_SSL_key(self, shell): assert args == (shell.session, "description", "SSL", "contents") assert not kw + def test_cryptokey_update_no_keytype(self, shell): + """ + Test do_cryptokey_update without correct key type. + + :param shell: + :return: + """ + shell.help_cryptokey_update = MagicMock() + shell.client.kickstart.keys.update = MagicMock() + shell.user_confirm = MagicMock(return_value=True) + read_file = MagicMock(return_value="contents") + prompt_user = MagicMock(side_effect=["", "interactive descr", "/tmp/file.txt"]) + editor = MagicMock() + logger = MagicMock() + + with patch("spacecmd.cryptokey.prompt_user", prompt_user) as pmu, \ + patch("spacecmd.cryptokey.read_file", read_file) as rfl, \ + patch("spacecmd.cryptokey.editor", editor) as edt, \ + patch("spacecmd.cryptokey.logging", logger) as lgr: + spacecmd.cryptokey.do_cryptokey_update(shell, "") + + assert not shell.help_cryptokey_update.called + assert not shell.client.kickstart.keys.update.called + assert not editor.called + assert read_file.called + assert prompt_user.called + assert logger.error.called + + assert_expect(logger.error.call_args_list, "Invalid key type") + + def test_cryptokey_update_interactive_no_contents(self, shell): + """ + Test do_cryptokey_update without arguments (interactive, no contents given). + + :param shell: + :return: + """ + shell.help_cryptokey_update = MagicMock() + shell.client.kickstart.keys.update = MagicMock() + shell.user_confirm = MagicMock(return_value=True) + read_file = MagicMock() + prompt_user = MagicMock(side_effect=["g", "interactive descr", ""]) + editor = MagicMock() + logger = MagicMock() + + with patch("spacecmd.cryptokey.prompt_user", prompt_user) as pmu, \ + patch("spacecmd.cryptokey.read_file", read_file) as rfl, \ + patch("spacecmd.cryptokey.editor", editor) as edt, \ + patch("spacecmd.cryptokey.logging", logger) as lgr: + spacecmd.cryptokey.do_cryptokey_update(shell, "") + + assert not shell.help_cryptokey_update.called + assert not shell.client.kickstart.keys.update.called + assert not read_file.called + assert not editor.called + assert prompt_user.called + assert logger.error.called + + assert_expect(logger.error.call_args_list, "No contents of the file") + + def test_cryptokey_update_interactive_wrong_key_type(self, shell): + """ + Test do_cryptokey_update without arguments (interactive, wrong key type). + + :param shell: + :return: + """ + shell.help_cryptokey_update = MagicMock() + shell.client.kickstart.keys.update = MagicMock() + shell.user_confirm = MagicMock(return_value=True) + read_file = MagicMock(return_value="contents") + prompt_user = MagicMock(side_effect=["x", "interactive descr", "/tmp/file.txt"]) + editor = MagicMock() + logger = MagicMock() + + with patch("spacecmd.cryptokey.prompt_user", prompt_user) as pmu, \ + patch("spacecmd.cryptokey.read_file", read_file) as rfl, \ + patch("spacecmd.cryptokey.editor", editor) as edt, \ + patch("spacecmd.cryptokey.logging", logger) as lgr: + spacecmd.cryptokey.do_cryptokey_update(shell, "") + + assert not shell.help_cryptokey_update.called + assert not shell.client.kickstart.keys.update.called + assert not editor.called + assert read_file.called + assert prompt_user.called + assert logger.error.called + + assert_expect(logger.error.call_args_list, "Invalid key type") + + def test_cryptokey_update_GPG_key(self, shell): + """ + Test do_cryptokey_update with parameters, calling GPG key type. + + :param shell: + :return: + """ + shell.help_cryptokey_update = MagicMock() + shell.client.kickstart.keys.update = MagicMock() + shell.user_confirm = MagicMock(return_value=True) + read_file = MagicMock(return_value="contents") + prompt_user = MagicMock(side_effect=[]) + editor = MagicMock() + logger = MagicMock() + + with patch("spacecmd.cryptokey.prompt_user", prompt_user) as pmu, \ + patch("spacecmd.cryptokey.read_file", read_file) as rfl, \ + patch("spacecmd.cryptokey.editor", editor) as edt, \ + patch("spacecmd.cryptokey.logging", logger) as lgr: + spacecmd.cryptokey.do_cryptokey_update(shell, "-t g -d description -f /tmp/file.txt") + + assert not editor.called + assert not shell.help_cryptokey_update.called + assert not prompt_user.called + assert not logger.error.called + + assert shell.client.kickstart.keys.update.called + assert read_file.called + + for call in shell.client.kickstart.keys.update.call_args_list: + args, kw = call + assert args == (shell.session, "description", "GPG", "contents") + assert not kw + + def test_cryptokey_update_SSL_key(self, shell): + """ + Test do_cryptokey_update with parameters, calling SSL key type. + + :param shell: + :return: + """ + shell.help_cryptokey_update = MagicMock() + shell.client.kickstart.keys.update = MagicMock() + shell.user_confirm = MagicMock(return_value=True) + read_file = MagicMock(return_value="contents") + prompt_user = MagicMock(side_effect=[]) + editor = MagicMock() + logger = MagicMock() + + with patch("spacecmd.cryptokey.prompt_user", prompt_user) as pmu, \ + patch("spacecmd.cryptokey.read_file", read_file) as rfl, \ + patch("spacecmd.cryptokey.editor", editor) as edt, \ + patch("spacecmd.cryptokey.logging", logger) as lgr: + spacecmd.cryptokey.do_cryptokey_update(shell, "-t s -d description -f /tmp/file.txt") + + assert not editor.called + assert not shell.help_cryptokey_update.called + assert not prompt_user.called + assert not logger.error.called + + assert shell.client.kickstart.keys.update.called + assert read_file.called + + for call in shell.client.kickstart.keys.update.call_args_list: + args, kw = call + assert args == (shell.session, "description", "SSL", "contents") + assert not kw + def test_cryptokey_delete_noargs(self, shell): """ Test do_cryptokey_delete without parameters, so help should be displayed.