Events

Events are describing the cause (or impulse) for the pipeline to start and based on the event all the actions taken by the pipeline are taken. Some would use instead of ‘event’ term ‘trigger’ but we’re trying to avoid such term as it can be used as both verb (to trigger the pipeline) and subjet (the trigger started the pipeline).

One of the main functions of the events is to provide name of branch which contains testplans that should be executed for such event instance.

Events may also provide additional information related to the event instance where such information are taken from external sources. Example of such functionality could be for example detecting product (and its version) for a Koji build that’s to be processed by the pipeline or information about packages that are product of the build. Another example would be additional information about compose such as label or compose type. These additional information may or may not be used by the event itself when deciding the name of the testplans branch.

The event that comes to the pipeline is json encoded mapping (dict) with 1 mandatory item “type” and optionally additional items which provide additional information about the nature of the event or are used as overrides. Resulting in json like:

{
  'type' : 'explosion',
  'other' : {
    'items' : ['a', 'b', 'c'],
    'where' : 'underground'
  }
}

In this case, the EventFactory looks for a class associated to the ‘explosion’ event type and crates its object passing the type as first argument and all other items as kwargs based on which corresponding event structures are created (described below).

To define Event responsible for handling ‘explosion’ event type which additionally provides information about exploded items following code would be used:

@libpermian.events.factory.register('explosion')
class ExplosionEvent(libpermian.events.base.Event):
    pass

In case of providing the example explosion event to the pipeline as the impulse for pipeline execution, the Pipeline would do something similar:

from libpermian.events.factory import EventFactory

branch_format = '{where}' # taken from settings
event_string = '''{
  "type" : "explosion",
  "other" : {
    "items" : ["a", "b", "c"]
  }
}'''
event = EventFactory.make(settings, event_string)
branch = event.format_branch_spec(branch_format)
# pipeline would clone the git repository fetching the branch and proceed with next steps (passing the event along with tplib.Library and settings for the execution)

The event can also hold additional structures (like “other” shown above) which are python objects created based on the content of the item which would be:

{
  'items' : ['a', 'b', 'c'],
  'where' : 'underground'
}

in case of:

{
  'type' : 'explosion',
  'other' : {
    'items' : ['a', 'b', 'c'],
    'where' : 'underground'
  }
}

The “other” structure can be accessed like regular object attribute using dot operator like: event.other. The structure is created by :py:method:`EventStructuresFactory.make` method which finds class associated to the name (“other”) and passes the content of the dict as kwargs to the event structure class constructor.

The event structure classes are ordinary python classes and the only special interfaces are __init__ (where the event specification string structure fields are defined by the arguments including mandatory fields by mandatory arguments) and special to_* methods and from_* classmethods.

The to_* methods provide conversion mechanism (which is not provided by python compared to e.g. C++) from one structure type to another. For example, koji_build event structure could provide to_compose method which would return new python object associated to “compose” event structure type based on the koji_build structure effectively providing information which compose is related to the koji build.

The from_* class methods provides conversion mechanism the other way allowing to construct the desired structure based on some other already existing structure. It has to be class method as there’s the instance of the desired type doesn’t exist yet.

Both to_* and from_* can return NotImplemented instead of new object signalling that for some reason, they cannot provide instance of the desired type for whatever reason and other conversion methods are attempted (trying to create the instance from different structure).

In case when the event.some_structure needs the conversion and no to_* or from_* method provides instance None value is provided so that expressions like event.some_structure.value can be used in jinja expressions without raising exception when some_structure is not available.

Base

class libpermian.events.base.Event(settings, event_type, **event_structures)

Base class of event which stores its type, event structures (automatically provides converted event structures) and decides which testplans and caserunconfigurations will be executed based on the event.

This base class can be directly used just by providing settings, event type and optionally definitions of event_structures which are constructed using EventStructuresFactory. Such created event uses default selection of testplans with testcases and provides only the provided event structures (along with possibly automatically converted event structures).

When defining new event type, one should create a new child class inheriting this class providing additional methods and/or properties.

property additional_requrements_data

