This is a machine translation based on the English version of the article. It might or might not have already been subject to text preparation. If you find errors, please file a GitHub issue that states the paragraph that has to be improved. |
1. 概要
商業版では、ベーカリー API を使用して、エージェントベーカリーからのエージェントパッケージの機能を含む、独自のいわゆるベーカリープラグインを作成することができます。 ほとんどの場合、これらの機能は、Checkmk エージェントによって実行される追加のスクリプトであるエージェントプラグインと、プラグインの設定ファイルです。 ただし、ファイルを含める、パッケージスクリプトレット(RPM、DEB、Solaris PKG パッケージ形式用)を実行する、または Windows エージェント用の特定の設定エントリ(YAML)を定義することでマッピングできる場合は、パッケージマネージャの機能にも影響を与える可能性があります。 これらの「成果物」はすべて、統一された構文を使用してベーカリー API で記述することができます。
例えば、実際のアプリケーションシナリオは次のとおりです。 Checkmk の拡張機能の開発に関する紹介を読み、それに触発されて、独自のエージェントベースのチェックプラグインと、それに関連するエージェントプラグインを作成しました。 次に、これら 2 つを 1 つのCheckmk 拡張パッケージ(MKP)にまとめました。
ここで、エージェントプラグインを設定可能にし(たとえば、特定のユーザーまたは特定のホストでのみ実行可能にする)、さらにエージェントパッケージのインストールまたはアンインストール時にアクションを実行したいとします。 これを行うには、ベーカリー API をパッケージングおよび配布の補助として使用できます。この記事では、例を使用してその方法について説明します。 これにより、2 つの新しいファイルが作成され、既存のプラグインファイルと一緒にパッケージ化して、新しい MKP を作成することができます。 この手順の詳細なコメント付き例も、Checkmk Exchange の「Hello world!MKP(GitHub で解凍)」でご覧いただけます。これは、この記事で紹介した例にほぼ基づいています。
注:ベーカリー API には、ベーカリープラグインを設定する機能、つまり関連するルールセットを作成する機能や、プラグインとともに提供されるファイル(エージェントプラグインなど)の内容を設定する機能はありません。
エージェントベーカリーは商業版にのみ含まれていますが、Checkmk2.3.0 以降、ベーカリー APIはすべてのエディションに存在しています。 これにより、Checkmk Raw ユーザーは、すべてのエディションにインストールできる拡張パッケージを作成することができます。 ベーカリー API で作成されたパッケージが Checkmk Raw にインストールされた場合、追加機能は単に無視されます。 |
2. API ドキュメント
2.1. バージョン管理
ベーカリー API ソフトウェアとドキュメントは同じソースから提供されているため、API ドキュメントは常にソフトウェアと一致し、API の機能を正確に説明しています。 そのため、Checkmk ユーザーガイドで、利用可能な機能、クラス、パラメータなどの参照部分を説明する必要はありません。 その代わりに、このユーザーガイドの外、Checkmk サイトで API ドキュメントを直接ご覧いただけます。
API およびそのドキュメントは、セマンティックバージョニング 2.x標準に準拠した 2 レベルの番号でバージョン管理されています。X.Y 、ここで、X はメジャーバージョン、Y はマイナーバージョンを表します。
新しいマイナーバージョンには、下位互換性のある新機能が含まれています。
一方、新しいメジャーバージョンには、API を以前のメジャーバージョンと互換性がない変更が含まれている場合があります。
バージョン1 は、この記事で説明するベーカリー API の現在のバージョンです。
各プラグインは、API へのアクセス時に、そのプラグインが基づいている API バージョンを明示的に宣言します。
API は、Checkmk ソフトウェアとは異なるバージョン管理方式を採用しています。 ただし、API ドキュメントと Checkmk ソフトウェアのバージョンは、次の章で説明するように、非常に簡単にマッピングすることができます。
2.2. API ドキュメントへのアクセス
ベーカリー API ドキュメントは、web ブラウザで表示できる HTML 形式で提供されており、Checkmk GUI から開くことができます。Help > Developer resources > Plug-in API references メニューのナビゲーションバーから開きます。

プラグイン API ドキュメントは、新しいブラウザウィンドウ(またはブラウザのタブ)に表示されます。

