At the end of last year, I suggested that we start a contest to gather up the best examples of elegant coding in DirXML Script.
The notion was, lets see your most elegant code sample, that does something useful, is interesting, and pretty quick. This is one of the cool things about Novell Identity Manager, there are so many different ways to do the same thing, that there is almost always something to learn from someone else's example.
Now I have to apologize to everyone and excuse myself for my extreme lateness on this article. I had meant to finish it up and post the results, alas, months ago, but you know how life gets. First I needed to get all the votes in, tally them, then write the article. But life kept getting in the way, and it fell off my radar. So my apologies to everyone who entered, for the delay in announcing the results. Sorry about that. The good news is that there were lots of great entries.
With that goal in mind, we scored based on three categories. Magnitude, simplicity, and performance.
Magnitude was related to how big a deal the task the code performed. As someone joked in the forums, as we were discussing the format, the simplest most elegant form of a rule would veto everything (He even provided a sample. Very funny David). Yes, very simple but not very useful. Though probably quite performant.
Next up is simplicity. The example I used to try and illustrate this point was an approach I got from Father Ramon to use strip by XPATH express to clean up a nodeset, in a single line of DirXML Script, which executed on 10,000 values in seconds, where before I had a for each loop that did the same work, but took almost two hours to run.
To me that was the sort of example I was looking for.
Finally was performance. If something was going to be horribly slow, then it almost by definition is probably not the most elegant example.
This is one of the fun things about working with Novell Identity Manager. Novell provides a really powerful framework and lets you do what you want within it. There are limits, but it amazes me each time we are able to push those and do something really powerful.
We got lots of interesting suggestions (thirteen in total actually) that ranged from as simple as adding an XML attribute to a document (simple, the notional elegance is that it enables some extra functionality in the driver) to as complex as a way to handle converting multi valued to single valued attributes that needed four different policy objects in different parts of the process.
Overall we had some great submissions, and I definitely learned a fair bit from it. Some of the notions became things I started using in most every project I work on now.
My favorite tidbit that came out of it was actually simple, remarkably useful, and left me saying, "Why did I not think of that?". It was a way of embedding comments inside the Rule. Use a do-trace token, and then just disable it. (Thanks Peter L.!) This way you can use the Comment block at the top of the rule to explain in general, and as you add a minor (or major) bit of functionality you can add comments inline to explain what is going on. This was something I had really wanted to get my hands on, since I am a huge fan of commentary in policy. There can never be enough. But alas that was not enough to win, with the caliber of competition out there.
The top three were pretty close, and after taking the three sets of scores and combining the,, we ended up with a tie for first between Rob Rawson and Lothar Haeger. Next up was Jim Willeke. (Lothar actually had a second submission that scored second, but no duplication of prizes!).
Lothar's winning entry was a fun one. I thought he would enter something from his Password Notifier driver (IDM 3.5 Password Notification Service Driver, http://www.brummelhook.com/dirxml.html) which has lots of great stuff in it, like an ECMA implementation of LDAP search (which is DARN useful) but he pulled out a new one! (Actually two new ones!) That reminds me, I have a modified version of that does ldapModifies in ECMA which is equally useful. Lothar asked me to note that the code for the ECMA LDAP Search, and the TLS support came based on advice and insight from Father Ramon, the patronizing saint of IDM. But then so many great ideas came from him as well! If you are not reading the forums to see his wisdom, you are losing out!
The winning submissionwas a very nice way to look at an object being created, by the destination DN and see if the container actually exists. If it does not, the rule creates it. Very nicely done. This can be extended nicely to work in most drivers, and would be a really nice addition to some of the basic driver configurations. Hopefully, when Identity Manager 4 comes out with Packaging this might be the sort of add on he can make available. Stay tuned for an article with more details on how Packaging works.
His second entry that did really well was specific to SAP where there can be multiple events coming in within a one second interval, so he wrote some nice Policy that delays it by a few seconds to keep the events in sequence. There are a lot of nice ideas in that one. The notion of using a driver scoped variable to keep some stuff around till the next operation. The notion of making it an XML nodeset variable, so you can use XPATH on it, to do powerful tricks. Like stripping out any events that are too old, and adding in events that are needed to be delayed.
He was missing the next part that did something with it, but that's ok, the interesting part was in the delaying action. I have since been using some of the ideas quite regularly. I have a use case where storing the list of changes to an object that need approval, as an XML attribute is really powerful. By storing it as an XML attribute, you can use XPATH to parse it to get what you need, with all the power of XPATH.
Turns out Lothar has submitted both these articles to Cool Solutions in the past at:
The second tie for first place was by Rob Rawson. This is a very cute approach, and he had it published as http://www.novell.com/communities/node/9413/generic-single-valued-schema-enforcement on Cool Solutions already. This one solves a major problem, and demonstrates a lot of hidden functionality built into Identity Manager. With Active Directory specifically, but other drivers as well, you often have an attribute that is single valued here, multivalued there and vica versa. This is so common, that Rob actually wrote a tool that read the schema map. looked at Active Directory and eDirectory's schema definitions, and wrote individual rules to manage this. That worked, but you ended up with a single rule for each attribute in use, so you could have one to dozens. (Of course it also handled resizing them, say eDirectory sizes a Case Ignore String attribute to 64 characters and Active Directory sizes it to 32, then you need to strip in one direction or else you get errors).
This is a general solution to the single to multi valued case. What is elegant about it, is that it looks at the DirXML-ApplicationSchema attribute, which every driver tries to generate on the first startup, and on any time you select Refresh application Schema in iManager. The driver is supposed to implement a getSchema() function that retrieves this info and each object class, and attribute gets a line in this XML document with a bunch of XML attributes that say if it is multi valued or not, and other information. Alas, not all the schema details get represented, which would be even more useful!
Now some drivers do a more complete job than others. (I wrote a policy for my Salesforce.com driver to do it, but it turns out the useful information is not made available by Salesforce.com. Or more correctly, every attribute is single values in Salesforce.com). But the Active Directory driver at least tells you if the schema defines the attribute as single or multi valued. Well technically it says mult-value=true if it is multi valued.
This is one of those rules you want trace disabled for performance reasons, and it uses XPATH wisely to select the right information, which is very fast. I once tried to troubleshoot an instance of this rule, and I was convinced I had improved his XPATH till I came across an edge case which he had for seen, and handled, but my 'correction' took away. See, if he had only added a comment like this, I never would have wasted my time on it!
A cute trick it uses is to load the DirXML-ApplicationSchema XML document into a driver scoped local variable, so it is only ever read off the driver once per driver start, and just sits idly in memory till needed. Then in the Output transform, as each attribute is headed out to Active Directory, loop through all the attributes in the document and if the attribute (past the Schema Map, so already in the Application namespace) is listed in the DirXML-ApplicationSchema, decide if it is a multivalued attribute and if so, what to do with it.
Since it loops through every attribute in the document, you can see that this will generate a fair bit of trace, that can slow down the process. With trace disabled it runs quite quickly.
Personally I would love to see the length of sized attributes listed in the DirXML-ApplicationSchema, and maybe even a simply named schema syntax as well, but that would require code changes in each driver to implement, and may not really be possible.
Finally our last winner was Jim Willeke,.who has published his notion on his excellent Wiki site he maintains at: Removing Novell Granted Entitlements I highly recommend browsing around, and particularly, look at his Universal Password Diagnostic tool (Password Information Tool) which is UTTERLY invaluable in diagnosing issues with passwords in eDirectory. I use it literally every day, and love it.
His solution is nice and simple and looks at and takes apart the DirXML-EntitlementRef to understand how to react to start a workflow for the event.
Probably the nicest bit he called out at the top is the XPATH you would need to find the information of interest, since the DirXML-EntitlementRef attribute is Path syntax, and the third component, usually ="path" is actually ="path.xml" and contains an XML nodeset serialized as text.
Lots of nice little pieces in there and as always some nits to pick, since he assumes the ="volume" component is equal to 1 it means the entitlement is active, when in fact that is a bit mask field, (Thanks Shon!). Though in all my looking at this attribute I have only ever seen it have a value of 0 or 1. But as Jim says, Novell does not want us writing to this attribute directly, since they probably will extend its usage over time. Roles and Resources in the Roles Based Provisioning Module use this quite heavily, and thus may be extended in the future. There are tokens you can use to add an entitlement, and that is probably your better way in general. This case just reads the values and deals with it, instead of using the Revoke Entitlement token, since he wants a workflow to be approved before really removing it.
Overall there were lots of interesting entries, and each contributor should submit their notions to Cool Solutions for publication as standalone articles, and of course if they want any help editing and getting the articles ready, just let me know and I can help out.
Thanks to the judges for their contributions, Aaron Burgemeister from Novell Technical Support and the artist formerly known as Father Ramon.