Bakery

Version 2 (UNSTABLE): cmk.bakery.v2_unstable

Warning

This version of the bakery API is work in progress and not yet stable. It might not even work at all. It is not recommended to use this version in production systems.

However: we do intend to stabilize this API version in the future and release it, so you are encouraged to experiment and give us feedback.

New in this version

This section lists the most important changes you have to be aware of when migrating your plug-in to this API version.

Note that changes are expressed in relation to the API version 1.

Registration is replaced by a discovery approach

This is the main reason for the introduction of this new API version. Plugins are no longer registered during import, but only created and picked up later by the backend. To realize this, we introduced a new class:

BakeryPlugin replacing register.bakery_plugin()

The arguments of these have barely changed (see next paragraph), resulting in easy to automate changes.

To be picked up by the backend, plugins need to be put in the right folder. This is described in the section Plugin location and loading.

Example:

We register the bakery plugin for our ceph integration from the file ~/lib/python3/cmk/plugins/ceph/bakery/ceph.py:

#!/usr/bin/env/python3
...
bakery_plugin_ceph = BakeryPlugin(
    name="ceph",
    parameter_parser=CephConfig.model_validate,
    files_function=get_ceph_files,
)

Changed arguments and validation for bakery plug-ins

We slightly adopted the arguments to the above-mentioned BakeryPlugin class compared to the former registry function. We now favor type annotations over runtime validation. To get slightly easier type annotations, we introduced the parameter_parser argument. It is strongly recommended to use this argument – but if you insist to not use it (maybe for easier migration), you can use the no_op_parser() function.

Changed Plugin and SystemBinary classes

We slightly adopted the arguments to these two artifact types to be slightly more permissive. We allow floats for the number arguments, as this plays more nicely with the values the rulesets provide.

We here also now favor type annotations over runtime validation. Not following the type annotations will result in unspecified behavior.

NOTE: The source argument is now always relative to the plugin families cmk.plugins.<FAMILY>.agent or cmk_addons.plugins.<FAMILY>.agent directory on the Checkmk site. This is a change compared to version 1, where it was relative to the agent source directory.

Removed password_store

We no longer expose the password_store and its (currently not stable) API to the bakery plug-ins. Instead, consumers of a Password form spec element will be passed an instance of a dedicated API class: Secret. Using this, plug-ins can access the secret directly.

class BakeryPlugin(name, parameter_parser, default_parameters, files_function=<function _nothing>, scriptlets_function=<function _nothing>, windows_config_function=<function _nothing>)

Defines a bakery plugin

Instances of this class will only be picked up by Checkmk if their names start with bakery_plugin_.

Parameters:
  • name (str) – Bakery plugin name. A valid plugin name must be a non-empty string consisting only of letters A-z, digits and the underscore.

  • parameter_parser (Callable[[Mapping[str, object]], TypeVar(ConfigType)]) – Function that parses the plugin parameters. It will be passed the preprocessed plugin parameters and can return any python object. The parser parameters will be passed to the other functions.

  • default_parameters (Mapping[str, object] | None) – Default parameters for the plugin. These parameters will be used if no parameters are provided by the user. If they are None and the user has no rule configured, this bakelet will not be called at all. If they are not None, they must be in the format expected by the parameter_parser, and they will be merged with the user-provided parameters (or passed on their own). Choose wisely if the plugin should be deployed or not by default. If you are a Checkmk developer, you might want to align with the product management on this.

  • files_function (Callable[[TypeVar(ConfigType)], Iterable[Plugin | PluginConfig | SystemBinary | SystemConfig]]) – Function that creates file artifacts. It will be passed the plugins configuration as parsed by the parameters_parser and must create artifacts of types Plugin, PluginConfig, SystemConfig, or SystemBinary.

  • scriptlets_function (Callable[[TypeVar(ConfigType)], Iterable[Scriptlet]]) – Function that creates scriptlet artifacts. It will be passed the plugins configuration as parsed by the parameter_parser and must create artifacts of type Scriptlet.

  • windows_config_function (Callable[[TypeVar(ConfigType)], Iterable[WindowsConfigEntry | WindowsGlobalConfigEntry | WindowsSystemConfigEntry | WindowsConfigItems]]) – Function that creates windows config artifacts. It will be passed the plugins configuration as parsed by the parameter_parser and must create artifacts of types WindowsConfigEntry, WindowsGlobalConfigEntry, WindowsSystemConfigEntry, WindowsConfigItems, or WindowsPluginConfig.

