Article
Here is a powerful Vim script to generate an LDIF backlinks export from a links export, such as to generate a user groupMemberships LDIF from a group members export. This has been useful during large first loads, when creating thousands of users with hundreds of groups and thousands of links and backlinks.
Script Installation
To install the script and use it in Vim,
1. Copy the file ldap_links.vim in your home folder, in a ".vim" folder.
2. Use the following code in your Vim init file in your home folder (".vimrc" in Linux, "_vimrc" in Windows):
source $HOME/.vim/ldap_links.vim
map <F7> :call LDIF:GenerateBackLinksAuto()<CR>
map <F8> :call LDIF:GenerateBackLinks(input("Link name (eg. member): ",'member'),input("Backlink name(eg. groupMembership): ",'groupMembership'))<CR>
The second line maps the function to the F7 key, to auto-generate the backlinks export. The third line takes the input of the link name and the backlink name before calling the function, and maps it to the F8 key.
Script Execution
To execute the script, simply press F7. If it is a member, groupMembership, manager, directReports, securityEquals or equivalentToMe export, the backlinks LDIF will automatically be generated. Otherwise, it will ask for the link name and the backlink name. Pressing F8 will directly ask for the link name and the backlink name to use.
Here is a short example of transformation. Let's take the following group members export:
1 # LDIF export of groups 2 version: 1 3 4 dn: cn=group2,ou=groups,ou=organizationalunit3,ou=organizationalunit2,ou=organ 5 izationalunit1,o=organization 6 changetype: modify 7 modify: member 8 member: cn=member1,ou=organizationalunit3,ou=organizationalunit2,ou=organizati 9 onalunit1,o=organization 10 member: cn=member2,ou=organizationalunit3,ou=organizationalunit2,ou=organizati 11 onalunit1,o=organization 12 13 dn: cn=group1,ou=groups,ou=organizationalunit3,ou=organizationalunit2,ou=organ 14 izationalunit1,o=organization 15 changetype: modify 16 modify: member 17 member: cn=member4,ou=organizationalunit3,ou=organizationalunit2,ou=organizati 18 onalunit1,o=organization 19 member: cn=member1,ou=organizationalunit3,ou=organizationalunit2,ou=organizati 20 onalunit1,o=organization
Here is the result when pressing F7:
1 # LDIF generated by Vim 2 # "groupMembership" back links generated from "member" links 3 # 3 entries with 4 total back links created 4 version: 1 5 6 dn: cn=member1,ou=organizationalunit3,ou=organizationalunit2,ou=organizational 7 unit1,o=organization 8 changetype: modify 9 add: groupMembership 10 groupMembership: cn=group1,ou=groups,ou=organizationalunit3,ou=organizationalu 11 nit2,ou=organizationalunit1,o=organization 12 groupMembership: cn=group2,ou=groups,ou=organizationalunit3,ou=organizationalu 13 nit2,ou=organizationalunit1,o=organization 14 15 dn: cn=member2,ou=organizationalunit3,ou=organizationalunit2,ou=organizational 16 unit1,o=organization 17 changetype: modify 18 add: groupMembership 19 groupMembership: cn=group2,ou=groups,ou=organizationalunit3,ou=organizationalu 20 nit2,ou=organizationalunit1,o=organization 21 22 dn: cn=member4,ou=organizationalunit3,ou=organizationalunit2,ou=organizational 23 unit1,o=organization 24 changetype: modify 25 add: groupMembership 26 groupMembership: cn=group1,ou=groups,ou=organizationalunit3,ou=organizationalu 27 nit2,ou=organizationalunit1,o=organization 28
Pressing F7 again will revert back to the previous state. You can also call the script using the following command:
:call LDIF:GenerateBackLinks("member","groupMembership")
or
:call LDIF:GenerateBackLinks("groupMembership","member")
The same will work with managers export:
1 # LDIF generated by Vim 2 version: 1 3 4 dn: cn=employee1,ou=organizationalunit3,ou=organizationalunit2,ou=organization 5 alunit1,o=organization 6 changetype: modify 7 add: manager 8 manager: cn=manager1,ou=managers,ou=organizationalunit3,ou=organizationalunit2 9 ,ou=organizationalunit1,o=organization 10 11 dn: cn=employee2,ou=organizationalunit3,ou=organizationalunit2,ou=organization 12 alunit1,o=organization 13 changetype: modify 14 add: manager 15 manager: cn=manager1,ou=managers,ou=organizationalunit3,ou=organizationalunit2 16 ,ou=organizationalunit1,o=organization
Here is the result when pressing F7:
1 # LDIF generated by Vim 2 # "directReports" back links generated from "manager" links 3 # 1 entries with 2 total back links created 4 version: 1 5 6 dn: cn=manager1,ou=managers,ou=organizationalunit3,ou=organizationalunit2,ou=o 7 rganizationalunit1,o=organization 8 changetype: modify 9 add: directReports 10 directReports: cn=employee1,ou=organizationalunit3,ou=organizationalunit2,ou=o 11 rganizationalunit1,o=organization 12 directReports: cn=employee2,ou=organizationalunit3,ou=organizationalunit2,ou=o 13 rganizationalunit1,o=organization
And for a custom links export:
1 # LDIF generated by Vim 2 version: 1 3 4 dn: cn=employee1,ou=organizationalunit3,ou=organizationalunit2,ou=organization 5 alunit1,o=organization 6 changetype: modify 7 add: manager 8 mySuperiorDn: cn=manager1,ou=managers,ou=organizationalunit3,ou=organizationalunit2 9 ,ou=organizationalunit1,o=organization 10 11 dn: cn=employee2,ou=organizationalunit3,ou=organizationalunit2,ou=organization 12 alunit1,o=organization 13 changetype: modify 14 add: manager 15 mySuperiorDn: cn=manager1,ou=managers,ou=organizationalunit3,ou=organizationalunit2 16 ,ou=organizationalunit1,o=organization
Pressing F7 or F8 will ask for the link name and backlink name. In this example we use "mySuperiorDn" and "myEmployeesDn":
1 # LDIF generated by Vim 2 # "myEmployeesDn" back links generated from "mySuperiorDn" links 3 # 1 entries with 2 total back links created 4 version: 1 5 6 dn: cn=manager1,ou=managers,ou=organizationalunit3,ou=organizationalunit2,ou=o 7 rganizationalunit1,o=organization 8 changetype: modify 9 add: myEmployeesDn 10 myEmployeesDn: cn=employee1,ou=organizationalunit3,ou=organizationalunit2,ou=o 11 rganizationalunit1,o=organization 12 myEmployeesDn: cn=employee2,ou=organizationalunit3,ou=organizationalunit2,ou=o 13 rganizationalunit1,o=organization
Try the script on the different test exports attached. These are group members, equivalentToMe and managers exports that will be converted into user groupMemberships, securityEquals and directReports exports.
More about the Vim Script
There are two versions of the GenerateBackLinks function in the Vim script. One is an old one I created for version 6 and earlier of Vim; the other one is a new one for version 7 of Vim and higher. This is because Vim introduced new dictionary and list objects in Vim 7.
Old Script for Vim version 6 and Earlier
The old version of the function uses a few regular expressions. For instance, the following command simply deletes all lines in the export that do not contain "dn:" or the link attribute (such as "member:").
:v/^dn:\|^member:/d
This one delete all empty dn entries:
:v/^dn:.*\n^member:\|^member:/d
This very powerful one sorts the links by block:
:g/^dn:/+1,/^$/-1!sort
Starting with Vim 7, there is a built-in sort function that can work as shown below ("!" was calling an external sort command):
:g/^dn:/+1,/^$/-1sort
New Script for Vim version 7 and Later
The new version of the script uses new Dictionary and List object types. The Dictionary type is like HashMap in Java, or the associative array in Php.
You can, for instance, create new lists in Vim using the following code:
:let mylist1 = [ "member1", "member2" ] :let mylist2 = [ "member3", "member4" ]
You can then easily access lists content:
:echo mylist1[0] member1 :echo mylist2[1] member4
You can create a new group dictionary with the following:
:let mydic = { "group2": mylist2, "group1": mylist1 }
When such a structure is created, there are many Vim functions to manipulate it:
:echo mydic["group1"][0] member1 :echo sort(keys(mydic)) ['group1', 'group2'] :echo has_key(mydic,"group1") 1 :echo has_key(mydic,"group3") 0
The script builds a structure with all members and their groups from all the groups and their members. Then it's pretty easy to cycle through it and build the final LDIF export.
Here is the most important part of the script. It cycles through all the lines, checks which is the current dn, and retrieves links values in the dictionary structure:
266 "Analyse LDIF content, links and dn are stored in a dictionary
267 let s:linksdic = {}
268 let s:currentdn = ''
269 let s:count = 1
270 let s:totaldn = 0
271 let s:totalbl = 0
272 while s:count < line('$')
273 let s:count = s:count + 1
274 let s:line = getline(s:count)
275
276 "Check if current line contains a new dn
277 if matchstr(s:line,'^dn:.*') != ''
278 let s:currentdn = substitute(s:line,'^dn: \(.*\)','\1','')
279
280 "Check if current line contains a new link
281 elseif matchstr(s:line,'^'.a:linkname.':.*') != ''
282
283 "Get link dn
284 let s:link = substitute(s:line,'^'.a:linkname.': \(.*\)','\1','')
285
286 "Check if current link already exists in the dictionary
287 "and add the current dn in the list entry if dn not in the list
288 if has_key( s:linksdic, s:link )
289 let s:backlinks = s:linksdic[s:link]
290 if count( s:backlinks, s:currentdn ) == 0
291 call add( s:backlinks, s:currentdn )
292 let s:totalbl = s:totalbl + 1
293 endif
294 else
295 "Create a new list entry with current dn if key does not exist
296 let s:backlinks = [s:currentdn]
297 let s:linksdic[s:link] = s:backlinks
298 let s:totaldn = s:totaldn + 1
299 let s:totalbl = s:totalbl + 1
300 endif
301 endif
302 endwhile
You can also have a look at the source code to see how the dictionary "s:linksdic" is used. Using the same technique, you can easily get a virtual representation of any LDIF objects and manipulate them (convert to CSV, XML, filter, run stats, merge LDIF contents, etc.). Have fun!
| Anhang | Größe |
|---|---|
| ldap_links.vim_.zip | 2.47 KB |
| test_groups.ldif_.zip | 339 bytes |
| test_managers.ldif_.zip | 313 bytes |
| test_security.ldif_.zip | 355 bytes |
Disclaimer: As with everything else at Cool Solutions, this content is definitely not supported by Novell (so don't even think of calling Support if you try something and it blows up).
It was contributed by a community member and is published "as is." It seems to have worked for at least one person, and might work for you. But please be sure to test, test, test before you do anything drastic with it.
Related Articles
User Comments
- Be the first to comment! To leave a comment you need to Login or Register
- 5415 reads



0