Event can provide additional requrements. Returns python dicts, as if they were tplib files read by yaml.safe_load.

Returns:

list of requrements data

Return type:

tuple

property additional_testcases_data

Event can provide additional testcases. Returns python dicts, as if they were tplib files read by yaml.safe_load.

Returns:

list of testcases data

Return type:

tuple

property additional_testplans_data

Event can provide additional testplans. Returns python dicts, as if they were tplib files read by yaml.safe_load.

Returns:

list of testplan data

Return type:

tuple

filter_testPlans(library)

Filters testplan from library based on: - event type and testplan.artifact_type - testplan execute_on filter

Parameters:

library (tplib.Library) – pipeline library

Returns:

Filtered testplans

Return type:

list of tplib.TestPlan

format_branch_spec(fmt)
generate_caseRunConfigurations(library)

Generates caseRunConfigurations for testcases in library relevant to this event

Parameters:

library (tplib.Library) – Library

Returns:

CaseRunConfigurations

Return type:

CaseRunConfigurationsList

handles_testplan_artifact_type(artifact_type)

Decide if this event is relevant to the provided artifact_type (which is found in test plan).

libpermian.events.base.payload_override(payload_name)

Built-in

class libpermian.events.builtin.UnknownEvent(settings, event_type, **kwargs)

Factory

class libpermian.events.factory.EventFactory

The EventFactory provides mechanisms for registering event classes (:py:method:`EventFactory.register`) and creating event instances based on event specification strings (:py:method:`EventFactory.make`).

The event specification string is json encoded dict which can be used outside of the pipeline and provides all information required for construction of event instance which is used by the pipeline on numerous occasions such as when selecting test plans for execution, in workflows to get information about the tested item and in the reportsenders to pair the report with tested product and version.

DEFAULT_TYPE

alias of UnknownEvent

EVENT_TYPES = {}
classmethod get_class(event_type)

Get event class which covers provided event_type. A class is covering the provided event_type if it matches exactly the event_type or if it contains the same parts using dot notation (part1.part2.part3) at the beginning.

For example if following event types are registered:

  • how.do.you.do

  • how.do

  • how

Following requests would provide following classes:

  • get_class(‘how.do.you.do’) => how.do.you.do

  • get_class(‘how.do.you.cook’) => how.do

  • get_class(‘how.do’) => how.do

  • get_class(‘how.are.you’) => how

If no corresponding class can be found, default class (registered with None) is returned.

Parameters:

event_type

Returns:

Return type:

classmethod make(settings, data)

Create new Event instance based on provided event specification which can be either json encoded event specification string or directly provided dict (which would be decoded from the event specification string).

The event specification is a dict containing type and optionally (depending on corresponding event class) event structures. Example of event specification string:

{"type": "toy.constructed",
 "toy" : {"name": "doll",
          "color": "pink"},
 "factory": {"location": "North Pole"}
}

In this example, the event type is “toy.constructed” which can be handled by event classes associated to either “toy.constructed” or “toy” (in this order) and contains 2 structures “toy” and “factory” which are passed to the event class constructor as kwargs.

Parameters:
  • settings (libpermian.settings.Settings) – Settings that are passed to events and their event structures.

  • data (str or dict) – Event specification string (json) or the decoded dict value of event specification.

Returns:

Return type:

libpermian.events.base.Event

classmethod register(event_type, event_class=None)

Associate the event_class to the event_type so that the class can be instantialized by the :py:method:`EventFactory.make` classmethod and the class can be referenced by dot notation in event specification string. For more details, see :py:method:`EventFactory.get_class`.

This classmethod can be used either directly:

EventFactory.register('some_event', SomeClass)

or indirectly:

EventFactory.register(‘some_event’)(SomeClass)

or as a class decorator:

EventFactory.register('some_event')
class SomeClass(Event):
    ..
Parameters:
  • event_type (str) – String representation of the event using dot notation.

  • event_class (libpermian.events.base.Event, not used when used as class decorator) – Class to be associated to the event type.

Returns:

decorator when event_class is not provided, otherwise the registered class