class Secret(revealed: str, source: str, id: str)

Represents a configured secret to the bakery plugin

This class aims to reduce the chances of accidentally exposing the secret in crash reports and log messages. However, a bakery plug-in produces configuration files that are deployed to the target system. Therefor the plugin needs access to the actual secret. As a result, we cannot guarantee that bakery plugins will not expose the secret in any way:

Example

This is passed by the backend to the bakery plugin

>>> s = Secret("s3cr3t", "", "")
>>> print(f"This is the secret as string: {s}")
This is the secret as string: 4e738ca5563c06cfd0018299933d58db1dd8bf97f6973dc99bf6cdc64b5550bd
>>> print(f"But we can see the actual value: {s.revealed!r}")
But we can see the actual value: 's3cr3t'

Deviating from what we’d ususally expect from repr, this deliberately does not show the actual value:

>>> s.revealed in repr(s)
False
revealed: str

Alias for field number 0

source: str

Alias for field number 1

id: str

Alias for field number 2

no_op_parser(parameters)

A no-op parser that does nothing and passes the parameters through.

Use this if you insist on not using a parser at all.

Parameters:

parameters (Mapping[str, object]) – The parameters to parse.

Return type:

Mapping[str, object]

class Plugin(*, base_os, source, target=None, interval=None, asynchronous=None, timeout=None, retry_count=None)

File artifact that represents a Checkmk agent plugin

The specified plug-in file will be deployed to the Checkmk agent’s plug-in directory as a callable plugin.

Parameters:
  • base_os (OS) – The target operating system.

  • source (Path) – Path of the plug-in file, relative to the plug-in families cmk.plugins.<FAMILY>.agent or cmk_addons.plugins.<FAMILY>.agent directory on the Checkmk site. This usually consists only of the filename.

  • target (Path | None) – Target path, relative to the plug-in directory within the agent’s file tree on the target system. If omitted, the plug-in will be deployed under it’s relative source path/filename.

  • interval (float | None) – Caching interval in seconds. The plug-in will only be executed by the agent after the caching interval is elapsed.

  • asynchronous (bool | None) – Relevant for Windows Agent. Don’t wait for termination of the plugin’s process if True. An existent interval will always result in asynchronous execution.

  • timeout (float | None) – Relevant for Windows Agent. Maximum waiting time for a plug-in to terminate.

  • retry_count (float | None) – Relevant for Windows Agent. Maximum number of retried executions after a failed plug-in execution.

class SystemBinary(*, base_os, source, target=None)

File artifact that represents a script/program that should be deployed on the hosts.

Under UNIX, the file will be deployed to the binary directory (by default, ‘/usr/bin’, configurable in WATO).

Under Windows, the file will be deployed to the ‘bin’-folder at the agent’s installation directory.

Parameters:
  • base_os (OS) – The target operating system.

  • source (Path) – Path of the file, relative to the plugin families cmk.plugins.<FAMILY>.agent or cmk_addons.plugins.<FAMILY>.agent directory on the Checkmk site.

  • target (Path | None) – Target path, relative to the binary directory on the target system. If omitted, the plug-in will be deployed under it’s relative source path/filename.

class PluginConfig(*, base_os, lines, target, include_header=False)

File artifact that represents a generated config file for a plugin.

The resulting configuration file will be placed to the agent’s config directory (by default, ‘/etc/check_mk’, configurable in WATO) and is meant to be read by the corresponding plugin. It’s content is unrestricted (apart from the fact that it must be passed as a list of ‘str’s), so it’s up to the consuming plug-in to process it correctly.

