[Freeipa-devel] Return values, CRUD, webUI

Jason Gerard DeRose jderose at redhat.com
Thu Nov 19 09:45:49 UTC 2009


On Wed, 2009-11-18 at 15:15 +0100, Pavel Zuna wrote:
> Jason Gerard DeRose wrote:
> > The vast majority of our Command plugins subclass from one of the CRUD
> > base classes, so in terms of return value consistency and API style, we
> > need to focus most on them (and then adapt their style to the few
> > non-CRUD commands).
> > 
> > While hooking up the webUI there have been many, many small problems in
> > the core library and plugins that have caused unexpected setbacks for
> > me.  Some features that I needed got changed without me noticing, some
> > of my half-baked designs needed more baking, some features were missing,
> > and some new code I was just unfamiliar with.  Point is, I've spent a
> > lot of time battling little gotchas and thinking about how best to clean
> > these things up.  Here are the guidelines I propose we follow:
> > 
> > 
> > A return value dict
> > ===================
> > 
> > As much as possible, I want to keep our return values very simple and
> > regular.  This 1) makes our API easy to learn and use, and 2) makes it
> > easy to use the return values to drive UI logic on both the CLI and
> > webUI.
> > 
> > One current source of irregularity is the need to pass the "this isn't
> > all the entries" flag from LDAP when we do searches.  For example,
> > `user_find` returns an (entry_list, more_remains) tuple.  The problem is
> > that most of the code paths don't care about the `more_remains` flag...
> > they just need to know whether a list of entries was returned (result is
> > a list) or whether a single entry was returned (result is a dict).
> > 
> > At the same time, we obviously need a way to pass extra data like the
> > `more_remains` flag and it would be nice to be able to extend a return
> > value with additional special data without breaking code or causing an
> > explosion of special cases.  So I propose that our return values always
> > be a dict containing at least a 'result', leaving us the option to
> > extend the return value without breaking code that just looks at
> > ret['result'].
> > 
> > So in the case of a search, instead of:
> > 
> >     ([{'uid': 'foo'}, {'uid': 'bar'}, ...], True)
> > 
> > We should return:
> > 
> >     {
> >         'result': [{'uid': 'foo'}, {'uid': 'bar'}, ...],
> >         'more_remains': True,
> >         ...
> >         'extend': 'as-needed',
> >     }
> > 
> > The following all assume we are returning {'result': blah} even though
> > they don't show it...
> > 
> > 
> > Entries
> > =======
> > 
> > 95% of our return values are LDAP entries.  Currently we're returning
> > pretty much the raw value from python-ldap (although we are decoding
> > UTF-8 into `unicode` objects for use in the Python pipeline and encoding
> > back to UTF-8 on the way out, which is good).  But the data structure
> > returned from python-ldap is pretty awkward to work with.
> > 
> > First, at the top it's typically a (dn, entry) tuple.  Assuming the 'dn'
> > key doesn't conflict with any sane LDAP attribute names, I think we
> > should return a single dict with the dn stored under the 'dn' key.
> > 
> > So instead of:
> > 
> >     ('uid=jdoe,cn=users,cn=accounts,dc=example,dc=com', {'sn': ['Doe']})
> > 
> > We should return:
> > 
> >     {'dn': 'uid=jdoe,cn=users,cn=accounts,dc=example,dc=com', 'sn': ['Doe']}
> > 
> > Second, currently we return all attribute values inside a list whether
> > or not they're multi-value.  This leads to lots of special cases
> > throughout the code that would be better dealt with in a single place,
> > in LDAP Backend adapter, IHMO.
> > 
> > So instead of:
> > 
> >     {'uid': ['jdoe'], 'group': ['foo', 'bar']}
> > 
> > We should return:
> > 
> >     {'uid': 'jdoe', 'group': ['foo', 'bar']}
> This is the only part I don't really agree with. See this thread for my reasons:
> 
> [Freeipa-devel] [PATCH] Add --all to LDAPCreate and make LDAP commands always 
> display default attributes.
> 
> But since both you and Rob seem to agree, I won't stand in the way and just make 
> the change. :)

Well, you've made some good points, and this is something I don't feel
super strongly about either way (although I lean toward not putting
scalar values in a list).

Rob, has this swayed you either way?

> > 
> > Lists of Entries
> > ================
> > 
> > When a command returns multiple entries, the entries should be in the
> > same form as they are from commands that return only one entry.  For
> > example, currently user-find returns each entry as a (uid, entry) tuple.
> > I think this should again be replaced with a single dict without the uid
> > being duplicated.
> > 
> > 
> > Create
> > ======
> > 
> > If successful, we should return the resulting entry in standard form.
> > If any error occurs, we should raise an appropriate exception.
> > 
> > 
> > Retrieve
> > ========
> > 
> > If successful, we should return the entry in standard form.  If no such
> > entry exists we should raise a NotFound exception.  If any other error
> > occurs, we should raise an appropriate exception.
> > 
> > 
> > Update
> > ======
> > 
> > (Same as Create.)
> > 
> > 
> > Delete
> > ======
> > 
> > (Same as Retrieve.)
> >
> After a delete, there is no entry to return. Unless an exception was raised, I 
> think we should just report 'delete successful' to the user and be done with it.
> 
> > 
> > Search
> > ======
> > 
> > If one or more entries matches the search criteria, we should return a
> > list of entries, where the each entry is in standard form.  If no
> > entries match, we should return an empty list.  If an error occurs, we
> > should raise an appropriate exception.
> > 
> > 
> > Thoughts?
> > 
> > -Jason
> > 
> 
> It's going to take a while to implement (and test!) all these changes, but I 
> should have it done by next week.
> 
> Pavel

We need to coordinate closely on these changes so we don't duplicate.  I
have some proof of concept changes I made just while exploring the idea,
but these were just scratch really.




More information about the Freeipa-devel mailing list