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.

-- 
Regards,

Ana Krivokapic
Associate Software Engineer
FreeIPA team
Red Hat Inc.

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

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 226b3f0193fe426f1dc92afdb75678790a13fd02 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 | 610 ++++++++++++++++++++++++-
 1 file changed, 597 insertions(+), 13 deletions(-)

diff --git a/ipatests/test_xmlrpc/test_automember_plugin.py b/ipatests/test_xmlrpc/test_automember_plugin.py
index 2c38b6463bfc684dbe23904f54b7107bb4ce3ff2..95e5bf757a58b5324c51fdb86179e171433ca3f9 100644
--- a/ipatests/test_xmlrpc/test_automember_plugin.py
+++ b/ipatests/test_xmlrpc/test_automember_plugin.py
@@ -27,8 +27,8 @@
 from xmlrpc_test import Declarative, fuzzy_digits, fuzzy_uuid, add_sid, add_oc
 
 
-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
@@ -40,13 +40,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]'
@@ -80,13 +84,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(
@@ -101,14 +105,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(
@@ -117,7 +121,587 @@ 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=add_sid(dict(
+                    gecos=[u'Michael Scott'],
+                    givenname=[u'Michael'],
+                    homedirectory=[u'/home/mscott'],
+                    krbprincipalname=[u'mscott@' + api.env.realm],
+                    has_keytab=False,
+                    has_password=False,
+                    loginshell=[u'/bin/sh'],
+                    objectclass=add_oc(objectclasses.user, u'ipantuserattrs'),
+                    sn=[u'Scott'],
+                    uid=[manager1],
+                    uidnumber=[fuzzy_digits],
+                    gidnumber=[fuzzy_digits],
+                    mail=[u'%s@%s' % (manager1, api.env.domain)],
+                    displayname=[u'Michael Scott'],
+                    cn=[u'Michael Scott'],
+                    initials=[u'MS'],
+                    ipauniqueid=[fuzzy_uuid],
+                    krbpwdpolicyreference=[
+                        DN(('cn', 'global_policy'), ('cn', api.env.realm),
+                           ('cn', 'kerberos'), api.env.basedn)
+                    ],
+                    mepmanagedentry=[
+                        DN(('cn', manager1), ('cn', 'groups'),
+                           ('cn', 'accounts'), api.env.basedn)
+                    ],
+                    memberof_group=[u'ipausers'],
+                    dn=DN(('uid', 'mscott'), ('cn', 'users'),
+                          ('cn', 'accounts'), api.env.basedn),
+                )),
+            ),
+        ),
+
+        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=add_sid(dict(
+                    gecos=[u'Test User1'],
+                    givenname=[u'Test'],
+                    homedirectory=[u'/home/tuser1'],
+                    krbprincipalname=[u'tuser1@' + api.env.realm],
+                    has_keytab=False,
+                    has_password=False,
+                    loginshell=[u'/bin/sh'],
+                    objectclass=add_oc(objectclasses.user, u'ipantuserattrs'),
+                    sn=[u'User1'],
+                    uid=[user1],
+                    uidnumber=[fuzzy_digits],
+                    gidnumber=[fuzzy_digits],
+                    mail=[u'%s@%s' % (user1, api.env.domain)],
+                    manager=[
+                        DN(('uid', 'mscott'), ('cn', 'users'),
+                           ('cn', 'accounts'), api.env.basedn)
+                    ],
+                    displayname=[u'Test User1'],
+                    cn=[u'Test User1'],
+                    initials=[u'TU'],
+                    ipauniqueid=[fuzzy_uuid],
+                    krbpwdpolicyreference=[
+                        DN(('cn', 'global_policy'), ('cn', api.env.realm),
+                           ('cn', 'kerberos'), api.env.basedn)],
+                    mepmanagedentry=[
+                        DN(('cn', user1), ('cn', 'groups'),
+                           ('cn', 'accounts'), api.env.basedn)
+                    ],
+                    memberof_group=[u'ipausers'],
+                    dn=DN(('uid', 'tuser1'), ('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

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to