Parameters:
  • base_os (OS) – The target operating system.

  • lines (Iterable[str]) – Lines of text that will be printed to the resulting file.

  • target (Path) – Path of the resulting configuration file, relative to the agent’s config directory. This usually consists only of the filename.

  • include_header (bool) –

    If True, the following header will be prepended at the start of the resulting configuration file:

    # Created by Check_MK Agent Bakery.

    # This file is managed via WATO, do not edit manually or you

    # lose your changes next time when you update the agent.

class SystemConfig(*, base_os, lines, target, include_header=False)

File artifact that represents a generated configuration file for the target system.

This is only relevant for UNIX systems.

The resulting configuration file will be placed under ‘/etc’ on the target system. This can be used, for example, to deploy a systemd service or to deploy a config file to a service’s <service>.d directory.

Parameters:
  • base_os (OS) – The target operating system.

  • lines (list[str]) – Lines of text that will be printed to the resulting file.

  • target (Path) – Path of the resulting configuration file, relative to ‘/etc’.

  • include_header (bool) –

    If True, the following header will be prepended at the start of the resulting configuration file:

    # Created by Check_MK Agent Bakery.

    # This file is managed via WATO, do not edit manually or you

    # lose your changes next time when you update the agent.

class OS(*values)

Describes an operating system in the context of the Bakery API.

Members: LINUX, SOLARIS, AIX, WINDOWS

class DebStep(*values)

Describes a step in the processing of a DEB package.

For details refer to Maintainer Scripts.

Members: PREINST, POSTINST, PRERM, POSTRM

class RpmStep(*values)

Describes a step in the processing of a RPM package.

For details refer to Scriptlets.

Members: PRE, POST, PREUN, POSTUN, PRETRANS, POSTTRANS

class SolStep(*values)

Describes a step in the processing of a Solaris PKG package.

For details refer to Writing Procedure Scripts.

Members: PREINSTALL, POSTINSTALL, PREREMOVE, POSTREMOVE

class Scriptlet(*, step, lines)

Represents a ‘Scriptlet’ (RPM), ‘Maintainer script’ (DEB) or ‘Installation script’ (Solaris PKG)

Describes a shell script that should be executed at a specific time during a package transition, i.e. package installation, update, or uninstallation. For a detailed explanation of the meaning and the execution time of the steps/scripts, please refer to the documentation of the three packaging systems.

Parameters:
  • step (DebStep | RpmStep | SolStep) – Takes any Enum of the types ‘RpmStep’, ‘DebStep’, ‘SolStep’, e.g. RpmStep.POST for a scriptlet that should be executed right after package installation.

  • lines (list[str]) – Lines of text that the scriptlet consists of. Don’t add a shebang line - The executing shell depends on the packaging system. Usually, this will be the Bourne shell (sh), so the scriptlets should be compatible to that.

class WindowsConfigEntry(*, path, content)

Config Entry for the Windows Agent yaml file (check_mk.install.yml)

It’s up to the consuming plug-in to read the config entry correctly from the yaml file. However, unlike the approach via PluginConfig, config entries described here will be accessible consistently via the python yaml module.

The logical structure of the yaml tree has up to two levels. It is divided into sections, that are again divided into subsections.

A config entry can be inserted to a section or a subsection.

Parameters:
  • path (list[str]) – The path to the entry consists either of [‘section’, ‘subsection’, ‘name’] or [‘section’, ‘name’], i.e. the resulting list must contain 2 or 3 entries. If the path already exists in the yaml structure, it will be overwritten.

  • content (int | str | bool | dict | list) – The actual content of the config entry. Allowed types are int, str, bool, dict, list. Must not contain any complex data types or custom classes. (Must be serializable with yaml.safe_dump)

class WindowsConfigItems(*, path, content)

List of entries for the Windows Agent yaml file (check_mk.install.yml)

