From 6f58f38748085e6a104de6f9e992469d3b685d5a Mon Sep 17 00:00:00 2001 From: Rob Crittenden Date: Fri, 7 Jan 2011 11:17:55 -0500 Subject: Display the entries that failed when deleting with --continue. We collected the failures but didn't report it back. This changes the API of most delete commands so rather than returning a boolean it returns a dict with the only current key as failed. This also adds a new parameter flag, suppress_empty. This will try to not print values that are empty if included. This makes the output of the delete commands a bit prettier. ticket 687 --- ipalib/cli.py | 9 ++++++--- ipalib/frontend.py | 9 +++++---- ipalib/output.py | 8 +++++++- ipalib/plugins/aci.py | 2 +- ipalib/plugins/baseldap.py | 8 ++++++-- ipalib/plugins/delegation.py | 2 +- ipalib/plugins/selfservice.py | 2 +- tests/test_xmlrpc/test_automount_plugin.py | 24 ++++++++++++++++-------- tests/test_xmlrpc/test_group_plugin.py | 6 +++--- tests/test_xmlrpc/test_hbac_plugin.py | 2 +- tests/test_xmlrpc/test_hbacsvcgroup_plugin.py | 4 ++-- tests/test_xmlrpc/test_host_plugin.py | 4 ++-- tests/test_xmlrpc/test_hostgroup_plugin.py | 4 ++-- tests/test_xmlrpc/test_netgroup_plugin.py | 2 +- tests/test_xmlrpc/test_passwd_plugin.py | 2 +- tests/test_xmlrpc/test_permission_plugin.py | 6 +++--- tests/test_xmlrpc/test_privilege_plugin.py | 2 +- tests/test_xmlrpc/test_pwpolicy.py | 2 +- tests/test_xmlrpc/test_role_plugin.py | 6 +++--- tests/test_xmlrpc/test_service_plugin.py | 2 +- tests/test_xmlrpc/test_sudocmd_plugin.py | 2 +- tests/test_xmlrpc/test_sudocmdgroup_plugin.py | 6 +++--- tests/test_xmlrpc/test_sudorule_plugin.py | 2 +- tests/test_xmlrpc/test_user_plugin.py | 6 ++++-- 24 files changed, 73 insertions(+), 49 deletions(-) diff --git a/ipalib/cli.py b/ipalib/cli.py index 436607f2..892db808 100644 --- a/ipalib/cli.py +++ b/ipalib/cli.py @@ -326,16 +326,16 @@ class textui(backend.Backend): for attr in sorted(entry): print_attr(attr) - def print_entries(self, entries, order=None, labels=None, print_all=True, format='%s: %s', indent=1): + def print_entries(self, entries, order=None, labels=None, flags=None, print_all=True, format='%s: %s', indent=1): assert isinstance(entries, (list, tuple)) first = True for entry in entries: if not first: print '' first = False - self.print_entry(entry, order, labels, print_all, format, indent) + self.print_entry(entry, order, labels, flags, print_all, format, indent) - def print_entry(self, entry, order=None, labels=None, print_all=True, format='%s: %s', indent=1): + def print_entry(self, entry, order=None, labels=None, flags=None, print_all=True, format='%s: %s', indent=1): """ """ if isinstance(entry, (list, tuple)): @@ -351,7 +351,10 @@ class textui(backend.Backend): if key not in entry: continue label = labels.get(key, key) + flag = flags.get(key, []) value = entry[key] + if 'suppress_empty' in flag and value in [u'', '', [], None]: + continue if isinstance(value, dict): if frontend.entry_count(value) == 0: continue diff --git a/ipalib/frontend.py b/ipalib/frontend.py index 18ea7287..7177bd18 100644 --- a/ipalib/frontend.py +++ b/ipalib/frontend.py @@ -895,6 +895,7 @@ class Command(HasParam): labels = None else: labels = dict((p.name, unicode(p.label)) for p in self.output_params()) + flags = dict((p.name, p.flags) for p in self.output_params()) for o in self.output: outp = self.output[o] @@ -912,13 +913,13 @@ class Command(HasParam): # Return an error to the shell rv = 1 if isinstance(outp, ListOfEntries): - textui.print_entries(result, order, labels, print_all) + textui.print_entries(result, order, labels, flags, print_all) elif isinstance(result, (tuple, list)): - textui.print_entries(result, order, labels, print_all) + textui.print_entries(result, order, labels, flags, print_all) elif isinstance(outp, Entry): - textui.print_entry(result, order, labels, print_all) + textui.print_entry(result, order, labels, flags, print_all) elif isinstance(result, dict): - textui.print_entry(result, order, labels, print_all) + textui.print_entry(result, order, labels, flags, print_all) elif isinstance(result, unicode): if o == 'summary': textui.print_summary(result) diff --git a/ipalib/output.py b/ipalib/output.py index 60abe798..61713627 100644 --- a/ipalib/output.py +++ b/ipalib/output.py @@ -135,9 +135,15 @@ standard_list_of_entries = ( ) standard_delete = ( + summary, + Output('result', dict, 'list of deletions that failed'), + value, +) + +standard_boolean = ( summary, Output('result', bool, 'True means the operation was successful'), value, ) -standard_value = standard_delete +standard_value = standard_boolean diff --git a/ipalib/plugins/aci.py b/ipalib/plugins/aci.py index 0193be5d..939fe535 100644 --- a/ipalib/plugins/aci.py +++ b/ipalib/plugins/aci.py @@ -473,7 +473,7 @@ class aci_del(crud.Delete): Delete ACI. """ INTERNAL = True - has_output = output.standard_delete + has_output = output.standard_boolean msg_summary = _('Deleted ACI "%(value)s"') def execute(self, aciname, **kw): diff --git a/ipalib/plugins/baseldap.py b/ipalib/plugins/baseldap.py index ecc3fd0b..fbe4fcec 100644 --- a/ipalib/plugins/baseldap.py +++ b/ipalib/plugins/baseldap.py @@ -136,6 +136,10 @@ global_output_params = ( Str('memberuser', label=_('Failed users/groups'), ), + Str('failed', + label=_('Failed to remove'), + flags=['suppress_empty'], + ), ) @@ -937,8 +941,8 @@ class LDAPDelete(LDAPMultiQuery): deleted.append(pkey) if self.obj.primary_key and pkeyiter[0] is not None: - return dict(result=result, value=u','.join(deleted)) - return dict(result=result, value=u'') + return dict(result=dict(failed=u','.join(failed)), value=u','.join(deleted)) + return dict(result=dict(failed=u''), value=u'') def pre_callback(self, ldap, dn, *keys, **options): return dn diff --git a/ipalib/plugins/delegation.py b/ipalib/plugins/delegation.py index 6ed22442..19d4c6da 100644 --- a/ipalib/plugins/delegation.py +++ b/ipalib/plugins/delegation.py @@ -174,7 +174,7 @@ class delegation_del(crud.Delete): Delete a delegation. """ - has_output = output.standard_delete + has_output = output.standard_boolean msg_summary = _('Deleted delegation "%(value)s"') def execute(self, aciname, **kw): diff --git a/ipalib/plugins/selfservice.py b/ipalib/plugins/selfservice.py index b5f754ee..adf6acb7 100644 --- a/ipalib/plugins/selfservice.py +++ b/ipalib/plugins/selfservice.py @@ -134,7 +134,7 @@ class selfservice_del(crud.Delete): Delete a selfservice. """ - has_output = output.standard_delete + has_output = output.standard_boolean msg_summary = _('Deleted selfservice "%(value)s"') def execute(self, aciname, **kw): diff --git a/tests/test_xmlrpc/test_automount_plugin.py b/tests/test_xmlrpc/test_automount_plugin.py index e793a454..92c695d4 100644 --- a/tests/test_xmlrpc/test_automount_plugin.py +++ b/tests/test_xmlrpc/test_automount_plugin.py @@ -147,7 +147,8 @@ class test_automount(XMLRPC_test): """ delkey_kw={'automountkey': self.keyname, 'raw': True} res = api.Command['automountkey_del'](self.locname, self.mapname, **delkey_kw)['result'] - assert res == True + assert res + assert_attr_equal(res, 'failed', '') # Verify that it is gone try: @@ -162,7 +163,8 @@ class test_automount(XMLRPC_test): Test the `xmlrpc.automountlocation_del` method. """ res = api.Command['automountlocation_del'](self.locname)['result'] - assert res == True + assert res + assert_attr_equal(res, 'failed', '') # Verify that it is gone try: @@ -227,7 +229,8 @@ class test_automount_indirect(XMLRPC_test): """ delkey_kw = {'automountkey': self.keyname} res = api.Command['automountkey_del'](self.locname, self.parentmap, **delkey_kw)['result'] - assert res == True + assert res + assert_attr_equal(res, 'failed', '') # Verify that it is gone try: @@ -242,7 +245,8 @@ class test_automount_indirect(XMLRPC_test): Remove the indirect map for auto.home. """ res = api.Command['automountmap_del'](self.locname, self.mapname)['result'] - assert res == True + assert res + assert_attr_equal(res, 'failed', '') # Verify that it is gone try: @@ -257,7 +261,8 @@ class test_automount_indirect(XMLRPC_test): Remove the location. """ res = api.Command['automountlocation_del'](self.locname)['result'] - assert res == True + assert res + assert_attr_equal(res, 'failed', '') # Verity that it is gone try: @@ -310,7 +315,8 @@ class test_automount_indirect_no_parent(XMLRPC_test): """ delkey_kw={'automountkey': self.keyname} res = api.Command['automountkey_del'](self.locname, self.parentmap, **delkey_kw)['result'] - assert res == True + assert res + assert_attr_equal(res, 'failed', '') # Verify that it is gone try: @@ -325,7 +331,8 @@ class test_automount_indirect_no_parent(XMLRPC_test): Remove the indirect map for auto.home. """ res = api.Command['automountmap_del'](self.locname, self.mapname)['result'] - assert res == True + assert res + assert_attr_equal(res, 'failed', '') # Verify that it is gone try: @@ -340,7 +347,8 @@ class test_automount_indirect_no_parent(XMLRPC_test): Remove the location. """ res = api.Command['automountlocation_del'](self.locname)['result'] - assert res == True + assert res + assert_attr_equal(res, 'failed', '') # Verity that it is gone try: diff --git a/tests/test_xmlrpc/test_group_plugin.py b/tests/test_xmlrpc/test_group_plugin.py index 56ed2e5e..5b2584b9 100644 --- a/tests/test_xmlrpc/test_group_plugin.py +++ b/tests/test_xmlrpc/test_group_plugin.py @@ -497,7 +497,7 @@ class test_group(Declarative): desc='Delete %r' % group1, command=('group_del', [group1], {}), expected=dict( - result=True, + result=dict(failed=u''), value=group1, summary=u'Deleted group "testgroup1"', ) @@ -532,7 +532,7 @@ class test_group(Declarative): desc='Delete %r' % group2, command=('group_del', [group2], {}), expected=dict( - result=True, + result=dict(failed=u''), value=group2, summary=u'Deleted group "testgroup2"', ) @@ -652,7 +652,7 @@ class test_group(Declarative): desc='Now delete the unmanaged group %r' % user1, command=('group_del', [user1], {}), expected=dict( - result=True, + result=dict(failed=u''), value=user1, summary=u'Deleted group "%s"' % user1, ) diff --git a/tests/test_xmlrpc/test_hbac_plugin.py b/tests/test_xmlrpc/test_hbac_plugin.py index 1d51c17a..50456547 100644 --- a/tests/test_xmlrpc/test_hbac_plugin.py +++ b/tests/test_xmlrpc/test_hbac_plugin.py @@ -405,7 +405,7 @@ class test_hbac(XMLRPC_test): """ Test deleting a HBAC rule using `xmlrpc.hbacrule_del`. """ - assert api.Command['hbacrule_del'](self.rule_name)['result'] is True + api.Command['hbacrule_del'](self.rule_name) # verify that it's gone try: api.Command['hbacrule_show'](self.rule_name) diff --git a/tests/test_xmlrpc/test_hbacsvcgroup_plugin.py b/tests/test_xmlrpc/test_hbacsvcgroup_plugin.py index 9bd8c76e..25b8f9fd 100644 --- a/tests/test_xmlrpc/test_hbacsvcgroup_plugin.py +++ b/tests/test_xmlrpc/test_hbacsvcgroup_plugin.py @@ -230,7 +230,7 @@ class test_hbacsvcgroup(Declarative): expected=dict( value=hbacsvcgroup1, summary=u'Deleted HBAC Service group "testhbacsvcgroup1"', - result=True, + result=dict(failed=u''), ), ), @@ -241,7 +241,7 @@ class test_hbacsvcgroup(Declarative): expected=dict( value=hbacsvc1, summary=u'Deleted service "%s"' % hbacsvc1, - result=True, + result=dict(failed=u''), ), ) diff --git a/tests/test_xmlrpc/test_host_plugin.py b/tests/test_xmlrpc/test_host_plugin.py index 20953017..18f813d5 100644 --- a/tests/test_xmlrpc/test_host_plugin.py +++ b/tests/test_xmlrpc/test_host_plugin.py @@ -370,7 +370,7 @@ class test_host(Declarative): expected=dict( value=fqdn1, summary=u'Deleted host "%s"' % fqdn1, - result=True, + result=dict(failed=u''), ), ), @@ -444,7 +444,7 @@ class test_host(Declarative): expected=dict( value=short1, summary=u'Deleted host "%s"' % short1, - result=True, + result=dict(failed=u''), ), ), diff --git a/tests/test_xmlrpc/test_hostgroup_plugin.py b/tests/test_xmlrpc/test_hostgroup_plugin.py index f443c8c0..99ca9226 100644 --- a/tests/test_xmlrpc/test_hostgroup_plugin.py +++ b/tests/test_xmlrpc/test_hostgroup_plugin.py @@ -238,7 +238,7 @@ class test_hostgroup(Declarative): expected=dict( value=hostgroup1, summary=u'Deleted hostgroup "testhostgroup1"', - result=True, + result=dict(failed=u''), ), ), @@ -249,7 +249,7 @@ class test_hostgroup(Declarative): expected=dict( value=fqdn1, summary=u'Deleted host "%s"' % fqdn1, - result=True, + result=dict(failed=u''), ), ) diff --git a/tests/test_xmlrpc/test_netgroup_plugin.py b/tests/test_xmlrpc/test_netgroup_plugin.py index b9fb8dfa..5e73d0ed 100644 --- a/tests/test_xmlrpc/test_netgroup_plugin.py +++ b/tests/test_xmlrpc/test_netgroup_plugin.py @@ -1057,7 +1057,7 @@ class test_netgroup(Declarative): expected=dict( value=netgroup1, summary=u'Deleted netgroup "%s"' % netgroup1, - result=True, + result=dict(failed=u''), ), ), diff --git a/tests/test_xmlrpc/test_passwd_plugin.py b/tests/test_xmlrpc/test_passwd_plugin.py index ecb4beec..32e75acb 100644 --- a/tests/test_xmlrpc/test_passwd_plugin.py +++ b/tests/test_xmlrpc/test_passwd_plugin.py @@ -59,7 +59,7 @@ class test_passwd(XMLRPC_test): """ Remove the test user """ - assert api.Command['user_del'](self.uid)['result'] is True + api.Command['user_del'](self.uid) # Verify that it is gone try: diff --git a/tests/test_xmlrpc/test_permission_plugin.py b/tests/test_xmlrpc/test_permission_plugin.py index 80ddb4d7..9d066cc8 100644 --- a/tests/test_xmlrpc/test_permission_plugin.py +++ b/tests/test_xmlrpc/test_permission_plugin.py @@ -336,7 +336,7 @@ class test_permission(Declarative): desc='Delete %r' % permission1, command=('permission_del', [permission1], {}), expected=dict( - result=True, + result=dict(failed=u''), value=permission1, summary=u'Deleted permission "%s"' % permission1, ) @@ -368,7 +368,7 @@ class test_permission(Declarative): desc='Delete %r' % permission2, command=('permission_del', [permission2], {}), expected=dict( - result=True, + result=dict(failed=u''), value=permission2, summary=u'Deleted permission "%s"' % permission2, ) @@ -391,7 +391,7 @@ class test_permission(Declarative): desc='Delete %r' % privilege1, command=('privilege_del', [privilege1], {}), expected=dict( - result=True, + result=dict(failed=u''), value=privilege1, summary=u'Deleted privilege "%s"' % privilege1, ) diff --git a/tests/test_xmlrpc/test_privilege_plugin.py b/tests/test_xmlrpc/test_privilege_plugin.py index adcf86ba..5b0bcc61 100644 --- a/tests/test_xmlrpc/test_privilege_plugin.py +++ b/tests/test_xmlrpc/test_privilege_plugin.py @@ -355,7 +355,7 @@ class test_privilege(Declarative): desc='Delete %r' % privilege1, command=('privilege_del', [privilege1], {}), expected=dict( - result=True, + result=dict(failed=u''), value=privilege1, summary=u'Deleted privilege "%s"' % privilege1, ) diff --git a/tests/test_xmlrpc/test_pwpolicy.py b/tests/test_xmlrpc/test_pwpolicy.py index 5cfc1492..3cfc311b 100644 --- a/tests/test_xmlrpc/test_pwpolicy.py +++ b/tests/test_xmlrpc/test_pwpolicy.py @@ -164,7 +164,7 @@ class test_pwpolicy(XMLRPC_test): """ Test the `xmlrpc.pwpolicy_del` method. """ - assert api.Command['pwpolicy_del'](self.group)['result'] is True + api.Command['pwpolicy_del'](self.group) # Verify that it is gone try: api.Command['pwpolicy_show'](self.group) diff --git a/tests/test_xmlrpc/test_role_plugin.py b/tests/test_xmlrpc/test_role_plugin.py index 283da2a0..28d1c6b4 100644 --- a/tests/test_xmlrpc/test_role_plugin.py +++ b/tests/test_xmlrpc/test_role_plugin.py @@ -411,7 +411,7 @@ class test_role(Declarative): desc='Delete %r' % group1, command=('group_del', [group1], {}), expected=dict( - result=True, + result=dict(failed=u''), value=group1, summary=u'Deleted group "testgroup1"', ) @@ -495,7 +495,7 @@ class test_role(Declarative): desc='Delete %r' % role1, command=('role_del', [role1], {}), expected=dict( - result=True, + result=dict(failed=u''), value=role1, summary=u'Deleted role "%s"' % role1, ) @@ -545,7 +545,7 @@ class test_role(Declarative): desc='Delete %r' % role2, command=('role_del', [role2], {}), expected=dict( - result=True, + result=dict(failed=u''), value=role2, summary=u'Deleted role "%s"' % role2, ) diff --git a/tests/test_xmlrpc/test_service_plugin.py b/tests/test_xmlrpc/test_service_plugin.py index 9d0936b6..a541cae1 100644 --- a/tests/test_xmlrpc/test_service_plugin.py +++ b/tests/test_xmlrpc/test_service_plugin.py @@ -280,7 +280,7 @@ class test_host(Declarative): expected=dict( value=service1, summary=u'Deleted service "%s"' % service1, - result=True, + result=dict(failed=u''), ), ), diff --git a/tests/test_xmlrpc/test_sudocmd_plugin.py b/tests/test_xmlrpc/test_sudocmd_plugin.py index 47c476f8..daf3ca65 100644 --- a/tests/test_xmlrpc/test_sudocmd_plugin.py +++ b/tests/test_xmlrpc/test_sudocmd_plugin.py @@ -163,7 +163,7 @@ class test_sudocmd(Declarative): expected=dict( value=sudocmd1, summary=u'Deleted sudo command "%s"' % sudocmd1, - result=True, + result=dict(failed=u''), ), ), diff --git a/tests/test_xmlrpc/test_sudocmdgroup_plugin.py b/tests/test_xmlrpc/test_sudocmdgroup_plugin.py index 5eb534b4..358b6dcd 100644 --- a/tests/test_xmlrpc/test_sudocmdgroup_plugin.py +++ b/tests/test_xmlrpc/test_sudocmdgroup_plugin.py @@ -449,7 +449,7 @@ class test_sudocmdgroup(Declarative): desc='Delete %r' % sudocmdgroup1, command=('sudocmdgroup_del', [sudocmdgroup1], {}), expected=dict( - result=True, + result=dict(failed=u''), value=sudocmdgroup1, summary=u'Deleted sudo command group "testsudocmdgroup1"', ) @@ -484,7 +484,7 @@ class test_sudocmdgroup(Declarative): desc='Delete %r' % sudocmdgroup2, command=('sudocmdgroup_del', [sudocmdgroup2], {}), expected=dict( - result=True, + result=dict(failed=u''), value=sudocmdgroup2, summary=u'Deleted sudo command group "testsudocmdgroup2"', ) @@ -519,7 +519,7 @@ class test_sudocmdgroup(Declarative): desc='Now delete the sudo command %r' % sudocmd1, command=('sudocmd_del', [sudocmd1], {}), expected=dict( - result=True, + result=dict(failed=u''), value=sudocmd1, summary=u'Deleted sudo command "%s"' % sudocmd1, ) diff --git a/tests/test_xmlrpc/test_sudorule_plugin.py b/tests/test_xmlrpc/test_sudorule_plugin.py index d6c24727..89f0af3a 100644 --- a/tests/test_xmlrpc/test_sudorule_plugin.py +++ b/tests/test_xmlrpc/test_sudorule_plugin.py @@ -449,7 +449,7 @@ class test_sudorule(XMLRPC_test): """ Test deleting a Sudo rule using `xmlrpc.sudorule_del`. """ - assert api.Command['sudorule_del'](self.rule_name)['result'] is True + api.Command['sudorule_del'](self.rule_name) # verify that it's gone try: api.Command['sudorule_show'](self.rule_name) diff --git a/tests/test_xmlrpc/test_user_plugin.py b/tests/test_xmlrpc/test_user_plugin.py index 4754e763..73d170af 100644 --- a/tests/test_xmlrpc/test_user_plugin.py +++ b/tests/test_xmlrpc/test_user_plugin.py @@ -370,7 +370,7 @@ class test_user(Declarative): desc='Delete %r' % user1, command=('user_del', [user1], {}), expected=dict( - result=True, + result=dict(failed=u''), summary=u'Deleted user "tuser1"', value=user1, ), @@ -411,6 +411,7 @@ class test_user(Declarative): ), ), + dict( desc='Create %r' % user2, command=( @@ -438,11 +439,12 @@ class test_user(Declarative): ), ), + dict( desc='Delete %r and %r at the same time' % (user1, user2), command=('user_del', [user1, user2], {}), expected=dict( - result=True, + result=dict(failed=u''), summary=u'Deleted user "tuser1,tuser2"', value=u','.join((user1, user2)), ), -- cgit