[PATCH] docs: Document how to write a plugin

Jon jdisnard at gmail.com
Sat Jul 11 03:59:55 UTC 2015


Really nice to see this documented.

+1 ack


On Fri, Jul 10, 2015 at 5:36 PM, Adam Miller <maxamillion at fedoraproject.org>
wrote:

> On Fri, Jul 10, 2015 at 5:33 PM, Mathieu Bridon <bochecha at daitauha.fr>
> 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
> > buildsys at lists.fedoraproject.org
> > https://admin.fedoraproject.org/mailman/listinfo/buildsys
> --
> buildsys mailing list
> buildsys at lists.fedoraproject.org
> https://admin.fedoraproject.org/mailman/listinfo/buildsys
>



-- 

-Jon Disnard
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.fedoraproject.org/pipermail/buildsys/attachments/20150710/dbd40147/attachment.html>


More information about the buildsys mailing list