On 10/15/2013 06:09 PM, Ana Krivokapic wrote: > On 09/30/2013 10:02 AM, Petr Viktorin wrote: >> On 09/27/2013 03:12 PM, Martin Kosek wrote: >>> On 09/27/2013 03:00 PM, Jan Cholasta wrote: >>>> On 23.9.2013 19:41, Ana Krivokapic wrote: >>>>> On 09/19/2013 03:29 PM, Ana Krivokapic wrote: >>> ... >>>> Patch 69: >>>> >>>> I think the changes in the update file should be also done in the >>>> right LDIF >>>> files in install/share, though I don't know what is the recent >>>> consensus on this. >>>> >>>> >>>> Honza >>>> >>> Last time I checked, we used to do the change both in LDIF and update >>> file. Just to avoid the LDIF become obsolete. >>> >>> Martin >> Rob recently said his preference is to move everything from LDIF to updates, >> and out of the the LDIF files: >> http://www.redhat.com/archives/freeipa-devel/2013-September/msg00106.html >> >> I would agree, having two places with the same information is redundant and >> error-prone. >> > Thanks Honza for the review. > > I incorporated your suggestions in this updated patchset. I attached all the > patches for more convenient reviewing, but only patches 68 and 70 have > changed. > > I haven't done any changes in the LDIF files since the consensus seems to be > not > to do that. > > > > _______________________________________________ > Freeipa-devel mailing list > Freeipa-devel@redhat.com > https://www.redhat.com/mailman/listinfo/freeipa-devel
Patch 70 needed a rebase, attaching the whole patchset again. -- Regards, Ana Krivokapic Associate Software Engineer FreeIPA team Red Hat Inc.
From 222d7e997f6f334210df79d9e3873bcde618c595 Mon Sep 17 00:00:00 2001 From: Ana Krivokapic <akriv...@redhat.com> Date: Thu, 19 Sep 2013 14:12:44 +0200 Subject: [PATCH] Add unit tests for automember rebuild command Design: http://www.freeipa.org/page/V3/Automember_rebuild_membership https://fedorahosted.org/freeipa/ticket/3752 --- ipatests/test_xmlrpc/test_automember_plugin.py | 553 ++++++++++++++++++++++++- 1 file changed, 540 insertions(+), 13 deletions(-) diff --git a/ipatests/test_xmlrpc/test_automember_plugin.py b/ipatests/test_xmlrpc/test_automember_plugin.py index 7b390a5000302d5bdbd483f9bc76ef6a08233a1f..fe66f101184643a97713f6eeb0a96b49b5f2917e 100644 --- a/ipatests/test_xmlrpc/test_automember_plugin.py +++ b/ipatests/test_xmlrpc/test_automember_plugin.py @@ -28,8 +28,8 @@ from ipatests.test_xmlrpc.test_user_plugin import get_user_result -user1=u'tuser1' -manager1=u'mscott' +user1 = u'tuser1' +manager1 = u'mscott' fqdn1 = u'web1.%s' % api.env.domain short1 = u'web1' fqdn2 = u'dev1.%s' % api.env.domain @@ -41,13 +41,17 @@ fqdn5 = u'webserver5.%s' % api.env.domain short5 = u'webserver5' -group1=u'group1' -defaultgroup1=u'defaultgroup1' -hostgroup1=u'hostgroup1' -hostgroup2=u'hostgroup2' -hostgroup3=u'hostgroup3' -hostgroup4=u'hostgroup4' -defaulthostgroup1=u'defaulthostgroup1' +group1 = u'group1' +group1_dn = DN(('cn', group1), ('cn', 'groups'), + ('cn', 'accounts'), api.env.basedn) +defaultgroup1 = u'defaultgroup1' +hostgroup1 = u'hostgroup1' +hostgroup1_dn = DN(('cn', hostgroup1), ('cn', 'hostgroups'), + ('cn', 'accounts'), api.env.basedn) +hostgroup2 = u'hostgroup2' +hostgroup3 = u'hostgroup3' +hostgroup4 = u'hostgroup4' +defaulthostgroup1 = u'defaulthostgroup1' group_include_regex = u'mscott' hostgroup_include_regex = u'^web[1-9]' @@ -81,13 +85,13 @@ class test_automember(Declarative): desc='Try to retrieve non-existent group rule %r' % group1, command=('automember_add', [group1], dict(description=u'Test desc', type=u'group')), - expected=errors.NotFound(reason=u'Group: %s not found!' % group1), + expected=errors.NotFound(reason=u'group "%s" not found' % group1), ), dict( desc='Try to update non-existent group rule %r' % group1, command=('automember_add', [group1], dict(type=u'group')), - expected=errors.NotFound(reason=u'Group: %s not found!' % group1), + expected=errors.NotFound(reason=u'group "%s" not found' % group1), ), dict( @@ -102,14 +106,14 @@ class test_automember(Declarative): command=('automember_add', [hostgroup1], dict(description=u'Test desc', type=u'hostgroup')), expected=errors.NotFound( - reason=u'Group: %s not found!' % hostgroup1), + reason=u'hostgroup "%s" not found' % hostgroup1), ), dict( desc='Try to update non-existent hostgroup rule %r' % hostgroup1, command=('automember_add', [hostgroup1], dict(type=u'hostgroup')), expected=errors.NotFound( - reason=u'Group: %s not found!' % hostgroup1), + reason=u'hostgroup "%s" not found' % hostgroup1), ), dict( @@ -118,7 +122,530 @@ class test_automember(Declarative): expected=errors.NotFound(reason=u': auto_member_rule not found'), ), + # Automember rebuild membership tests + dict( + desc='Create hostgroup: %r' % hostgroup1, + command=( + 'hostgroup_add', [hostgroup1], dict(description=u'Test desc') + ), + expected=dict( + value=hostgroup1, + summary=u'Added hostgroup "%s"' % hostgroup1, + result=dict( + cn=[hostgroup1], + description=[u'Test desc'], + objectclass=objectclasses.hostgroup, + ipauniqueid=[fuzzy_uuid], + mepmanagedentry=[DN(('cn', hostgroup1), ('cn', 'ng'), + ('cn', 'alt'), api.env.basedn)], + dn=hostgroup1_dn + ), + ), + ), + dict( + desc='Create host: %r' % fqdn1, + command=( + 'host_add', + [fqdn1], + dict( + description=u'Test host 1', + l=u'Undisclosed location 1', + force=True, + ), + ), + expected=dict( + value=fqdn1, + summary=u'Added host "%s"' % fqdn1, + result=dict( + dn=DN(('fqdn', fqdn1), ('cn', 'computers'), + ('cn', 'accounts'), api.env.basedn), + fqdn=[fqdn1], + description=[u'Test host 1'], + l=[u'Undisclosed location 1'], + krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)], + has_keytab=False, + has_password=False, + objectclass=objectclasses.host, + ipauniqueid=[fuzzy_uuid], + managedby_host=[fqdn1], + ), + ), + ), + + dict( + desc='Create automember rule: %r' % hostgroup1, + command=( + 'automember_add', [hostgroup1], dict( + description=u'Test desc', type=u'hostgroup', + ) + ), + expected=dict( + value=hostgroup1, + summary=u'Added automember rule "%s"' % hostgroup1, + result=dict( + cn=[hostgroup1], + description=[u'Test desc'], + automembertargetgroup=[hostgroup1_dn], + objectclass=objectclasses.automember, + dn=DN(('cn', hostgroup1), ('cn', 'hostgroup'), + ('cn', 'automember'), ('cn', 'etc'), api.env.basedn), + ), + ), + ), + + dict( + desc='Create automember condition: %r' % hostgroup1, + command=( + 'automember_add_condition', [hostgroup1], dict( + key=u'fqdn', type=u'hostgroup', + automemberinclusiveregex=[hostgroup_include_regex], + ) + ), + expected=dict( + value=hostgroup1, + summary=u'Added condition(s) to "%s"' % hostgroup1, + completed=1, + failed=dict( + failed=dict( + automemberinclusiveregex=tuple(), + automemberexclusiveregex=tuple(), + ) + ), + result=dict( + cn=[hostgroup1], + description=[u'Test desc'], + automemberinclusiveregex=[ + u'fqdn=%s' % hostgroup_include_regex + ], + automembertargetgroup=[hostgroup1_dn], + ), + ), + ), + + dict( + desc='Retrieve hostgroup: %r' % hostgroup1, + command=('hostgroup_show', [hostgroup1], dict()), + expected=dict( + value=hostgroup1, + summary=None, + result=dict( + dn=hostgroup1_dn, + cn=[hostgroup1], + description=[u'Test desc'], + ), + ), + ), + + dict( + desc='Rebuild membership for hostgroups', + command=('automember_rebuild', [], dict(type=u'hostgroup')), + expected=dict( + value=u'', + summary=u'Automember rebuild membership task completed', + result=True + ), + ), + + dict( + desc='Retrieve hostgroup: %r' % hostgroup1, + command=('hostgroup_show', [hostgroup1], dict()), + expected=dict( + value=hostgroup1, + summary=None, + result=dict( + dn=hostgroup1_dn, + member_host=[u'%s' % fqdn1], + cn=[hostgroup1], + description=[u'Test desc'], + ), + ), + ), + + dict( + desc='Remove host %r from hostgroup %r' % (fqdn1, hostgroup1), + command=( + 'hostgroup_remove_member', + [hostgroup1], + dict(host=fqdn1) + ), + expected=dict( + failed=dict( + member=dict( + host=tuple(), + hostgroup=tuple(), + ), + ), + completed=1, + result=dict( + dn=hostgroup1_dn, + cn=[hostgroup1], + description=[u'Test desc'], + ), + ), + ), + + dict( + desc='Retrieve hostgroup: %r' % hostgroup1, + command=('hostgroup_show', [hostgroup1], dict()), + expected=dict( + value=hostgroup1, + summary=None, + result=dict( + dn=hostgroup1_dn, + cn=[hostgroup1], + description=[u'Test desc'], + ), + ), + ), + + dict( + desc='Try to rebuild membership (no options)', + command=('automember_rebuild', [], dict()), + expected=errors.MutuallyExclusiveError( + reason=(u'at least one of options: type, users, hosts must be ' + 'specified') + ) + ), + + dict( + desc='Try to rebuild membership (--users and --hosts together)', + command=( + 'automember_rebuild', + [], + dict(users=user1, hosts=fqdn1) + ), + expected=errors.MutuallyExclusiveError( + reason=u'users and hosts cannot both be set' + ) + ), + + dict( + desc='Try to rebuild membership (--users and --type=hostgroup)', + command=( + 'automember_rebuild', + [], + dict(users=user1, type=u'hostgroup') + ), + expected=errors.MutuallyExclusiveError( + reason="users cannot be set when type is 'hostgroup'" + ) + ), + + dict( + desc='Try to rebuild membership (--hosts and --type=group)', + command=( + 'automember_rebuild', + [], + dict(hosts=fqdn1, type=u'group') + ), + expected=errors.MutuallyExclusiveError( + reason=u"hosts cannot be set when type is 'group'" + ) + ), + + dict( + desc='Rebuild membership for host: %s' % fqdn1, + command=('automember_rebuild', [], dict(hosts=fqdn1)), + expected=dict( + value=u'', + summary=u'Automember rebuild membership task completed', + result=True + ), + ), + + dict( + desc='Retrieve hostgroup: %r' % hostgroup1, + command=('hostgroup_show', [hostgroup1], dict()), + expected=dict( + value=hostgroup1, + summary=None, + result=dict( + dn=hostgroup1_dn, + member_host=[u'%s' % fqdn1], + cn=[hostgroup1], + description=[u'Test desc'], + ), + ), + ), + + dict( + desc='Delete host: %r' % fqdn1, + command=('host_del', [fqdn1], dict()), + expected=dict( + value=fqdn1, + summary=u'Deleted host "%s"' % fqdn1, + result=dict(failed=u''), + ), + ), + + dict( + desc='Delete hostgroup: %r' % hostgroup1, + command=('hostgroup_del', [hostgroup1], dict()), + expected=dict( + value=hostgroup1, + summary=u'Deleted hostgroup "%s"' % hostgroup1, + result=dict(failed=u''), + ), + ), + + dict( + desc='Delete automember rule: %r' % hostgroup1, + command=('automember_del', [hostgroup1], dict(type=u'hostgroup')), + expected=dict( + value=hostgroup1, + summary=u'Deleted automember rule "%s"' % hostgroup1, + result=dict(failed=u''), + ), + ), + + dict( + desc='Create group: %r' % group1, + command=( + 'group_add', [group1], dict(description=u'Test desc') + ), + expected=dict( + value=group1, + summary=u'Added group "%s"' % group1, + result=dict( + cn=[group1], + description=[u'Test desc'], + objectclass=objectclasses.group + [u'posixgroup'], + ipauniqueid=[fuzzy_uuid], + gidnumber=[fuzzy_digits], + dn=group1_dn + ), + ), + ), + + dict( + desc='Create user: %r' % manager1, + command=( + 'user_add', [manager1], dict(givenname=u'Michael', sn=u'Scott') + ), + expected=dict( + value=manager1, + summary=u'Added user "mscott"', + result=get_user_result(manager1, u'Michael', u'Scott', 'add'), + ), + ), + + dict( + desc='Create user: %r' % user1, + command=( + 'user_add', + [user1], + dict(givenname=u'Test', sn=u'User1', manager=manager1) + ), + expected=dict( + value=user1, + summary=u'Added user "tuser1"', + result=get_user_result( + user1, u'Test', u'User1', 'add', + manager=[DN(('uid', 'mscott'), ('cn', 'users'), + ('cn', 'accounts'), api.env.basedn)] + ) + ), + ), + + + dict( + desc='Create automember rule: %r' % group1, + command=( + 'automember_add', [group1], dict( + description=u'Test desc', type=u'group', + ) + ), + expected=dict( + value=group1, + summary=u'Added automember rule "%s"' % group1, + result=dict( + cn=[group1], + description=[u'Test desc'], + automembertargetgroup=[group1_dn], + objectclass=objectclasses.automember, + dn=DN(('cn', group1), ('cn', 'group'), + ('cn', 'automember'), ('cn', 'etc'), api.env.basedn), + ), + ), + ), + + dict( + desc='Create automember condition: %r' % group1, + command=( + 'automember_add_condition', [group1], dict( + key=u'manager', type=u'group', + automemberinclusiveregex=[group_include_regex], + ) + ), + expected=dict( + value=group1, + summary=u'Added condition(s) to "%s"' % group1, + completed=1, + failed=dict( + failed=dict( + automemberinclusiveregex=tuple(), + automemberexclusiveregex=tuple(), + ) + ), + result=dict( + cn=[group1], + description=[u'Test desc'], + automemberinclusiveregex=[ + u'manager=%s' % group_include_regex + ], + automembertargetgroup=[group1_dn], + ), + ), + ), + + dict( + desc='Retrieve group: %r' % group1, + command=('group_show', [group1], dict()), + expected=dict( + value=group1, + summary=None, + result=dict( + dn=group1_dn, + cn=[group1], + description=[u'Test desc'], + gidnumber=[fuzzy_digits], + ), + ), + ), + + dict( + desc='Rebuild membership for groups', + command=('automember_rebuild', [], dict(type=u'group')), + expected=dict( + value=u'', + summary=u'Automember rebuild membership task completed', + result=True + ), + ), + + dict( + desc='Retrieve group: %r' % group1, + command=('group_show', [group1], dict()), + expected=dict( + value=group1, + summary=None, + result=dict( + dn=group1_dn, + member_user=[u'%s' % user1], + cn=[group1], + description=[u'Test desc'], + gidnumber=[fuzzy_digits], + ), + ), + ), + + dict( + desc='Remove user %r from group %r' % (fqdn1, hostgroup1), + command=( + 'group_remove_member', + [group1], + dict(user=user1) + ), + expected=dict( + failed=dict( + member=dict( + user=tuple(), + group=tuple(), + ), + ), + completed=1, + result=dict( + dn=group1_dn, + cn=[group1], + description=[u'Test desc'], + gidnumber=[fuzzy_digits], + ), + ), + ), + + dict( + desc='Retrieve group: %r' % group1, + command=('group_show', [group1], dict()), + expected=dict( + value=group1, + summary=None, + result=dict( + dn=group1_dn, + cn=[group1], + description=[u'Test desc'], + gidnumber=[fuzzy_digits], + ), + ), + ), + + dict( + desc='Rebuild membership for user: %s' % user1, + command=('automember_rebuild', [], dict(users=user1)), + expected=dict( + value=u'', + summary=u'Automember rebuild membership task completed', + result=True + ), + ), + + dict( + desc='Retrieve group: %r' % group1, + command=('group_show', [group1], dict()), + expected=dict( + value=group1, + summary=None, + result=dict( + dn=group1_dn, + member_user=[u'%s' % user1], + cn=[group1], + description=[u'Test desc'], + gidnumber=[fuzzy_digits], + ), + ), + ), + + dict( + desc='Delete user: %r' % user1, + command=('user_del', [user1], dict()), + expected=dict( + value=user1, + summary=u'Deleted user "%s"' % user1, + result=dict(failed=u''), + ), + ), + + dict( + desc='Delete user: %r' % manager1, + command=('user_del', [manager1], dict()), + expected=dict( + value=manager1, + summary=u'Deleted user "%s"' % manager1, + result=dict(failed=u''), + ), + ), + + dict( + desc='Delete group: %r' % group1, + command=('group_del', [group1], dict()), + expected=dict( + value=group1, + summary=u'Deleted group "%s"' % group1, + result=dict(failed=u''), + ), + ), + + dict( + desc='Delete automember rule: %r' % group1, + command=('automember_del', [group1], dict(type=u'group')), + expected=dict( + value=group1, + summary=u'Deleted automember rule "%s"' % group1, + result=dict(failed=u''), + ), + ), + + # End of automember rebuild membership tests dict( desc='Create %r' % group1, -- 1.8.3.1
From af969cd1541f066502c5202e8ad757b5a5dc84e8 Mon Sep 17 00:00:00 2001 From: Ana Krivokapic <akriv...@redhat.com> Date: Mon, 23 Sep 2013 13:56:14 +0200 Subject: [PATCH] Fix error message when adding duplicate automember rule Also fix object_name and object_name_plural for automember rules. https://fedorahosted.org/freeipa/ticket/2708 --- install/ui/test/data/ipa_init_objects.json | 4 ++-- ipalib/plugins/automember.py | 4 ++-- ipalib/plugins/baseldap.py | 5 +++-- ipatests/test_xmlrpc/test_automember_plugin.py | 4 ++-- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/install/ui/test/data/ipa_init_objects.json b/install/ui/test/data/ipa_init_objects.json index bef3cc65d45a8473f7fed3b67124bbc892213ca5..c6a252b973775dd5210c67c105949616e586bd91 100644 --- a/install/ui/test/data/ipa_init_objects.json +++ b/install/ui/test/data/ipa_init_objects.json @@ -52,8 +52,8 @@ "automemberregexrule" ], "object_class_config": null, - "object_name": "auto_member_rule", - "object_name_plural": "auto_member_rules", + "object_name": "Automember rule", + "object_name_plural": "Automember rules", "parent_object": "", "rdn_attribute": "", "relationships": { diff --git a/ipalib/plugins/automember.py b/ipalib/plugins/automember.py index 9473dd4d11a88e96e4d02e0de6fddb9ffb7a42bd..4ae32f8688be179b266664f95e6b0951cfcf385e 100644 --- a/ipalib/plugins/automember.py +++ b/ipalib/plugins/automember.py @@ -159,8 +159,8 @@ class automember(LDAPObject): container_dn = api.env.container_automember - object_name = 'auto_member_rule' - object_name_plural = 'auto_member_rules' + object_name = 'Automember rule' + object_name_plural = 'Automember rules' object_class = ['top', 'automemberregexrule'] default_attributes = [ 'automemberinclusiveregex', 'automemberexclusiveregex', diff --git a/ipalib/plugins/baseldap.py b/ipalib/plugins/baseldap.py index 4a79502708c358dd20ede017037b16f691b76766..f0d667dd444c548f704a914c3c5f41dc36895068 100644 --- a/ipalib/plugins/baseldap.py +++ b/ipalib/plugins/baseldap.py @@ -582,9 +582,10 @@ def handle_not_found(self, *keys): ) def handle_duplicate_entry(self, *keys): - pkey = '' - if self.primary_key: + try: pkey = keys[-1] + except KeyError: + pkey = '' raise errors.DuplicateEntry( message=self.already_exists_msg % { 'pkey': pkey, 'oname': self.object_name, diff --git a/ipatests/test_xmlrpc/test_automember_plugin.py b/ipatests/test_xmlrpc/test_automember_plugin.py index cb4d7e3f837af83786d52fe0c5ddf3f100e27083..9442420f48b39be76c14e31a7d20fe5c537b2734 100644 --- a/ipatests/test_xmlrpc/test_automember_plugin.py +++ b/ipatests/test_xmlrpc/test_automember_plugin.py @@ -96,7 +96,7 @@ class test_automember(Declarative): dict( desc='Try to delete non-existent group rule %r' % group1, command=('automember_del', [group1], dict(type=u'group')), - expected=errors.NotFound(reason=u': auto_member_rule not found'), + expected=errors.NotFound(reason=u': Automember rule not found'), ), @@ -118,7 +118,7 @@ class test_automember(Declarative): dict( desc='Try to delete non-existent hostgroup rule %r' % hostgroup1, command=('automember_del', [hostgroup1], dict(type=u'hostgroup')), - expected=errors.NotFound(reason=u': auto_member_rule not found'), + expected=errors.NotFound(reason=u': Automember rule not found'), ), # Automember rebuild membership tests -- 1.8.3.1
From 8893bc9ab1c5fe62b05956b4fad3bcb02e41d6cb Mon Sep 17 00:00:00 2001 From: Ana Krivokapic <akriv...@redhat.com> Date: Thu, 19 Sep 2013 14:10:32 +0200 Subject: [PATCH] Add permissions for automember rebuild command Design: http://www.freeipa.org/page/V3/Automember_rebuild_membership https://fedorahosted.org/freeipa/ticket/3752 --- install/updates/40-delegation.update | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/install/updates/40-delegation.update b/install/updates/40-delegation.update index 64a6432acc8605f3164d267d16609f51ce02a7ef..3a0e7f70e4bfda21bf1011c92562d565fb4d32cb 100644 --- a/install/updates/40-delegation.update +++ b/install/updates/40-delegation.update @@ -373,3 +373,29 @@ dn: cn=Retrieve Certificates from the CA,cn=permissions,cn=pbac,$SUFFIX dn: cn=Revoke Certificate,cn=permissions,cn=pbac,$SUFFIX add: member: 'cn=Host Administrators,cn=privileges,cn=pbac,$SUFFIX' + +# Automember tasks +dn: cn=Automember Task Administrator,cn=privileges,cn=pbac,$SUFFIX +default:objectClass: nestedgroup +default:objectClass: groupofnames +default:objectClass: top +default:cn: Automember Task Administrator +default:description: Automember Task Administrator + +dn: cn=Add Automember Rebuild Membership Task,cn=permissions,cn=pbac,$SUFFIX +default:objectClass: groupofnames +default:objectClass: ipapermission +default:objectClass: top +default:cn: Add Automember Rebuild Membership Task +default:member: cn=Automember Task Administrator,cn=privileges,cn=pbac,$SUFFIX + +dn: cn=Add Automember Export Updates Task,cn=permissions,cn=pbac,$SUFFIX +default:objectClass: groupofnames +default:objectClass: ipapermission +default:objectClass: top +default:cn: Add Automember Export Updates Task +default:member: cn=Automember Task Administrator,cn=privileges,cn=pbac,$SUFFIX + +dn: cn=config +add:aci: '(target = "ldap:///cn=automember rebuild membership,cn=tasks,cn=config")(targetattr=*)(version 3.0;acl "permission:Add Automember Rebuild Membership Task";allow (add) groupdn = "ldap:///cn=Add Automember Rebuild Membership Task,cn=permissions,cn=pbac,$SUFFIX";)' +add:aci: '(target = "ldap:///cn=automember export updates,cn=tasks,cn=config")(targetattr=*)(version 3.0;acl "permission:Add Automember Export Updates Task";allow (add) groupdn = "ldap:///cn=Add Automember Export Updates Task,cn=permissions,cn=pbac,$SUFFIX";)' -- 1.8.3.1
From 12426d8945396468bf7ecb85ccd6a6ddab4630d2 Mon Sep 17 00:00:00 2001 From: Ana Krivokapic <akriv...@redhat.com> Date: Thu, 19 Sep 2013 14:01:58 +0200 Subject: [PATCH] Add automember rebuild command Add a new command to IPA CLI: ipa automember-rebuild The command integrates the automember rebuild membership task functionality into IPA CLI. It makes it possible to rebuild automember membership for groups/hostgroups. Design: http://www.freeipa.org/page/V3/Automember_rebuild_membership https://fedorahosted.org/freeipa/ticket/3752 --- API.txt | 9 ++++ VERSION | 2 +- ipalib/plugins/automember.py | 118 +++++++++++++++++++++++++++++++++++++++---- 3 files changed, 118 insertions(+), 11 deletions(-) diff --git a/API.txt b/API.txt index 40871f6a8b105a7b161df34ce4f6feaf785a6107..05c5a988b7738e20e6351f6b3a01026f61cb6063 100644 --- a/API.txt +++ b/API.txt @@ -199,6 +199,15 @@ command: automember_mod output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None) output: Output('value', <type 'unicode'>, None) +command: automember_rebuild +args: 0,4,3 +option: Str('hosts*') +option: StrEnum('type', cli_name='type', multivalue=False, required=False, values=(u'group', u'hostgroup')) +option: Str('users*') +option: Str('version?', exclude='webui') +output: Output('result', <type 'bool'>, None) +output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None) +output: Output('value', <type 'unicode'>, None) command: automember_remove_condition args: 1,8,5 arg: Str('cn', cli_name='automember_rule') diff --git a/VERSION b/VERSION index c3c6d5a4c28991839a1917f18d2804475a16bcb7..32f6efbc4d4768c77c514a3367cb9feb039205e5 100644 --- a/VERSION +++ b/VERSION @@ -89,4 +89,4 @@ IPA_DATA_VERSION=20100614120000 # # ######################################################## IPA_API_VERSION_MAJOR=2 -IPA_API_VERSION_MINOR=65 +IPA_API_VERSION_MINOR=66 diff --git a/ipalib/plugins/automember.py b/ipalib/plugins/automember.py index 4f563f11953dafac0d5bfd00f0309aca2f346f81..b30182d9ee6545d08b0f57fbf7733f11a17dcb6f 100644 --- a/ipalib/plugins/automember.py +++ b/ipalib/plugins/automember.py @@ -16,13 +16,11 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. - -from ipalib import api, errors -from ipalib import Str, StrEnum +import uuid +import ldap as _ldap +from ipalib import api, errors, Str, StrEnum, _, ngettext from ipalib.plugins.baseldap import * -from ipalib import _, ngettext from ipalib.request import context -import ldap as _ldap from ipapython.dn import DN __doc__ = _(""" @@ -184,14 +182,17 @@ class automember(LDAPObject): ), ) - def dn_exists(self, grouptype, groupname, *keys): + def dn_exists(self, otype, oname): ldap = self.api.Backend.ldap2 - dn = self.api.Object[grouptype].get_dn(groupname) + dn = self.api.Object[otype].get_dn(oname) try: - (gdn, entry_attrs) = ldap.get_entry(dn, []) + entry = ldap.get_entry(dn, []) except errors.NotFound: - raise errors.NotFound(reason=_(u'Group: %s not found!') % groupname) - return gdn + raise errors.NotFound( + reason=_(u'%(otype)s "%(oname)s" not found') % + dict(otype=otype, oname=oname) + ) + return entry.dn def get_dn(self, *keys, **options): if self.parent_object: @@ -587,3 +588,100 @@ def execute(self, *keys, **options): return result api.register(automember_default_group_show) + + +class automember_rebuild(Command): + __doc__ = _('Rebuild auto membership for specified entries.') + # TODO: Add a --dry-run option: + # https://fedorahosted.org/freeipa/ticket/3936 + takes_options = ( + group_type[0].clone(required=False), + Str( + 'users*', + label=_('Users'), + doc=_('Users for which the rebuild task will be run'), + ), + Str( + 'hosts*', + label=_('Hosts'), + doc=_('Hosts for which the rebuild task will be run'), + ), + ) + has_output = output.standard_value + msg_summary = _('Automember rebuild membership task completed') + + def validate(self, **kw): + """ + Validation rules: + - at least one of 'type', 'users', 'hosts' is required + - 'users' and 'hosts' cannot be combined together + - if 'users' and 'type' are specified, 'type' must be 'group' + - if 'hosts' and 'type' are specified, 'type' must be 'hostgroup' + """ + super(automember_rebuild, self).validate(**kw) + users, hosts, gtype = kw.get('users'), kw.get('hosts'), kw.get('type') + + if not (gtype or users or hosts): + raise errors.MutuallyExclusiveError( + reason=_('at least one of options: type, users, hosts must be ' + 'specified') + ) + + if users and hosts: + raise errors.MutuallyExclusiveError( + reason=_("users and hosts cannot both be set") + ) + if gtype == 'group' and hosts: + raise errors.MutuallyExclusiveError( + reason=_("hosts cannot be set when type is 'group'") + ) + if gtype == 'hostgroup' and users: + raise errors.MutuallyExclusiveError( + reason=_("users cannot be set when type is 'hostgroup'") + ) + + def execute(self, *keys, **options): + ldap = self.api.Backend.ldap2 + cn = str(uuid.uuid4()) + + gtype = options.get('type') + if not gtype: + gtype = 'group' if options.get('users') else 'hostgroup' + + types = { + 'group': ('user', 'users'), + 'hostgroup': ('host', 'hosts'), + } + + obj_name, opt_name = types[gtype] + obj = self.api.Object[obj_name] + + names = options.get(opt_name) + if names: + for name in names: + obj.get_dn_if_exists(name) + search_filter = ldap.make_filter_from_attr( + obj.primary_key.name, + names, + rules=ldap.MATCH_ANY + ) + else: + search_filter = '(%s=*)' % obj.primary_key.name + + entry = ldap.make_entry( + DN( + ('cn', cn), + ('cn', 'automember rebuild membership'), + ('cn', 'tasks'), + ('cn', 'config'), + ), + objectclass=['top', 'extensibleObject'], + cn=[cn], + basedn=[api.env.basedn], + filter=[search_filter], + scope=['sub'] + ) + ldap.add_entry(entry) + return dict(result=True, value=u'') + +api.register(automember_rebuild) -- 1.8.3.1
_______________________________________________ Freeipa-devel mailing list Freeipa-devel@redhat.com https://www.redhat.com/mailman/listinfo/freeipa-devel