Optionally wait for 389-ds postop plugins to complete

Add a new command that lets you wait for an attribute to appear in
a value. Using this you can do things like wait for a managed entry
to be created, adding a new objectclass to the parent entry.

This is controlled by a new booleon option, wait_for_attr, defaulting
to False.

https://fedorahosted.org/freeipa/ticket/1144
This commit is contained in:
Rob Crittenden 2011-07-01 15:32:31 -04:00 committed by Martin Kosek
parent c09f116f43
commit 1dd9e14073
13 changed files with 120 additions and 3 deletions

View File

@ -148,6 +148,7 @@ DEFAULT_CONFIG = (
# Enable certain optional plugins:
('enable_ra', False),
('ra_plugin', 'selfsign'),
('wait_for_attr', False),
# Used when verifying that the API hasn't changed. Not for production.
('validate_api', False),

View File

@ -194,6 +194,25 @@ def get_effective_rights(ldap, dn, attrs=None):
return rdict
def entry_from_entry(entry, newentry):
"""
Python is more or less pass-by-value except for immutable objects. So if
you pass in a dict to a function you are free to change members of that
dict but you can't create a new dict in the function and expect to replace
what was passed in.
In some post-op plugins that is exactly what we want to do, so here is a
clumsy way around the problem.
"""
# Wipe out the current data
for e in entry.keys():
del entry[e]
# Re-populate it with new wentry
for e in newentry:
entry[e] = newentry[e]
def wait_for_memberof(keys, entry_start, completed, show_command, adding=True):
"""
When adding or removing reverse members we are faking an update to
@ -238,6 +257,40 @@ def wait_for_memberof(keys, entry_start, completed, show_command, adding=True):
return entry_attrs
def wait_for_value(ldap, dn, attr, value):
"""
389-ds postoperation plugins are executed after the data has been
returned to a client. This means that plugins that add data in a
postop are not included in data returned to the user.
The downside of waiting is that this increases the time of the
command.
The updated entry is returned.
"""
# Loop a few times to give the postop-plugin a chance to complete
# Don't sleep for more than 6 seconds.
x = 0
while x < 20:
# sleep first because the first search, even on a quiet system,
# almost always fails.
time.sleep(.3)
x = x + 1
# FIXME: put a try/except around here? I think it is probably better
# to just let the exception filter up to the caller.
(dn, entry_attrs) = ldap.get_entry( dn, ['*'])
if attr in entry_attrs:
if isinstance(entry_attrs[attr], (list, tuple)):
values = map(lambda y:y.lower(), entry_attrs[attr])
if value.lower() in values:
break
else:
if value.lower() == entry_attrs[attr].lower():
break
return entry_attrs
class LDAPObject(Object):
"""
Object representing a LDAP entry.

View File

@ -98,6 +98,14 @@ class hostgroup_add(LDAPCreate):
msg_summary = _('Added hostgroup "%(value)s"')
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
if self.api.env.wait_for_attr:
newentry = wait_for_value(ldap, dn, 'objectclass', 'mepOriginEntry')
entry_from_entry(entry_attrs, newentry)
return dn
api.register(hostgroup_add)

View File

@ -402,6 +402,11 @@ class user_add(LDAPCreate):
self.api.Command['user_mod'](keys[-1], **kw)
except (errors.EmptyModlist, errors.NotFound):
pass
else:
if self.api.env.wait_for_attr:
newentry = wait_for_value(ldap, dn, 'objectclass', 'mepOriginEntry')
entry_from_entry(entry_attrs, newentry)
return dn
api.register(user_add)

View File

@ -21,7 +21,7 @@
Defines the expected objectclass for various entries.
"""
user = [
user_base = [
u'top',
u'person',
u'organizationalperson',
@ -33,6 +33,8 @@ user = [
u'ipaobject',
]
user = user_base + [u'mepOriginEntry']
group = [
u'top',
u'groupofnames',

View File

@ -61,6 +61,9 @@ class test_attr(Declarative):
cn=[u'Test User1'],
initials=[u'TU'],
ipauniqueid=[fuzzy_uuid],
krbpwdpolicyreference=[u'cn=global_policy,cn=%s,cn=kerberos,%s' % (api.env.realm, api.env.basedn)],
mepmanagedentry=[u'cn=%s,cn=groups,cn=accounts,%s' % (user1, api.env.basedn)],
memberof_group=[u'ipausers'],
dn=u'uid=tuser1,cn=users,cn=accounts,' + api.env.basedn,
),
),

View File

@ -590,6 +590,9 @@ class test_group(Declarative):
cn=[u'Test User1'],
initials=[u'TU'],
ipauniqueid=[fuzzy_uuid],
krbpwdpolicyreference=[u'cn=global_policy,cn=%s,cn=kerberos,%s' % (api.env.realm, api.env.basedn)],
mepmanagedentry=[u'cn=%s,cn=groups,cn=accounts,%s' % (user1, api.env.basedn)],
memberof_group=[u'ipausers'],
dn=u'uid=%s,cn=users,cn=accounts,%s' % (user1, api.env.basedn),
),
),
@ -691,7 +694,7 @@ class test_group(Declarative):
homedirectory=[u'/home/tuser1'],
krbprincipalname=[u'tuser1@' + api.env.realm],
loginshell=[u'/bin/sh'],
objectclass=objectclasses.user,
objectclass=objectclasses.user_base,
sn=[u'User1'],
uid=[user1],
uidnumber=[fuzzy_digits],

View File

@ -23,6 +23,7 @@ Test the `ipalib.plugins.hostgroup` module.
"""
from ipalib import api, errors
from ipalib.dn import DN
from tests.test_xmlrpc.xmlrpc_test import Declarative, fuzzy_uuid
from tests.test_xmlrpc import objectclasses
@ -79,6 +80,7 @@ class test_hostgroup(Declarative):
objectclass=objectclasses.hostgroup,
description=[u'Test hostgroup 1'],
ipauniqueid=[fuzzy_uuid],
mepmanagedentry=['cn=%s,cn=ng,cn=alt,%s' % (hostgroup1, api.env.basedn)],
),
),
),