This artifact describes a list of entries that is identified by a path (section,[ subsection,] name). In contrast to a WindowsConfigEntry, the given list will be merged to an already existing list.

Parameters:
  • path (list[str]) – The path to the entry consists either of [‘section’, ‘subsection’, ‘name’] or [‘section’, ‘name’], i.e. the resulting list must contain 2 or 3 entries. If the path already exists in the yaml structure, it will be overwritten.

  • content (list[int | str | bool | dict | list]) – The list that should be added or merged to the given path. Allowed list entries are the same as for WindowsConfigEntry content.

class WindowsGlobalConfigEntry(*, name, content)

Shortcut for WindowsConfigEntry(path=[‘global’, name], content=content)

For details about the ‘global’ section and it’s meaning, please refer to the Windows Agent documentation.

Parameters:
  • name (str) – The name part of the [‘global’,name] path

  • content (int | str | bool | dict | list) – The content, according to the WindowsConfigEntry requirements.

class WindowsSystemConfigEntry(*, name, content)

Shortcut for WindowsConfigEntry(path=[‘system’, name], content=content)

For details about the ‘system’ section and it’s meaning, please refer to the Windows Agent documentation.

Parameters:
  • name (str) – The name part of the [‘global’,name] path

  • content (int | str | bool | dict | list) – The content, according to the WindowsConfigEntry requirements.

entry_point_prefixes()

Return the types of plug-ins and their respective prefixes that can be discovered by Checkmk.

These types can be used to create plug-ins that can be discovered by Checkmk. To be discovered, the plug-in must be of one of the types returned by this function and its name must start with the corresponding prefix.

Return type:

Mapping[type[BakeryPlugin], str]

Example:

>>> for plugin_type, prefix in entry_point_prefixes().items():
...     print(f'{prefix}... = {plugin_type.__name__}(...)')
bakery_plugin_... = BakeryPlugin(...)

Version 1: cmk.base.plugins.bakery.bakery_api.v1

bakery_api.v1

class Plugin(*, base_os, source, target=None, interval=None, asynchronous=None, timeout=None, retry_count=None)

Bases: object

File artifact that represents a Checkmk agent plugin

The specified plug-in file will be deployed to the Checkmk agent’s plug-in directory as a callable plugin.

Parameters:
  • base_os (OS) – The target operating system.

  • source (Path) – Path of the plug-in file, relative to the plug-in source directory on the Checkmk site. This usually consists only of the filename.

  • target (Path | None) – Target path, relative to the plug-in directory within the agent’s file tree on the target system. If omitted, the plug-in will be deployed under it’s relative source path/filename.

  • interval (int | None) – Caching interval in seconds. The plug-in will only be executed by the agent after the caching interval is elapsed.

  • asynchronous (bool | None) – Relevant for Windows Agent. Don’t wait for termination of the plugin’s process if True. An existent interval will always result in asynchronous execution.

  • timeout (int | None) – Relevant for Windows Agent. Maximum waiting time for a plug-in to terminate.

  • retry_count (int | None) – Relevant for Windows Agent. Maximum number of retried executions after a failed plug-in execution.

class PluginConfig(*, base_os, lines, target, include_header=False)

Bases: object

File artifact that represents a generated config file for a plugin.

The resulting configuration file will be placed to the agent’s config directory (by default, ‘/etc/check_mk’, configurable in WATO) and is meant to be read by the corresponding plugin. It’s content is unrestricted (apart from the fact that it must be passed as a list of ‘str’s), so it’s up to the consuming plug-in to process it correctly.

Parameters:
  • base_os (OS) – The target operating system.

  • lines (Iterable[str]) – Lines of text that will be printed to the resulting file.

  • target (Path) – Path of the resulting configuration file, relative to the agent’s config directory. This usually consists only of the filename.

  • include_header (bool) –

    If True, the following header will be prepended at the start of the resulting configuration file:

    # Created by Check_MK Agent Bakery.

    # This file is managed via WATO, do not edit manually or you

    # lose your changes next time when you update the agent.

