[PATCH] docs: Document how to write a plugin

Mathieu Bridon bochecha at daitauha.fr
Fri Jul 10 22:33:48 UTC 2015


---

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



More information about the buildsys mailing list