@William Brown
 
Thanks for the reply .

I was wondering if UserAccount can do it , why UserAccounts cant .

Anyway now i will go for 3. (best) to solve the problem.

Thanks
Anuj Borah

On Wed, Mar 27, 2019 at 5:45 AM William Brown <wbrown@suse.de> wrote:
Hi,

I have previously commented a number of times on this pattern that you have been using and that it is incorrect in reviews.

> On 26 Mar 2019, at 13:27, Anuj Borah <aborah@redhat.com> wrote:
>
> Hay everyone,
>
> Consider bellow condition:
>
> users = UserAccounts(topo.standalone, f"ou=Keywords,{DEFAULT_SUFFIX}", rdn=None)
> for i in [f'NONE_2_KEY,ou=Authmethod',
>           f'EVERYDAY_KEY,ou=Dayofweek',
>           f'TODAY_KEY,ou=Dayofweek',
>           f'NODAY_KEY,ou=Dayofweek',
>           f'NETSCAPEDNS_KEY,ou=DNS',
>           f'FULLIP_KEY,ou=IP',
>           f'NETSCAPEIP_KEY,ou=IP',
>           f'NOIP_KEY,ou=IP',
>           f'FULLWORKER_KEY,ou=Timeofday',
>           f'DAYWORKER_KEY,ou=Timeofday',
>           f'NIGHTWORKER_KEY,ou=Timeofday',
>           f'NOWORKER_KEY,ou=Timeofday']:
>     properties = {
>         'uid': i,
>         'cn': i.split(',')[0],
>         'sn': 'user',
>         'uidNumber': '1000',
>         'gidNumber': '2000',
>         'homeDirectory': '/home/' + i,
>         'userPassword': PW_DM
>     }
>     users.create(properties=properties)

^ This is where the mistake happens. UserAccounts *already* knows that you have an rdn etc. So then you say “users.create(uid = “everyday_key,ou=….”).

So it LITERALLY takes that, escapes the content (which is the cause of the \\2C and \\3D you see below) and put’s that into the field)


>
>
> If you see the created users:
>
> for i in users.list(): i.dn
> 'uid=NONE_2_KEY\\2Cou\\3DAuthmethod,ou=Keywords,dc=example,dc=com'
> 'uid=EVERYDAY_KEY\\2Cou\\3DDayofweek,ou=Keywords,dc=example,dc=com'
> 'uid=TODAY_KEY\\2Cou\\3DDayofweek,ou=Keywords,dc=example,dc=com'
> 'uid=NODAY_KEY\\2Cou\\3DDayofweek,ou=Keywords,dc=example,dc=com'
> 'uid=NETSCAPEDNS_KEY\\2Cou\\3DDNS,ou=Keywords,dc=example,dc=com'
> 'uid=FULLIP_KEY\\2Cou\\3DIP,ou=Keywords,dc=example,dc=com'
> 'uid=NETSCAPEIP_KEY\\2Cou\\3DIP,ou=Keywords,dc=example,dc=com'
> 'uid=NOIP_KEY\\2Cou\\3DIP,ou=Keywords,dc=example,dc=com'
> 'uid=FULLWORKER_KEY\\2Cou\\3DTimeofday,ou=Keywords,dc=example,dc=com'
> 'uid=DAYWORKER_KEY\\2Cou\\3DTimeofday,ou=Keywords,dc=example,dc=com'
> 'uid=NIGHTWORKER_KEY\\2Cou\\3DTimeofday,ou=Keywords,dc=example,dc=com'
> 'uid=NOWORKER_KEY\\2Cou\\3DTimeofday,ou=Keywords,dc=example,dc=com'
>
> We can see users become useless to use for further operations.
>
> And consider bellow condition:
>
>
> for i in [f'NONE_2_KEY,ou=Authmethod',
>           f'EVERYDAY_KEY,ou=Dayofweek',
>           f'TODAY_KEY,ou=Dayofweek',
>           f'NODAY_KEY,ou=Dayofweek',
>           f'NETSCAPEDNS_KEY,ou=DNS',
>           f'FULLIP_KEY,ou=IP',
>           f'NETSCAPEIP_KEY,ou=IP',
>           f'NOIP_KEY,ou=IP',
>           f'FULLWORKER_KEY,ou=Timeofday',
>           f'DAYWORKER_KEY,ou=Timeofday',
>           f'NIGHTWORKER_KEY,ou=Timeofday',
>           f'NOWORKER_KEY,ou=Timeofday']:
>     properties = {
>         'uid': i,
>         'cn': i.split(',')[0],
>         'sn': 'user',
>         'uidNumber': '1000',
>         'gidNumber': '2000',
>         'homeDirectory': '/home/' + i,
>         'userPassword': PW_DM
>     }
>     users = UserAccount(topo.standalone, f"cn={i},ou=Keywords,{DEFAULT_SUFFIX}")
>     users.create(properties=properties)
>
>
> users = UserAccounts(topo.standalone, f"ou=Keywords,{DEFAULT_SUFFIX}", rdn=None)
>
> for i in users.list(): i.dn
> 'cn=NONE_2_KEY,ou=Authmethod,ou=Keywords,dc=example,dc=com'
> 'cn=EVERYDAY_KEY,ou=Dayofweek,ou=Keywords,dc=example,dc=com'
> 'cn=TODAY_KEY,ou=Dayofweek,ou=Keywords,dc=example,dc=com'
> 'cn=NODAY_KEY,ou=Dayofweek,ou=Keywords,dc=example,dc=com'
> 'cn=NETSCAPEDNS_KEY,ou=DNS,ou=Keywords,dc=example,dc=com'
> 'cn=FULLIP_KEY,ou=IP,ou=Keywords,dc=example,dc=com'
> 'cn=NETSCAPEIP_KEY,ou=IP,ou=Keywords,dc=example,dc=com'
> 'cn=NOIP_KEY,ou=IP,ou=Keywords,dc=example,dc=com'
> 'cn=FULLWORKER_KEY,ou=Timeofday,ou=Keywords,dc=example,dc=com'
> 'cn=DAYWORKER_KEY,ou=Timeofday,ou=Keywords,dc=example,dc=com'
> 'cn=NIGHTWORKER_KEY,ou=Timeofday,ou=Keywords,dc=example,dc=com'
> 'cn=NOWORKER_KEY,ou=Timeofday,ou=Keywords,dc=example,dc=com'
>
> Here users are in good shape .