class Scriptlet(*, step, lines)

Bases: object

Represents a ‘Scriptlet’ (RPM), ‘Maintainer script’ (DEB) or ‘Installation script’ (Solaris PKG)

Describes a shell script that should be executed at a specific time during a package transition, i.e. package installation, update, or uninstallation. For a detailed explanation of the meaning and the execution time of the steps/scripts, please refer to the documentation of the three packaging systems.

Parameters:
  • step (DebStep | RpmStep | SolStep) – Takes any Enum of the types ‘RpmStep’, ‘DebStep’, ‘SolStep’, e.g. RpmStep.POST for a scriptlet that should be executed right after package installation.

  • lines (list[str]) – Lines of text that the scriptlet consists of. Don’t add a shebang line - The executing shell depends on the packaging system. Usually, this will be the Bourne shell (sh), so the scriptlets should be compatible to that.

class SystemBinary(*, base_os, source, target=None)

Bases: object

File artifact that represents a script/program that should be deployed on the hosts.

Under UNIX, the file will be deployed to the binary directory (by default, ‘/usr/bin’, configurable in WATO).

Under Windows, the file will be deployed to the ‘bin’-folder at the agent’s installation directory.

Parameters:
  • base_os (OS) – The target operating system.

  • source (Path) – Path of the file, relative to the agent source directory on the Checkmk site.

  • target (Path | None) – Target path, relative to the binart directory on the target system. If omitted, the plug-in will be deployed under it’s relative source path/filename.

class SystemConfig(*, base_os, lines, target, include_header=False)

Bases: object

File artifact that represents a generated configuration file for the target system.

This is only relevant for UNIX systems.

The resulting configuration file will be placed under ‘/etc’ on the target system. This can be used, for example, to deploy a systemd service or to deploy a config file to a service’s <service>.d directory.

Parameters:
  • base_os (OS) – The target operating system.

  • lines (list[str]) – Lines of text that will be printed to the resulting file.

  • target (Path) – Path of the resulting configuration file, relative to ‘/etc’.

  • include_header (bool) –

    If True, the following header will be prepended at the start of the resulting configuration file:

    # Created by Check_MK Agent Bakery.

    # This file is managed via WATO, do not edit manually or you

    # lose your changes next time when you update the agent.

class WindowsConfigEntry(*, path, content)

Bases: object

Config Entry for the Windows Agent yaml file (check_mk.install.yml)

It’s up to the consuming plug-in to read the config entry correctly from the yaml file. However, unlike the approach via PluginConfig, config entries described here will be accessible consistently via the python yaml module.

The logical structure of the yaml tree has up to two levels. It is divided into sections, that are again divided into subsections.

A config entry can be inserted to a section or a subsection.

Parameters:
  • path (list[str]) – The path to the entry consists either of [‘section’, ‘subsection’, ‘name’] or [‘section’, ‘name’], i.e. the resulting list must contain 2 or 3 entries. If the path already exists in the yaml structure, it will be overwritten.

  • content (int | str | bool | dict | list) – The actual content of the config entry. Allowed types are int, str, bool, dict, list. Must not contain any complex data types or custom classes. (Must be serializable with yaml.safe_dump)

class WindowsConfigItems(*, path, content)

Bases: object

List of entries for the Windows Agent yaml file (check_mk.install.yml)

This artifact describes a list of entries that is identified by a path (section,[ subsection,] name). In contrast to a WindowsConfigEntry, the given list will be merged to an already existing list.

Parameters:
  • path (list[str]) – The path to the entry consists either of [‘section’, ‘subsection’, ‘name’] or [‘section’, ‘name’], i.e. the resulting list must contain 2 or 3 entries. If the path already exists in the yaml structure, it will be overwritten.

  • content (list[int | str | bool | dict | list]) – The list that should be added or merged to the given path. Allowed list entries are the same as for WindowsConfigEntry content.

