How to write Koji plugins — Koji 1.16.0 documentation (2024)

Writing Koji plugins

Depending on what you are trying to do, there are different ways towrite 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. Thoseare types of tasks which Koji knows about.

If you need to do something which Koji does not know yet how to do, youcould create a Koji Builder plugin.

Such a plugin would minimally look like this:

from koji.tasks import BaseTaskHandlerclass 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 themethod names your task can handle.

  • You can specify the weight of your task with the _taskWeightattribute. The more intensive (CPU, IO, …) your task is, the higherthis number should be.

  • The task object has a logger attribute, which is a Python loggerwith the usual debug, info, warning and errormethods. The messages you send with it will end up in the KojiBuilder logs (kojid.log)

  • Your task must have a handler() method. That is the method Kojiwill call to run your task. It is the method that should actually dowhat you need. It can have as many positional and named arguments asyou want.

Save your plugin as e.g mytask.py, then install it in the KojiBuilder plugins folder: /usr/lib/koji-builder-plugins/

Finally, edit the Koji Builder config file, /etc/kojid/kojid.conf:

Restart the Koji Builder service, and your plugin will be enabled.

You can try running a task from your new task type with thecommand-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 canrequest 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 somethingmymethod.exported = True

A few explanations on what goes on here:

  • Your plugin is just a method, with whatever positional and/or namedarguments you need.

  • You must export your method by setting its exported attribute toTrue

  • The context.session.assertPerm() is how you ensure that the

Save your plugin as e.g mymethod.py, then install it in the Koji Hubplugins 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 enablePlugins = 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 theuser, all you need to do is add the following to your method:

from koji.context import contextdef mymethod(arg1, arg2, kwarg1=None): context.session.assertPerm("admin") # Here is where you actually do somethingmymethod.exported = True

In the example above, Koji will ensure that the user is anadministrator. You could of course create your own permission, and checkfor that.

Running code automatically triggered on events

You might want to run something automatically when something elsehappens in Koji.

A typical example is to automatically sign a package right after a buildfinished. Another would be to send a notification to a message bus afterany kind of event.

This can be achieved with a plugin, which would look minimally asfollows:

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 shouldtrigger your function. You can pass as many as you want. For a listof 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. Youprobably should use *kwargs to be safe. You can see how callbacksare called in the hub/kojihub.py file, search for calls of therun_callbacks function.

Save your plugin as e.g mycallback.py, then install it in the KojiHub 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 enablePlugins = mycallback

Restart the Koji Hub service, and your plugin will be enabled.

You can try triggering your callback plugin with the command-line. Forexample, if you registered a callback for the postTag event, trytagging a build:

$ koji tag-build mytag mypkg-1.0-1

New command for CLI

When you add new XMLRPC call or just wanted to do some more complicatedthings with API, you can benefit from writing a new command for CLI.

Most simple command would look like this:

from koji.plugin import export_cli@export_clidef anon_handle_echo(options, session, args): "[info] Print arguments" usage = _("usage: %prog echo <message>") parser = OptionParser(usage=usage) (opts, args) = parser.parse_args(args) print(args[0])

@export_cli is a decorator which registers a new command. The commandname is derived from name of the function. The function name must start witheither anon_handle_ or handle_. The rest of the name becomes the name ofthe command.

In the first case, the command will not automaticallyauthenticate with the hub (though the user can still overridethis behavior with –force-auth option). In the second case, the commandwill perform authentication by default (this too can be overridden by theuser with the –noauth option).

The example above is very simplistic. We recommend that developers alsoexamine the actual calls included in Koji. The built in commands live inkoji_cli.commands and our standard cli plugins live in plugins/cli.

Koji provides some important functions via in the client cli library(koji_cli.lib) for use by cli commands. Some notable examples are:

  • activate_session(session, options) - It is needed to authenticateagainst hub. Both parameters are same as those passed to handler.

  • watch_tasks(session, tasklist, quiet=False, poll_interval=60) - It isthe same function used e.g. in build command for waiting for spawnedtasks.

  • list_task_output_all_volumes(session, task_id) - wrapper function forlistTaskOutput with different versions of hub.

Final command has to be saved in python system-wide library path - e.g. in/usr/lib/python3.4/site-packages/koji_cli_plugins. Filename doesn’t matteras all files in this directory are searched for @export_cli macros. Note,that python 3 variant of CLI is looking to different directory than python 2one.

CLI plugins structure will be extended (made configurable and allowing morethan just adding commands - e.g. own authentication methods, etc.) in future.

Pull requests

These plugins have to be written in python 2.6+/3.x compatible way. We areusing six library to support this, so we will also prefer pull requestswritten this way. CLI (and client library) is meant to be fully compatiblewith python 3 from koji 1.13.

Tests are also recommended for PR. For example one seetests/test_plugins/test_runroot_cli.py.

How to write Koji plugins — Koji 1.16.0 documentation (2024)

References

Top Articles
Latest Posts
Recommended Articles
Article information

Author: Chrissy Homenick

Last Updated:

Views: 5333

Rating: 4.3 / 5 (54 voted)

Reviews: 85% of readers found this page helpful

Author information

Name: Chrissy Homenick

Birthday: 2001-10-22

Address: 611 Kuhn Oval, Feltonbury, NY 02783-3818

Phone: +96619177651654

Job: Mining Representative

Hobby: amateur radio, Sculling, Knife making, Gardening, Watching movies, Gunsmithing, Video gaming

Introduction: My name is Chrissy Homenick, I am a tender, funny, determined, tender, glorious, fancy, enthusiastic person who loves writing and wants to share my knowledge and understanding with you.