このウィンドウには、Checkmk プラグインの開発に関連する API ドキュメントが表示されます。 つまり、ここでは、ベーカリー API ドキュメントに加えて、Check API のドキュメントもご覧いただけます。 API ドキュメントは、Sphinx を使用して生成および表示されます。
ベーカリー API ドキュメントは、サイトにインストールされている Checkmk バージョンでサポートされているバージョンで確認できます。
3. API の使用
3.1. サンプルシナリオ
以下のサンプルシナリオを使用して、API の使用方法を説明します:
Checkmk エージェント用に、
hello_worldという名前のプラグインが提供されています。このエージェントプラグインには、Linux、Solaris、Windows の 3 つのバリエーションがあり、これら 3 つのオペレーティングシステム用のエージェントパッケージにも含まれています。対応するファイルも利用可能で、Linux では
hello_world、Solaris ではhello_world.solaris.ksh、Windows ではhello_world.cmdという名前です。
Python、シェル、および CMD スクリプトはあくまで例です。エージェントプラグインは、ターゲットシステムで実行可能な任意のファイルにすることができます。
このコンテキストでは、ファイルの内容自体は重要ではありません。 エージェントプラグインの機能は、ベーカリー API の対象ではありません。 詳細については、独自のエージェントベースのチェックプラグインの開発入門をご覧ください。プラグインの出力をキャッシュするかどうか、つまり、この場合、プラグインは、設定された時間(実行間隔)が経過してからエージェントによって再度実行されるかどうかを設定できる必要があります。
プラグインは、セットアップメニューの「エージェントベーカリー」設定で、
userおよびcontentの変数を使用して設定します。 Linux プラグインは、hello_world.json設定ファイルから設定を読み込み、Solaris プラグインは、hello_world.cfgファイルから設定を読み込みます。 Windows プラグインは、Windows エージェントの YAML 設定ファイルからhello_world.userおよびhello_world.contentのエントリを読み込みます。
いずれの場合も、これらのリソースへのアクセスはエージェントプラグインで実装する必要があり、ベーカリー API ではハンドルされません。Linux および Solaris には、
some_binaryという追加プログラムがあります。これは、Checkmk エージェントとは独立してコマンドでプラグインを起動できるように、たとえば小さなシェルスクリプトとして提供する必要があります。Linux および Solaris では、エージェントをインストールした後、
hello_worldがインストールされたことをパッケージマネージャのルーチンで syslog に書き込む必要があります。 同様に、エージェントをアンインストールした後、hello_worldがアンインストールされたことを syslog に書き込む必要があります。
Linux では、postinstおよびprermスクリプトが一般的です。postinstスクリプトでは、たとえばキャッシュを作成し、ディーモンを起動します。prermスクリプトでは、ディーモンを停止し、キャッシュを消去することができます。maintainer scriptsの使用方法の詳細については、Debian のドキュメントを参照してください。
3.2. ルールセットの作成
ベーカリープラグインには、GUI を使用してプラグインを設定するためのセットアップ用ルールセットが必要です。 最も単純なケースでは、ルールセットは、特定のホストにプラグインを割り当てることによってプラグインをアクティブにするだけです。 ルールセットの作成は、ベーカリー API の一部ではありません。 このトピックの概要については、「独自のエージェントベースのチェックプラグインの開発」の記事をご覧ください。 そこでは、ルールセットを保存するためのパス規則についても説明しています。
最小限のルールセット
プラグインの配布のみを有効にする、このような最小限のルールセットの例は、次のとおりです。
ここでは、拡張例もカバーするために、必要以上に多くのクラスをインポートしています。
エージェントベースのチェックプラグインのルールセットとの最も顕著な違いは、CheckParameters の代わりにAgentConfig クラスを使用していることです。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Shebang only needed for editor!
from cmk.rulesets.v1 import Label, Title, Help
from cmk.rulesets.v1.form_specs import (
BooleanChoice,
DefaultValue,
DictElement,
Dictionary,
String,
TimeSpan,
TimeMagnitude
)
from cmk.rulesets.v1.rule_specs import AgentConfig, HostCondition, Topic
def _parameter_form_bakery():
return Dictionary(
elements = {}
)
rule_spec_hello_world_bakery = AgentConfig(
name = "hello_world",
title = Title("Hello bakery!"),
topic = Topic.GENERAL,
parameter_form = _parameter_form_bakery,
)拡張ルールセット
ただし、この例では、実行間隔を選択し、user とcontent の2つの変数を設定するように指定しています。
これらの変数は、parameter_form で指定された関数から返されるDictionary のキーとして定義されています。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Shebang only needed for editor!
from cmk.rulesets.v1 import Label, Title, Help
from cmk.rulesets.v1.form_specs import (
BooleanChoice,
DefaultValue,
DictElement,
Dictionary,
String,
TimeSpan,
TimeMagnitude
)
from cmk.rulesets.v1.rule_specs import AgentConfig, HostCondition, Topic
def _parameter_form_bakery():
return Dictionary(
elements = {
"user": DictElement(
parameter_form = String(
title = Title("User for example plugin"),
)
),
"content": DictElement(
parameter_form = String(
title = Title("The actual content"),
)
),
"interval": DictElement(
parameter_form = TimeSpan(
title = Title("Run asynchronously"),
label = Label("Interval for collecting data"),
displayed_magnitudes = [TimeMagnitude.SECOND, TimeMagnitude.MINUTE],
prefill = DefaultValue(300.0),
)
)
}
)
rule_spec_hello_world_bakery = AgentConfig(
name = "hello_world",
title = Title("Hello bakery!"),
topic = Topic.GENERAL,
parameter_form = _parameter_form_bakery,
)このルールセットの結果の GUI は、次のスクリーンショットに示されています。