class WindowsGlobalConfigEntry(*, name, content)

Bases: object

Shortcut for WindowsConfigEntry(path=[‘global’, name], content=content)

For details about the ‘global’ section and it’s meaning, please refer to the Windows Agent documentation.

Parameters:
  • name (str) – The name part of the [‘global’,name] path

  • content (int | str | bool | dict | list) – The content, according to the WindowsConfigEntry requirements.

class WindowsSystemConfigEntry(*, name, content)

Bases: object

Shortcut for WindowsConfigEntry(path=[‘system’, name], content=content)

For details about the ‘system’ section and it’s meaning, please refer to the Windows Agent documentation.

Parameters:
  • name (str) – The name part of the [‘global’,name] path

  • content (int | str | bool | dict | list) – The content, according to the WindowsConfigEntry requirements.

class DebStep(*values)

Bases: StrEnum

Describes a step in the processing of a DEB package.

For details refer to Maintainer Scripts.

Members: PREINST, POSTINST, PRERM, POSTRM

class OS(*values)

Bases: Enum

Describes an operating system in the context of the Bakery API.

Members: LINUX, SOLARIS, AIX, WINDOWS

class RpmStep(*values)

Bases: StrEnum

Describes a step in the processing of a RPM package.

For details refer to Scriptlets.

Members: PRE, POST, PREUN, POSTUN, PRETRANS, POSTTRANS

class SolStep(*values)

Bases: StrEnum

Describes a step in the processing of a Solaris PKG package.

For details refer to Writing Procedure Scripts.

Members: PREINSTALL, POSTINSTALL, PREREMOVE, POSTREMOVE

class BakeryPlugin(name, files_function, scriptlets_function, windows_config_function)

Bases: NamedTuple

name: BakeryPluginName

Alias for field number 0

files_function: Callable[[...], Iterator[Plugin | SystemBinary | PluginConfig | SystemConfig]]

Alias for field number 1

scriptlets_function: Callable[[...], Iterator[Scriptlet]]

Alias for field number 2

windows_config_function: Callable[[...], Iterator[WindowsConfigEntry | WindowsConfigItems | WindowsGlobalConfigEntry | WindowsSystemConfigEntry]]

Alias for field number 3

bakery_api.v1.register

bakery_plugin(*, name: str, files_function: FilesFunction | None = None, scriptlets_function: ScriptletsFunction | None = None, windows_config_function: WindowsConfigFunction | None = None) None

Register a Bakery Plugin (Bakelet) to Checkmk

This registration function accepts a plug-in name (mandatory) and up to three generator functions that may yield different types of artifacts. The generator functions will be called with keyword-arguments ‘conf’ and/or ‘aghash’ while processing the bakery plug-in (Callbacks), thus the specific call depends on the argument names of the provided functions. For keyword-arg ‘conf’, the corresponding WATO configuration will be provided. For keyword-arg ‘aghash’, the configuration hash of the resulting agent package will be provided. Unused arguments can be omitted in the function’s signatures.

Parameters:
  • name – The name of the agent plug-in to be processed. It must be unique, and match the name of the corresponding WATO rule. It may only contain ascii letters (A-Z, a-z), digits (0-9), and underscores (_).

  • files_function – Generator function that yields file artifacts. Allowed function argument is ‘conf’. Yielded artifacts must must be of types ‘Plugin’, ‘PluginConfig’, ‘SystemConfig’, or ‘SystemBinary’.

  • scriptlets_function – Generator function that yields scriptlet artifacts. Allowed function arguments are ‘conf’ and ‘aghash’. Yielded artifacts must be of type ‘Scriptlet’.

  • windows_config_function – generator function that yields windows config artifacts. Allowed function arguments are ‘conf’ and ‘aghash’. Yielded artifacts must be of types ‘WindowsConfigEntry’, ‘WindowsGlobalConigEntry’, ‘WindowsSystemConfigEntry’, ‘WindowsConfigItems’, or ‘WindowsPluginConfig’.