diff options
author | Jason Gerard DeRose <jderose@redhat.com> | 2010-02-04 09:52:33 -0700 |
---|---|---|
committer | Rob Crittenden <rcritten@redhat.com> | 2010-02-05 14:32:04 -0500 |
commit | c43b69e77cf46118d40b89e6be557d19181da8f6 (patch) | |
tree | 57b0c139523284f342d2045368aa59c0551d0fe0 /ipalib | |
parent | ea6dfc30fa9003850c7d57f1246334381ed74b71 (diff) | |
download | freeipa-c43b69e77cf46118d40b89e6be557d19181da8f6.tar.gz freeipa-c43b69e77cf46118d40b89e6be557d19181da8f6.tar.xz freeipa-c43b69e77cf46118d40b89e6be557d19181da8f6.zip |
Add support for the 'no_create', 'no_update', and 'no_search' Param flags
Diffstat (limited to 'ipalib')
-rw-r--r-- | ipalib/crud.py | 112 |
1 files changed, 109 insertions, 3 deletions
diff --git a/ipalib/crud.py b/ipalib/crud.py index 173fefc72..77c97f3f4 100644 --- a/ipalib/crud.py +++ b/ipalib/crud.py @@ -16,14 +16,114 @@ # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + """ Base classes for standard CRUD operations. + +These base classes are for `Method` plugins that provide standard +Create, Retrieve, Updated, and Delete operations (CRUD) for their corresponding +`Object` plugin. In particuar, these base classes provide logic to +automatically create the plugin args and options by inspecting the params on +their corresponding `Object` plugin. This provides a single point of definition +for LDAP attributes and enforces a simple, consistent API for CRUD operations. + +For example, say we want CRUD operations on a hypothetical "user" entry. First +we need an `Object` plugin: + +>>> from ipalib import Object, Str +>>> class user(Object): +... takes_params = ( +... Str('login', primary_key=True), +... Str('first'), +... Str('last'), +... Str('ipauniqueid', flags=['no_create', 'no_update']), +... ) +... + +Next we need `Create`, `Retrieve`, `Updated`, and `Delete` plugins, and +optionally a `Search` plugin. For brevity, we'll just define `Create` and +`Retrieve` plugins: + +>>> from ipalib import crud +>>> class user_add(crud.Create): +... pass +... +>>> class user_show(crud.Retrieve): +... pass +... + +Now we'll register the plugins and finalize the `plugable.API` instance: + +>>> from ipalib import create_api +>>> api = create_api() +>>> api.register(user) +>>> api.register(user_add) +>>> api.register(user_show) +>>> api.finalize() + +First, notice that our ``user`` `Object` has the params we defined with the +``takes_params`` tuple: + +>>> list(api.Object.user.params) +['login', 'first', 'last', 'ipauniqueid'] +>>> api.Object.user.params.login +Str('login', primary_key=True) + +Although we defined neither ``takes_args`` nor ``takes_options`` for our +``user_add`` plugin, the `Create` base class automatically generated them for +us: + +>>> list(api.Command.user_add.args) +['login'] +>>> list(api.Command.user_add.options) +['first', 'last'] + +Notice that ``'ipauniqueid'`` isn't included in the options for our ``user_add`` +plugin. This is because of the ``'no_create'`` flag we used when defining the +``ipauniqueid`` param. Often times there are LDAP attributes that are +automatically created by the server and therefor should not be supplied as an +option to the `Create` plugin. Often these same attributes shouldn't be +update-able either, in which case you can also supply the ``'no_update'`` flag, +as we did with our ``ipauniqueid`` param. Lastly, you can also use the ``'no_search'`` flag for attributes that shouldn't be search-able (because, for +example, the attribute isn't indexed). + +As with our ``user_add` plugin, we defined neither ``takes_args`` nor +``takes_options`` for our ``user_show`` plugin; instead the `Retrieve` base +class created them for us: + +>>> list(api.Command.user_show.args) +['login'] +>>> list(api.Command.user_show.options) +[] + +As you can see, `Retrieve` plugins take a single argument (the primary key) and +no options. If needed, you can still specify options for your `Retrieve` plugin +with a ``takes_options`` tuple. + +Flags like ``'no_create'`` remove LDAP attributes from those that can be +supplied as *input* to a `Method`, but they don't effect the attributes that can +be returned as *output*. Regardless of what flags have been used, the output +entry (or list of entries) can contain all the attributes defined on the +`Object` plugin (in our case, the above ``user.params``). + +For example, compare ``user.params`` with ``user_add.output_params`` and +``user_show.output_params``: + +>>> list(api.Object.user.params) +['login', 'first', 'last', 'ipauniqueid'] +>>> list(api.Command.user_add.output_params) +['login', 'first', 'last', 'ipauniqueid'] +>>> list(api.Command.user_show.output_params) +['login', 'first', 'last', 'ipauniqueid'] + +Note that the above are all equal. """ +from frontend import Method, Object import backend, frontend, parameters, output -class Create(frontend.Method): +class Create(Method): """ Create a new entry. """ @@ -39,13 +139,15 @@ class Create(frontend.Method): for option in super(Create, self).get_options(): yield option for option in self.obj.params_minus(self.args): + if 'no_create' in option.flags: + continue yield option.clone(attribute=True) if not self.extra_options_first: for option in super(Create, self).get_options(): yield option -class PKQuery(frontend.Method): +class PKQuery(Method): """ Base class for `Retrieve`, `Update`, and `Delete`. """ @@ -75,6 +177,8 @@ class Update(PKQuery): for option in super(Update, self).get_options(): yield option for option in self.obj.params_minus_pk(): + if 'no_update' in option.flags: + continue yield option.clone(attribute=True, required=False, autofill=False) if not self.extra_options_first: for option in super(Update, self).get_options(): @@ -89,7 +193,7 @@ class Delete(PKQuery): has_output = output.standard_delete -class Search(frontend.Method): +class Search(Method): """ Retrieve all entries that match a given search criteria. """ @@ -104,6 +208,8 @@ class Search(frontend.Method): for option in super(Search, self).get_options(): yield option for option in self.obj.params_minus(self.args): + if 'no_search' in option.flags: + continue yield option.clone( attribute=True, query=True, required=False, autofill=False ) |