On Fri, Jul 10, 2015 at 5:33 PM, Mathieu Bridon <[email protected]> wrote: > --- > > Koji supports different types of plugins. > > This commit documents the 3 types that I know of, but I have absolutely > no idea if there are others. > > docs/Writing_a_plugin.md | 153 > +++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 153 insertions(+) > create mode 100644 docs/Writing_a_plugin.md > > diff --git a/docs/Writing_a_plugin.md b/docs/Writing_a_plugin.md > new file mode 100644 > index 0000000..36cddd9 > --- /dev/null > +++ b/docs/Writing_a_plugin.md > @@ -0,0 +1,153 @@ > +# Writing Koji plugins > + > +Depending on what you are trying to do, there are different ways to write a > +Koji plugin. > + > +Each is described in this file, by use case. > + > +## Adding new task types > + > +Koji can do several things, for example build RPMs, or live CDs. Those are > +types of tasks which Koji knows about. > + > +If you need to do something which Koji does not know yet how to do, you could > +create a Koji Builder plugin. > + > +Such a plugin would minimally look like this: > + > + from koji.tasks import BaseTaskHandler > + > + class MyTask(BaseTaskHandler): > + Methods = ['mytask'] > + _taskWeight = 2.0 > + > + def handler(self, arg1, arg2, kwarg1=None): > + self.logger.debug("Running my task...") > + > + # Here is where you actually do something > + > +A few explanations on what goes on here: > + > +* Your task needs to inherit from `koji.tasks.BaseTaskHandler` > +* Your task must have a `Methods` attribute, which is a list of the method > + names your task can handle. > +* You can specify the weight of your task with the `_taskWeight` attribute. > + The more intensive (CPU, IO, ...) your task is, the higher this number > + should be. > +* The task object has a `logger` attribute, which is a Python logger with the > + usual `debug`, `info`, `warning` and `error` methods. The messages you send > + with it will end up in the Koji Builder logs (`kojid.log`) > +* Your task must have a `handler()` method. That is the method Koji will call > + to run your task. It is the method that should actually do what you need. > It > + can have as many positional and named arguments as you want. > + > +Save your plugin as e.g `mytask.py`, then install it in the Koji Builder > +plugins folder: `/usr/lib/koji-builder-plugins/` > + > +Finally, edit the Koji Builder config file, `/etc/kojid/kojid.conf`: > + > + # A space-separated list of plugins to enable > + plugins = mytask > + > +Restart the Koji Builder service, and your plugin will be enabled. > + > +You can try running a task from your new task type with the command-line: > + > + $ koji make-task mytask arg1 arg2 kwarg1 > + > +## Exporting new API methods over XMLRPC > + > +Koji clients talk to the Koji Hub via an XMLRPC API. > + > +It is sometimes desirable to add to that API, so that clients can request > +things Koji does not expose right now. > + > +Such a plugin would minimally look like this: > + > + def mymethod(arg1, arg2, kwarg1=None): > + # Here is where you actually do something > + > + mymethod.exported = True > + > +A few explanations on what goes on here: > + > +* Your plugin is just a method, with whatever positional and/or named > + arguments you need. > +* You must export your method by setting its `exported` attribute to `True` > +* The `context.session.assertPerm()` is how you ensure that the > + > +Save your plugin as e.g `mymethod.py`, then install it in the Koji Hub > plugins > +folder: `/usr/lib/koji-hub-plugins/` > + > +Finally, edit the Koji Hub config file, `/etc/koji-hub/hub.conf`: > + > + # A space-separated list of plugins to enable > + Plugins = mymethod > + > +Restart the Koji Hub service, and your plugin will be enabled. > + > +You can try calling the new XMLRPC API with the Python client library: > + > + >>> import koji > + >>> session = koji.ClientSession("http://koji/example.org/kojihub") > + >>> session.mymethod(arg1, arg2, kwarg1='some value') > + > +### Ensuring the user has the required permissions > + > +If you want your new XMLRPC API to require specific permissions from the > user, > +all you need to do is add the following to your method: > + > + from koji.context import context > + > + def mymethod(arg1, arg2, kwarg1=None): > + context.session.assertPerm("admin") > + > + # Here is where you actually do something > + > + mymethod.exported = True > + > +In the example above, Koji will ensure that the user is an administrator. You > +could of course create your own permission, and check for that. > + > +## Running code automatically triggered on events > + > +You might want to run something automatically when something else happens in > +Koji. > + > +A typical example is to automatically sign a package right after a build > +finished. Another would be to send a notification to a message bus after any > +kind of event. > + > +This can be achieved with a plugin, which would look minimally as follows: > + > + from koji.plugin import callback > + > + @callback('preTag', 'postTag') > + def mycallback(cbtype, tag, build, user, force=False): > + # Here is where you actually do something > + > +A few explanations on what goes on here: > + > +* The `@callback` decorator allows you to declare which events should trigger > + your function. You can pass as many as you want. For a list of supported > + events, see `koji/plugins.py`. > +* The arguments of the function depend on the event you subscribed to. As a > + result, you need to know how it will be called by Koji. You probably should > + use `*kwargs` to be safe. You can see how callbacks are called in the > + `hub/kojihub.py` file, search for calls of the `run_callbacks` function. > + > +Save your plugin as e.g `mycallback.py`, then install it in the Koji Hub > +plugins folder: `/usr/lib/koji-hub-plugins` > + > +Finally, edit the Koji Hub config file, `/etc/koji-hub/hub.conf`: > + > + # A space-separated list of plugins to enable > + Plugins = mycallback > + > +Restart the Koji Hub service, and your plugin will be enabled. > + > +You can try triggering your callback plugin with the command-line. For > +example, if you registered a callback for the `postTag` event, try tagging a > +build: > + > + $ koji tag-build mytag mypkg-1.0-1 > -- > 2.4.3 >
Can I +1 more than once? ;) But no, seriously this is amazing. Thank you so much for writing this. For whatever it's worth: +1 -AdamM > -- > buildsys mailing list > [email protected] > https://admin.fedoraproject.org/mailman/listinfo/buildsys -- buildsys mailing list [email protected] https://admin.fedoraproject.org/mailman/listinfo/buildsys