View File

@ -106,6 +106,9 @@ class test_krbtpolicy(Declarative):
cn=[u'Test User1'],
initials=[u'TU'],
ipauniqueid=[fuzzy_uuid],
krbpwdpolicyreference=[u'cn=global_policy,cn=%s,cn=kerberos,%s' % (api.env.realm, api.env.basedn)],
mepmanagedentry=[u'cn=%s,cn=groups,cn=accounts,%s' % (user1, api.env.basedn)],
memberof_group=[u'ipausers'],
dn=u'uid=%s,cn=users,cn=accounts,%s' % (user1, api.env.basedn)
),
),

View File

@ -167,6 +167,9 @@ class test_nesting(Declarative):
cn=[u'Test User1'],
initials=[u'TU'],
ipauniqueid=[fuzzy_uuid],
krbpwdpolicyreference=[u'cn=global_policy,cn=%s,cn=kerberos,%s' % (api.env.realm, api.env.basedn)],
mepmanagedentry=[u'cn=%s,cn=groups,cn=accounts,%s' % (user1, api.env.basedn)],
memberof_group=[u'ipausers'],
dn=u'uid=%s,cn=users,cn=accounts,%s' % (user1, api.env.basedn)
),
),
@ -196,6 +199,9 @@ class test_nesting(Declarative):
cn=[u'Test User2'],
initials=[u'TU'],
ipauniqueid=[fuzzy_uuid],
krbpwdpolicyreference=[u'cn=global_policy,cn=%s,cn=kerberos,%s' % (api.env.realm, api.env.basedn)],
mepmanagedentry=[u'cn=%s,cn=groups,cn=accounts,%s' % (user2, api.env.basedn)],
memberof_group=[u'ipausers'],
dn=u'uid=%s,cn=users,cn=accounts,%s' % (user2, api.env.basedn)
),
),
@ -225,6 +231,9 @@ class test_nesting(Declarative):
cn=[u'Test User3'],
initials=[u'TU'],
ipauniqueid=[fuzzy_uuid],
krbpwdpolicyreference=[u'cn=global_policy,cn=%s,cn=kerberos,%s' % (api.env.realm, api.env.basedn)],
mepmanagedentry=[u'cn=%s,cn=groups,cn=accounts,%s' % (user3, api.env.basedn)],
memberof_group=[u'ipausers'],
dn=u'uid=%s,cn=users,cn=accounts,%s' % (user3, api.env.basedn)
),
),
@ -254,6 +263,9 @@ class test_nesting(Declarative):
cn=[u'Test User4'],
initials=[u'TU'],
ipauniqueid=[fuzzy_uuid],
krbpwdpolicyreference=[u'cn=global_policy,cn=%s,cn=kerberos,%s' % (api.env.realm, api.env.basedn)],
mepmanagedentry=[u'cn=%s,cn=groups,cn=accounts,%s' % (user4, api.env.basedn)],
memberof_group=[u'ipausers'],
dn=u'uid=%s,cn=users,cn=accounts,%s' % (user4, api.env.basedn)
),
),
@ -623,6 +635,7 @@ class test_nesting(Declarative):
objectclass=objectclasses.hostgroup,
description=[u'Test hostgroup 1'],
ipauniqueid=[fuzzy_uuid],
mepmanagedentry=[u'cn=%s,cn=ng,cn=alt,%s' % (hostgroup1, api.env.basedn)],
),
),
),
@ -642,6 +655,7 @@ class test_nesting(Declarative):
objectclass=objectclasses.hostgroup,
description=[u'Test hostgroup 2'],
ipauniqueid=[fuzzy_uuid],
mepmanagedentry=[u'cn=%s,cn=ng,cn=alt,%s' % (hostgroup2, api.env.basedn)],
),
),
),

View File