Here, because you do cn as i.split(,), now the cn becomes “EVERYDAY_KEY” and the provided basedn you have in the UserAccount initialise is now set to the full DN, so the create works.

Basically, the mistake here is that you are iterating over a list of partial-dn’s and you expect lib389 to magically fix this all for you, and it’s behaviour is now surprising you because it’s “making safe” from your mistake.


There are two main pieces of advice I would give here.

First is to *stop* thinking about everything in terms of DN’s and start thinking about things in terms of “containers and what they hold”. When you do:

uas = UserAccounts(basedn=DEFAULT_SUFFIX, rdn=ou=People)

You are describing “Here is the set of all possible users, and where they exist in the servers tree”. So now that UserAccounts is setup like this you can do:

uas.create(properties={
    uid: ’test'
})

this will be combined to make uid=test + ou=People + DEFAULT_SUFFIX -> uid=test,ou=people,DEFAULT_SUFFIX.

Now, when we look at your example, because you are trying to take shortcuts, you are including the location of the object into the cn parameter with things like: ‘ips,ou=ips’ ….


There are three possible ways to handle this.

1: (okay, but not the best)

Create each item bypassing UserAccounts, by loading the full dn into the UserAccount setup. This is done with:

u = UserAccount(topo.standalone, dn=“uid=test,ou=People,dc=example,dc=com”)
u.create(properties={
    ….
})

Remember, UserAccount (singular) being an absolute object, can have a full path into the DN like this. Once you have added all these, even if you do say:

u = UserAccount(topo.standalone, dn=“uid=test,ou=Container,ou=People,dc=example,dc=com”)

uas = UserAccounts(topo.standalone, DEFAULT_SUFFIX, rdn=ou=People)
uas.list()

uas.list/get will find the userAccount becaus it’s a subtree seacch, regardless of how many containers exist in the path.


2. (“good enough")

Keep updating and changing your UserAccounts to account for the relative location change during your create:

authmethod_users = UserAccounts(topo.standalone, DEFAULT_SUFFIX, rdn=ou=Authmethod,ou=Keywords)
uas.create( …)

ip_users = UserAccounts(topo.standalone, DEFAULT_SUFFIX, rdn=ou=IP,ou=Keywords)
ip_users.create(…)

So this at the very least means you keep things work in the best way possible, even though you need to do lots of changes to get all the weird rdns. You can probably solve this with some lists of tuples like:

my users = [ (’name’, ‘ou=ip,ou=keywords’),
                     ….]

for (uid, rdn) in my_users:
    us = UserAccounts(topo.standalone, DEFAULT_SUFFIX, rdn)
    us.create(properties={ ‘uid’: uid })



3. (best)

Unless the test requires you to have all these crazy ou’s (and even if it does … fixtures per test, rather than one giant fixture per module …), then your users should all be in a SINGLE OU anyway. LDAP supports filtering and querying, which is a much more effective way of expressing constraints and what users you want etc.

So just do:

users = UserAccounts(topo.standalone, DEFAULT_SUFFIX)


test_fixture_1
    users.create(…)
    fin:
        for u in users.get():
            u.delete()

test_fixture_2
    users.create(…)
    …


my_test(test_fixture_1)
    # Now do the test thing. Apply my ACI to ou=People instead, and do the test, then reset in the fixture.

I think you often are trying to copy-paste ACI’s as they are from past tests, you are trying to duplicate bad test structure from TET, and you are then hitting up against lib389 and wondering why it won’t work. Of course it won’t! Lib389 *can* allow you to do everything you want with LDAP, but for the common cases, lib389 is trying to guide you to do things in a certain, correct, and simple way. Sprawling deep tree directories are awful to administer and understand, where flatter structures defined by group memberships and filtering are far nicer.

Remember: if you find you are struggling to do something, is it the API that’s at fault? Or the way you are approaching the problem?


Hope that helps,



Sincerely,

William Brown

Senior Software Engineer, 389 Directory Server
SUSE Labs
_______________________________________________
389-devel mailing list -- 389-devel@lists.fedoraproject.org
To unsubscribe send an email to 389-devel-leave@lists.fedoraproject.org
Fedora Code of Conduct: https://getfedora.org/code-of-conduct.html
List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines
List Archives: https://lists.fedoraproject.org/archives/list/389-devel@lists.fedoraproject.org