From bc7250f3126766c45396f43fa0864d2a650e6b4e Mon Sep 17 00:00:00 2001 From: Brendan Reilly Date: Oct 11 2019 19:54:08 +0000 Subject: Added CLI counterpart to groupListRemove Fixes: #893 --- diff --git a/cli/koji_cli/commands.py b/cli/koji_cli/commands.py index 849a6d8..fc13af7 100644 --- a/cli/koji_cli/commands.py +++ b/cli/koji_cli/commands.py @@ -111,6 +111,35 @@ def handle_block_group(goptions, session, args): session.groupListBlock(tag, group) + +def handle_remove_group(goptions, session, args): + "[admin] Remove group from tag" + usage = _("usage: %prog remove-group ") + usage += _("\n(Specify the --help global option for a list of other help options)") + parser = OptionParser(usage=usage) + (options, args) = parser.parse_args(args) + if len(args) != 2: + parser.error(_("Please specify a tag name and a group name")) + assert False # pragma: no cover + tag = args[0] + group = args[1] + + activate_session(session, goptions) + if not session.hasPerm('admin'): + error(_("This action requires admin privileges")) + + dsttag = session.getTag(tag) + if not dsttag: + error(_("Unknown tag: %s" % tag)) + + groups = dict([(p['name'], p['group_id']) for p in session.getTagGroups(tag, inherit=False)]) + group_id = groups.get(group, None) + if group_id is None: + error(_("Group %s doesn't exist within tag %s" % (group, tag))) + + session.groupListRemove(tag, group) + + def handle_assign_task(goptions, session, args): "[admin] Assign a task to a host" usage = _('usage: %prog assign-task task_id hostname') diff --git a/tests/test_cli/data/list-commands-admin.txt b/tests/test_cli/data/list-commands-admin.txt index 1d5e1c1..d94761a 100644 --- a/tests/test_cli/data/list-commands-admin.txt +++ b/tests/test_cli/data/list-commands-admin.txt @@ -42,6 +42,7 @@ admin commands: regen-repo Force a repo to be regenerated remove-channel Remove a channel entirely remove-external-repo Remove an external repo from a tag or tags, or remove entirely + remove-group Remove group from tag remove-host-from-channel Remove a host from a channel remove-pkg Remove a package from the listing for tag remove-tag Remove a tag diff --git a/tests/test_cli/data/list-commands.txt b/tests/test_cli/data/list-commands.txt index 972f42f..12bac1b 100644 --- a/tests/test_cli/data/list-commands.txt +++ b/tests/test_cli/data/list-commands.txt @@ -42,6 +42,7 @@ admin commands: regen-repo Force a repo to be regenerated remove-channel Remove a channel entirely remove-external-repo Remove an external repo from a tag or tags, or remove entirely + remove-group Remove group from tag remove-host-from-channel Remove a host from a channel remove-pkg Remove a package from the listing for tag remove-tag Remove a tag diff --git a/tests/test_cli/test_remove_group.py b/tests/test_cli/test_remove_group.py new file mode 100644 index 0000000..d478479 --- /dev/null +++ b/tests/test_cli/test_remove_group.py @@ -0,0 +1,118 @@ +from __future__ import absolute_import + +import mock +import six + +from koji_cli.commands import handle_remove_group +from . import utils + + +class TestRemoveGroup(utils.CliTestCase): + # Show long diffs in error output... + maxDiff = None + + def setUp(self): + self.error_format = """Usage: %s remove-group +(Specify the --help global option for a list of other help options) + +%s: error: {message} +""" % (self.progname, self.progname) + + @mock.patch('sys.stdout', new_callable=six.StringIO) + @mock.patch('sys.stderr', new_callable=six.StringIO) + @mock.patch('koji_cli.commands.activate_session') + def test_handle_remove_group_nonexistent_tag(self, activate_session_mock, stdout, stderr): + tag = 'nonexistent-tag' + group = 'group' + arguments = [tag, group] + options = mock.MagicMock() + + # Mock out the xmlrpc server + session = mock.MagicMock() + session.hasPerm.return_value = True + session.getTag.return_value = None + + with self.assertRaises(SystemExit): + rv = handle_remove_group(options, session, arguments) + + # assert that things were called as we expected. + activate_session_mock.assert_called_once_with(session, options) + session.hasPerm.assert_called_once_with('admin') + session.getTag.assert_called_once_with(tag) + session.getTagGroups.assert_not_called() + session.groupListRemove.assert_not_called() + + @mock.patch('sys.stdout', new_callable=six.StringIO) + @mock.patch('sys.stderr', new_callable=six.StringIO) + @mock.patch('koji_cli.commands.activate_session') + def test_handle_remove_group_nonexistent_group(self, activate_session_mock, stdout, stderr): + tag = 'tag' + group = 'group' + arguments = [tag, group] + options = mock.MagicMock() + + # Mock out the xmlrpc server + session = mock.MagicMock() + session.hasPerm.return_value = True + session.getTag.return_value = tag + session.getTagGroups.return_value = [] + + with self.assertRaises(SystemExit): + rv = handle_remove_group(options, session, arguments) + + # assert that things were called as we expected. + activate_session_mock.assert_called_once_with(session, options) + session.hasPerm.assert_called_once_with('admin') + session.getTag.assert_called_once_with(tag) + session.getTagGroups.assert_called_once_with(tag, inherit=False) + session.groupListRemove.assert_not_called() + + @mock.patch('sys.stdout', new_callable=six.StringIO) + @mock.patch('sys.stderr', new_callable=six.StringIO) + @mock.patch('koji_cli.commands.activate_session') + def test_handle_remove_group(self, activate_session_mock, stdout, stderr): + tag = 'tag' + group = 'group' + arguments = [tag, group] + options = mock.MagicMock() + + # Mock out the xmlrpc server + session = mock.MagicMock() + session.hasPerm.return_value = True + session.getTag.return_value = tag + session.getTagGroups.return_value = [ + {'name': 'group', 'group_id': 'groupId'}] + + rv = handle_remove_group(options, session, arguments) + + # assert that things were called as we expected. + activate_session_mock.assert_called_once_with(session, options) + session.hasPerm.assert_called_once_with('admin') + session.getTag.assert_called_once_with(tag) + session.getTagGroups.assert_called_once_with(tag, inherit=False) + session.groupListRemove.assert_called_once_with(tag, group) + self.assertEqual(rv, None) + + @mock.patch('sys.stdout', new_callable=six.StringIO) + @mock.patch('sys.stderr', new_callable=six.StringIO) + @mock.patch('koji_cli.commands.activate_session') + def test_handle_remove_group_error_handling(self, activate_session_mock, stdout, stderr): + session = mock.MagicMock() + options = mock.MagicMock() + + expected = self.format_error_message( + "Please specify a tag name and a group name") + for args in [[], ['tag'], ['tag', 'grp', 'etc']]: + self.assert_system_exit( + handle_remove_group, + options, + session, + args, + stderr=expected, + activate_session=None) + + # if we don't have 'admin' permission + session.hasPerm.return_value = False + with self.assertRaises(SystemExit): + rv = handle_remove_group(options, session, ['tag', 'grp']) + activate_session_mock.assert_called_with(session, options)