---
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
On Fri, Jul 10, 2015 at 5:33 PM, Mathieu Bridon bochecha@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@lists.fedoraproject.org https://admin.fedoraproject.org/mailman/listinfo/buildsys
Really nice to see this documented.
+1 ack
On Fri, Jul 10, 2015 at 5:36 PM, Adam Miller maxamillion@fedoraproject.org wrote:
On Fri, Jul 10, 2015 at 5:33 PM, Mathieu Bridon bochecha@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@lists.fedoraproject.org https://admin.fedoraproject.org/mailman/listinfo/buildsys
-- buildsys mailing list buildsys@lists.fedoraproject.org https://admin.fedoraproject.org/mailman/listinfo/buildsys
buildsys@lists.fedoraproject.org