@ -183,6 +183,8 @@ class test_netgroup(Declarative):
cn=[hostgroup1],
objectclass=objectclasses.hostgroup,
description=[u'Test hostgroup 1'],
mepmanagedentry=['cn=%s,cn=ng,cn=alt,%s' % (hostgroup1, api
.env.basedn)],
ipauniqueid=[fuzzy_uuid],
),
),
@ -212,6 +214,9 @@ class test_netgroup(Declarative):
cn=[u'Test User1'],
initials=[u'TU'],
ipauniqueid=[fuzzy_uuid],
krbpwdpolicyreference=[u'cn=global_policy,cn=%s,cn=kerberos,%s' % (api.env.realm, api.env.basedn)],
mepmanagedentry=[u'cn=%s,cn=groups,cn=accounts,%s' % (user1, api.env.basedn)],
memberof_group=[u'ipausers'],
dn=u'uid=%s,cn=users,cn=accounts,%s' % (user1, api.env.basedn),
),
),
@ -240,6 +245,9 @@ class test_netgroup(Declarative):
cn=[u'Test User2'],
initials=[u'TU'],
ipauniqueid=[fuzzy_uuid],
krbpwdpolicyreference=[u'cn=global_policy,cn=%s,cn=kerberos,%s' % (api.env.realm, api.env.basedn)],
mepmanagedentry=[u'cn=%s,cn=groups,cn=accounts,%s' % (user2, api.env.basedn)],
memberof_group=[u'ipausers'],
dn=u'uid=%s,cn=users,cn=accounts,%s' % (user2, api.env.basedn),
),
),

View File

@ -67,6 +67,9 @@ class test_replace(Declarative):
initials=[u'TU'],
mail=[u'test1@example.com', u'test2@example.com'],
ipauniqueid=[fuzzy_uuid],
krbpwdpolicyreference=[u'cn=global_policy,cn=%s,cn=kerberos,%s' % (api.env.realm, api.env.basedn)],
mepmanagedentry=[u'cn=%s,cn=groups,cn=accounts,%s' % (user1, api.env.basedn)],
memberof_group=[u'ipausers'],
dn=u'uid=tuser1,cn=users,cn=accounts,' + api.env.basedn,
),
),

View File

@ -98,6 +98,9 @@ class test_user(Declarative):
cn=[u'Test User1'],
initials=[u'TU'],
ipauniqueid=[fuzzy_uuid],
krbpwdpolicyreference=[u'cn=global_policy,cn=%s,cn=kerberos,%s' % (api.env.realm, api.env.basedn)],
mepmanagedentry=[u'cn=%s,cn=groups,cn=accounts,%s' % (user1, api.env.basedn)],
memberof_group=[u'ipausers'],
dn=u'uid=tuser1,cn=users,cn=accounts,' + api.env.basedn,
),
),
@ -153,7 +156,7 @@ class test_user(Declarative):
'krbprincipalname': [u'tuser1@' + api.env.realm],
'loginshell': [u'/bin/sh'],
'memberof_group': [u'ipausers'],
'objectclass': objectclasses.user + [u'mepOriginEntry'],
'objectclass': objectclasses.user,
'sn': [u'User1'],
'uid': [user1],
'uidnumber': [fuzzy_digits],
@ -442,6 +445,9 @@ class test_user(Declarative):
cn=[u'Test User1'],
initials=[u'TU'],
ipauniqueid=[fuzzy_uuid],
krbpwdpolicyreference=[u'cn=global_policy,cn=%s,cn=kerberos,%s' % (api.env.realm, api.env.basedn)],
mepmanagedentry=[u'cn=%s,cn=groups,cn=accounts,%s' % (user1, api.env.basedn)],
memberof_group=[u'ipausers'],
dn=u'uid=tuser1,cn=users,cn=accounts,' + api.env.basedn,
),
),
@ -471,6 +477,9 @@ class test_user(Declarative):
cn=[u'Test User2'],
initials=[u'TU'],
ipauniqueid=[fuzzy_uuid],
krbpwdpolicyreference=[u'cn=global_policy,cn=%s,cn=kerberos,%s' % (api.env.realm, api.env.basedn)],
mepmanagedentry=[u'cn=%s,cn=groups,cn=accounts,%s' % (user2, api.env.basedn)],
memberof_group=[u'ipausers'],
dn=u'uid=tuser2,cn=users,cn=accounts,' + api.env.basedn,
),
),
@ -602,6 +611,9 @@ class test_user(Declarative):
postalcode=[u'01234-5678'],
telephonenumber=[u'410-555-1212'],
ipauniqueid=[fuzzy_uuid],
krbpwdpolicyreference=[u'cn=global_policy,cn=%s,cn=kerberos,%s' % (api.env.realm, api.env.basedn)],
mepmanagedentry=[u'cn=%s,cn=groups,cn=accounts,%s' % (user1, api.env.basedn)],
memberof_group=[u'ipausers'],
dn=u'uid=tuser1,cn=users,cn=accounts,' + api.env.basedn,
),
),