3.3. プラグインファイルの作成
hello_world.py プラグインファイルは、サイトディレクトリ構造のローカル部分、local/lib/check_mk/base/cee/plugins/bakery/ に保存されます。
Bakery プラグインは、Python 3 モジュールとしてインポートされるファイルのフォームで作成されます。 したがって、Checkmk の規則に従って、プラグインファイルも次の行で始まります。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-これはモジュールであるため、必要なすべてのクラスと関数は最初にインポートする必要があります。
3.4. API へのアクセス
ベーカリー API のすべてのオブジェクトは、cmk.base.cee.plugins.bakery.bakery_api.vX で利用できます。ここで、X は API のバージョン番号を表します。この例では、1 です。
プラグインファイル自体はcmk.base.cee.plugins.bakery 名前空間にあるため、.bakery_api.v1 から相対インポートも機能します。
from .bakery_api.v1 import (
OS,
DebStep,
RpmStep,
SolStep,
Plugin,
PluginConfig,
SystemBinary,
Scriptlet,
WindowsConfigEntry,
register,
FileGenerator,
ScriptletGenerator,
WindowsConfigGenerator,
quote_shell_string,
)上記の例では、例示のシナリオで必要な名前のみがインポートされています。
3.5. API で利用可能なオブジェクト
ベーカリー API で使用できる名前は、API ドキュメントで詳しく説明されています。 ただし、この章では、例シナリオの実装を理解するのに役立つため、オブジェクトについて簡単に紹介します。
識別子 / 列挙型
個々のプラグインアーティファクトを指定するために、列挙型 (Enum) を使用できます。これは、通常、引数のフォームでさまざまなプロパティを指定するために使用します。
OS- Bakery API のコンテキストにおけるオペレーティングシステム。DebStep- DEB 「メンテナスクリプト」のトランザクションステップRpmStep- RPM 「スクリプトレット」のトランザクションステップ。SolStep- Solaris PKG の「インストールスクリプト」のトランザクションステップ。
アーティファクト
プラグインの実際のコンポーネントであるファイルおよびファイルの内容は、アーティファクトと呼ばれます。 これらは、適切なクラスを使用して記述され、次のカテゴリに分類されます。
ファイル (
Plugin、SystemBinary、PluginConfig、SystemConfig) - Checkmk エージェントに提供される各ファイルは、オブジェクトで記述されます。 ファイルタイプは、クラスで記述されます。 ファイルをデプロイするオペレーティングシステムごとに、個別のオブジェクトを定義する必要があります。スクリプトレット (
Scriptlet) - 指定したトランザクションステップ (preinstall、postremoveなど) で、エージェントパッケージのインストール、アンインストール、または更新を実行する際に実行される DEB 「メンテナスクリプト」、RPM 「スクリプトレット」、または Solaris PKG 「インストールスクリプト」。Windows 構成エントリ (
WindowsConfigEntry、WindowsConfigItems、WindowsGlobalConfigEntry、WindowsSystemConfigEntry) - Windows エージェントの YAML 構成ファイル内のエントリも、適切なクラスを使用して記述されます。
これらのアーティファクトは、それぞれのカテゴリに対応するコールバック関数で記述されています。
個々の関数は、引数files_function 、scriptlets_function 、windows_config_function とともにregister 関数に渡されます。
これらは、指定された個々のアーティファクトを返すジェネレータ関数です。
評価は、エージェントベーカリーによって行われます。
関数は、返されるアーティファクトを構築および決定するために評価できるさまざまなパラメータを引数として受け取ります。
パラメータは、一方では、ベイクされる各エージェントの GUI 構成 (conf)、他方では、現在のエージェント構成およびプラグインファイルのハッシュ (aghash) です。
登録関数
登録は、Bakery プラグインをモジュールとしてインポートするときに呼び出されるregister 関数によって実行されます。
この関数は、Bakery プラグインの個々のコンポーネントを引数として受け取ります。
プラグインの名前 (name) およびその関数 (files_function 、scriptlets_function 、windows_config_function) で、それぞれはアーティファクトのカテゴリを返します。
型注釈
型注釈の名前(FileGenerator 、ScriptletGenerator 、WindowsConfigGenerator 、WindowsConfigContent )は、指定された関数の型を識別するためにオプションで使用できます。例えば、次のように使用できます:
def get_files(conf: dict) -> FileGenerator:
yield Plugin(...)
yield PluginConfig(...)
def get_scriptlets(conf: dict) -> ScriptletGenerator:
yield Scriptlet(...)
def get_windows_config(conf: dict) -> WindowsConfigGenerator:
content: WindowsConfigContent = conf["some_entry"]
yield WindowsGlobalConfigEntry(name="some_name",content=content)ヘルパー関数
次のヘルパー関数を使用できます。
quote_shell_string- この関数は、Python コードで引用符を手動でマスクすることなく、文字列式を、結果ファイルでシェルによって式として正しく認識されるように変換するために使用できます。password_store- このモジュールを使用すると、Checkmk パスワードストアに保存されているパスワードにアクセスできます。
3.6. 登録
プラグイン名とその関数を使用してプラグインを Checkmk に登録するには、register.bakery_plugin 関数を使用します。
register.bakery_plugin(
name = "hello_world",
files_function = get_hello_world_plugin_files,
scriptlets_function = get_hello_world_scriptlets,
windows_config_function = get_hello_world_windows_config,
)ここで指定されたget_hello_world_windows_config 、get_hello_world_scriptlets 、およびget_hello_world_plugin_files 関数については、以下の章で詳細に説明されています。
3.7. Windows エージェントの設定
この例では、実行間隔を定義する必要があり、プラグインの設定は 2 つの変数で実行できる必要があります。 キーとデータ型は、上記で作成したルールセットで定義したとおりに定義してください。
class HelloWorldConfig(TypedDict, total=False):
interval: float
user: str
content: str
def get_hello_world_windows_config(conf: HelloWorldConfig) -> WindowsConfigGenerator:
yield WindowsConfigEntry(path=["hello_world", "user"], content=conf["user"])
yield WindowsConfigEntry(path=["hello_world", "content"], content=conf["content"])get_hello_world_windows_config 関数では、conf 引数を使用して、セットアップGUIでルールセットで設定された設定にアクセスします。
キャッシュされた出力の再実行の時間間隔(interval )と、プラグインの設定に使用できる2つの変数(user 、content )。
ここでは、ルールセットの設定がdict として提供されていることを前提としています。クラスHelloWorldConfig のTypedDict を使用すると、それへの標準化されたアクセスを設定できます。
次に、WindowsConfigEntry を使用して、user およびcontent の値が読み込まれるYAML-Windowsエージェント設定ファイル内のエントリを指定します。
3.8. Linux 用のインストールスクリプト
Linux および Solaris では、エージェントのインストールおよびアンインストール時に syslog メッセージが書き込まれる必要があります。 ここでは、Debian Linux ディストリビューションの実装のみを示します。
def get_hello_world_scriptlets(conf: Any) -> ScriptletGenerator:
installed_lines = ['logger "Installed hello_world"']
uninstalled_lines = ['logger "Uninstalled hello_world"']
yield Scriptlet(step=DebStep.POSTINST, lines=installed_lines)
yield Scriptlet(step=DebStep.POSTRM, lines=uninstalled_lines)
# yield Scriptlet(step=RpmStep.POST, lines=installed_lines)
# yield Scriptlet(step=RpmStep.POSTUN, lines=uninstalled_lines)
# yield Scriptlet(step=SolStep.POSTINSTALL, lines=installed_lines)
# yield Scriptlet(step=SolStep.POSTREMOVE, lines=uninstalled_lines)まず、syslog メッセージ用のコマンドを定義し、次に、インストール後に実行すべき Debian (DebStep) およびアンインストール後に実行すべき (POSTINST) および (POSTRM) のインストールスクリプトを定義します。
以下のコメントには、RPM および Solaris を使用するディストリビューションに対応する行も記載されています。
注:ご入力いただいたコマンドラインに続き、Checkmk によってインストールスクリプトに追加のコマンドが読み込まれます。
したがって、スクリプト内のすべてのコマンドが確実に実行されるように、コマンドセットをexit 0 で終了しないでください。
3.9. Linux 用のエージェントプラグイン
Linux エージェントプラグインの設定は、次のようになります。
ルールセットとベーカリーは異なるデータ型を使用するため、Integer に渡される間隔を必ず変換してください。
def get_hello_world_plugin_files(conf: HelloWorldConfig) -> FileGenerator:
interval = conf.get('interval')
yield Plugin(
base_os = OS.LINUX,
source = Path('hello_world'),
target = Path('hello_world'),
interval = int(interval),
)
yield PluginConfig(
base_os = OS.LINUX,
lines = _get_linux_cfg_lines(conf['user'], conf['content']),
target = Path('hello_world.json'),
include_header = False)
for base_os in [OS.LINUX]:
yield SystemBinary(
base_os = base_os,
source = Path('some_binary'),
)
def _get_linux_cfg_lines(user: str, content: str) -> List[str]:
config = json.dumps({'user': user, 'content': content})
return config.split('\n')get_hello_world_plugin_files 関数では、まずPythonファイルhello_world をplugin 、つまりCheckmkエージェントがエージェントプラグインとして実行する実行ファイルとして定義します。
次に、PluginConfig を使用して、user およびcontent エントリを含む、Linuxエージェントプラグイン用に生成するhello_world.json 設定ファイルを指定します。
2 番目の関数_get_linux_cfg_lines を使用して、これらの行を JSON 形式で記述します。
ここで、Python 辞書conf には、セットアップ GUI のルールセットで設定された値が格納されており、小さな回り道を経て JSON ファイルにパックされます。
最後に、追加のシェルスクリプトsome_binary を、ターゲットシステムのユーザープログラム用ディレクトリ (デフォルトでは/usr/bin) にSystemBinary として配置します。
3.10. この例の場合のプラグインファイル
これまで紹介してきたすべての部分をまとめ、完成させると、この例の場合のプラグインは、最終的には次のようになります。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Shebang only needed for editor!
import json
from pathlib import Path
from typing import Iterable, TypedDict, List
from .bakery_api.v1 import (
OS,
DebStep,
RpmStep,
SolStep,
Plugin,
PluginConfig,
SystemBinary,
Scriptlet,
WindowsConfigEntry,
register,
FileGenerator,
ScriptletGenerator,
WindowsConfigGenerator,
quote_shell_string,
)
class HelloWorldConfig(TypedDict, total=False):
interval: float
user: str
content: str
def get_hello_world_plugin_files(conf: HelloWorldConfig) -> FileGenerator:
interval = conf.get('interval')
yield Plugin(
base_os = OS.LINUX,
source = Path('hello_world'),
target = Path('hello_world'),
interval = int(interval),
)
yield Plugin(
base_os =OS.SOLARIS,
source = Path('hello_world.solaris.ksh'),
target = Path('hello_world'),
interval = int(interval),
)
yield Plugin(
base_os = OS.WINDOWS,
source = Path('hello_world.cmd'),
target = Path('hello_world.bat'),
interval = int(interval),
)
yield PluginConfig(
base_os = OS.LINUX,
lines = _get_linux_cfg_lines(conf['user'], conf['content']),
target = Path('hello_world.json'),
include_header = False
)
yield PluginConfig(
base_os = OS.SOLARIS,
lines = _get_solaris_cfg_lines(conf['user'], conf['content']),
target = Path('hello_world.cfg'),
include_header = True
)
for base_os in [OS.LINUX, OS.SOLARIS]:
yield SystemBinary(
base_os = base_os,
source = Path('some_binary'),
)
def _get_linux_cfg_lines(user: str, content: str) -> List[str]:
config = json.dumps({'user': user, 'content': content})
return config.split('\n')
def _get_solaris_cfg_lines(user: str, content: str) -> List[str]:
# To be loaded with 'source' in Solaris shell script
return [
f'USER={quote_shell_string(user)}',
f'CONTENT={quote_shell_string(user)}',
]
def get_hello_world_scriptlets(conf: HelloWorldConfig) -> ScriptletGenerator:
installed_lines = ['logger -p local3.info "Installed hello_world"']
uninstalled_lines = ['logger -p local3.info "Uninstalled hello_world"']
yield Scriptlet(step=DebStep.POSTINST, lines=installed_lines)
yield Scriptlet(step=DebStep.POSTRM, lines=uninstalled_lines)
yield Scriptlet(step=RpmStep.POST, lines=installed_lines)
yield Scriptlet(step=RpmStep.POSTUN, lines=uninstalled_lines)
yield Scriptlet(step=SolStep.POSTINSTALL, lines=installed_lines)
yield Scriptlet(step=SolStep.POSTREMOVE, lines=uninstalled_lines)
def get_hello_world_windows_config(conf: HelloWorldConfig) -> WindowsConfigGenerator:
yield WindowsConfigEntry(path=["hello_world", "user"], content=conf["user"])
yield WindowsConfigEntry(path=["hello_world", "content"], content=conf["content"])
register.bakery_plugin(
name = "hello_world",
files_function = get_hello_world_plugin_files,
scriptlets_function = get_hello_world_scriptlets,
windows_config_function = get_hello_world_windows_config,
)3.11. ファイルの利用可能化
Bakery プラグインが正しく動作するには、関連するすべてのファイルをサイトディレクトリのローカル構造内の正しい場所に配置または書き込む必要があります。
これらは、プラグインファイル自体と、files_function によって返されるオブジェクトです。これらのオブジェクトは、Bakery プラグインによって直接作成される設定ファイルを表すか、エージェントパッケージのパッケージ化時に見つけることができるように正しく保存しなければならないファイルを参照します。
Plugin およびSystemBinary クラスのオブジェクトは、保存する必要がある既存のファイルを表します。PluginConfig およびSystemConfig として記述されたファイルは、lines 引数に基づいてまだ生成されていないため、ここにファイルを保存する必要はありません。
最後に、ファイルセットには、プラグインのルールセットファイルも含まれます。
次の章、そして最後の章では、すべてのディレクトリのまとめをご紹介します。
4. ファイルおよびディレクトリ
Bakery プラグインをデプロイするためのファイルは、以下のディレクトリに配置する必要があります。
いつものように、ここでの仕様はすべてサイトディレクトリ (/omd/sites/mysite など) に対する相対パスです。
| ファイルパス | 説明 |
|---|---|
|
Bakery プラグインのディレクトリ (この例では |
|
Unix 系のエージェントプラグインを保存するディレクトリ。 |
|
Windows エージェントプラグインを保存するディレクトリ。 |
|
Unix 系オペレーティングシステム用のプログラムまたはシェルスクリプトのディレクトリ (この例では |
|
Windows 用の付属プログラムまたはシェルスクリプトのディレクトリ。 |
|
エージェントプラグイン(この例では |
