Skip to main content

Programmatic Zabbix template generation — Monitoring as Code

Project description

zbxtemplar

A Pythonic framework for programmatic Zabbix Template generation (Monitoring as Code).

The goal is to cover the essential Zabbix configuration primitives — not every possible option. If you need a field that isn't exposed, raw dicts and string expressions give you an escape hatch.

Installation

pip install .

Core Architecture

The project follows the src-layout:

  • zbxtemplar.entities — Domain models: Template, Host, Item, Trigger, Graph, Dashboard.
  • zbxtemplar.core — Module contract (TemplarModule), loader, serialization, shared types.
  • zbxtemplar.main — CLI entry point.

Module Contract

Templates and hosts are defined as Python classes that inherit from TemplarModule. The constructor is the contract — all configuration logic lives in __init__.

from zbxtemplar.core import TemplarModule
from zbxtemplar.entities import Template, Item, Host, TriggerPriority
from zbxtemplar.entities.Template import TemplateGroup
from zbxtemplar.entities.Host import HostGroup, AgentInterface

class MyModule(TemplarModule):
    def __init__(self):
        super().__init__()

        template = Template(name="My Service", groups=[TemplateGroup("Custom Templates")])
        template.add_tag("Service", "MyApp")
        template.add_macro("THRESHOLD", 90, "Alert threshold")

        item = Item("CPU Usage", "system.cpu.util", template.name)
        item.add_trigger("High CPU", "last", ">",
                         template.get_macro("THRESHOLD"),
                         priority=TriggerPriority.HIGH)
        template.add_item(item)

        host = Host("My Server", groups=[HostGroup("Linux Servers")])
        host.add_template(template)
        host.add_interface(AgentInterface(ip="192.168.1.10"))

        self.templates = [template]
        self.hosts = [host]

A module file can contain multiple TemplarModule subclasses. The loader discovers all of them by class name.

Running standalone

Add a __main__ guard to run the module directly:

if __name__ == "__main__":
    import yaml
    module = MyModule()
    print(yaml.dump(module.to_export(), default_flow_style=False, sort_keys=False))

CLI

# Combined output (templates + hosts)
zbxtemplar module.py output.yml

# Separate outputs
zbxtemplar module.py --templates-output templates.yml --hosts-output hosts.yml

# Combined + separate
zbxtemplar module.py output.yml --templates-output templates.yml --hosts-output hosts.yml

# With UUID namespace
zbxtemplar module.py output.yml --namespace "My Company"
Argument Description
module Path to a .py file with TemplarModule subclass(es)
output Combined output YAML file path (optional if split outputs are given)
--templates-output Output YAML file path for templates only
--hosts-output Output YAML file path for hosts only
--namespace UUID namespace for deterministic ID generation

Programmatic Loading

from zbxtemplar.core import load_module

modules = load_module("path/to/module.py")
# Returns {"ClassName": <instance>, ...}

for name, mod in modules.items():
    export = mod.to_export()  # Full zabbix_export dict

Entities Reference

Template

template = Template(name="My Template", groups=[TemplateGroup("Custom Group")])
template.add_tag("Service", "MyApp")
template.add_macro("TIMEOUT", 30, "Connection timeout")
template.add_item(item)

Host

from zbxtemplar.entities import Host
from zbxtemplar.entities.Host import HostGroup, AgentInterface

host = Host("My Host", groups=[HostGroup("Linux Servers")])
host.add_tag("Environment", "Production")
host.add_macro("HOST_PORT", 8080, "Application port")

# Link a template
host.add_template(template)

# Add an interface (first interface becomes the default)
iface = AgentInterface(ip="192.168.1.10", port="10050")
host.add_interface(iface)

# Host-level items, triggers, graphs work the same as on templates
item = Item("Host Uptime", "system.uptime", host.name)
item.set_interface(iface)
host.add_item(item)

# Macro lookup walks linked templates when not found on the host
host.get_macro("TEMPLATE_MACRO")  # falls back to template macros

Hosts produce UUID-free YAML (matching Zabbix export format). Dashboards are template-only and cannot be added to hosts.

AgentInterface is the built-in interface type (type: ZABBIX). Custom interface types can be created by subclassing HostInterface.

HostGroup

from zbxtemplar.entities.Host import HostGroup

group = HostGroup("Linux Servers")

Works the same as TemplateGroup — name-based identity with a deterministic UUID.

Item

item = Item("CPU Usage", "system.cpu.util")

# Expression helper — builds Zabbix function strings
item.expr("last")            # last(/host/key)
item.expr("min", "10m")      # min(/host/key,10m)
item.expr("count", "#10")    # count(/host/key,#10)

# Single-item trigger shorthand
item.add_trigger("High CPU", "last", ">", 90,
                 priority=TriggerPriority.HIGH,
                 description="CPU threshold exceeded")

# With function args
item.add_trigger("Sustained high", "min", ">", 100,
                 fn_args=("10m",), priority=TriggerPriority.WARNING)

All enum values (ItemType, ValueType, TriggerPriority, GraphType, DrawType, CalcFnc, etc.) follow the Zabbix export format documentation.

Trigger

# Standalone (multi-item) trigger — raw expression string
Trigger(name="Complex alert",
        expression=item1.expr("last") + ">0 and " + item2.expr("min", "5m") + "<100",
        priority=TriggerPriority.WARNING,
        description="Multi-item condition")

Macro

Macros work seamlessly in string contexts:

template.add_macro("MY_MACRO", 1, "Description")
macro = template.get_macro("MY_MACRO")

str(macro)                    # {$MY_MACRO}
item.expr("last") + ">" + macro  # last(/host/key)>{$MY_MACRO}
item.add_trigger("Alert", "last", ">", macro)  # works as threshold

Graph

graph = Graph("CPU Graph",
              graph_type=GraphType.STACKED,
              y_min_type=YAxisType.FIXED, y_min=0,
              y_max_type=YAxisType.FIXED, y_max=100)

graph.add_item(item1, "FF0000")
graph.add_item(item2, "00FF00",
               drawtype=DrawType.BOLD_LINE,
               calc_fnc=CalcFnc.MAX,
               yaxisside=YAxisSide.RIGHT)

Dashboard

from zbxtemplar.entities import Dashboard, DashboardPage
from zbxtemplar.entities.DashboardWidget import ClassicGraph

page = DashboardPage(name="Overview", display_period=120)
page.add_widget(ClassicGraph(template=template.name, graph=graph, width=36, height=5))

dashboard = Dashboard("My Dashboard", display_period=60, auto_start=YesNo.NO)
dashboard.add_page(page)
template.add_dashboard(dashboard)

Widgets are concrete subclasses of Widget (abstract). Each widget type lives in zbxtemplar.entities.DashboardWidget. Creating custom widgets is straightforward — subclass Widget, define type and widget_fields().

Global Configuration

from zbxtemplar.core.ZbxEntity import set_uuid_namespace

set_uuid_namespace("My Company")  # Deterministic UUIDs scoped to namespace

Executor

The executor is a separate tool that applies generated YAML and other configuration to a live Zabbix instance. Install with the executor extra:

pip install ".[executor]"

Commands

# Bootstrap or rotate super admin password
zbxtemplar-exec set_super_admin --new-password $ZBX_ADMIN_PASSWORD \
  --user Admin --password zabbix --url http://localhost

# Set global macros
zbxtemplar-exec set_macro SNMP_COMMUNITY public --token $ZBX_TOKEN
zbxtemplar-exec set_macro macros.yml --token $ZBX_TOKEN

# Import Zabbix-native YAML (templates, hosts, media types, etc.)
zbxtemplar-exec apply zabbix-native.yml --token $ZBX_TOKEN

# Apply state configuration (user groups, users)
zbxtemplar-exec decree state.yml --token $ZBX_TOKEN

# Create service accounts (shorthand — feeds into decree)
zbxtemplar-exec add_user users.yml --token $ZBX_TOKEN

Connection credentials can be passed via CLI flags (--url, --token, --user, --password) or environment variables (ZABBIX_URL, ZABBIX_TOKEN, ZABBIX_USER, ZABBIX_PASSWORD).

Decree

A decree is zbxtemplar's declarative YAML format for live-state configuration that has no Zabbix-native import format. A single decree file can contain any combination of supported sections, processed in dependency order.

user_group:
  - name: Templar Users
    gui_access: INTERNAL
    host_groups:
      - name: Linux servers
        permission: READ
    template_groups:
      - name: Custom Templates
        permission: READ_WRITE

add_user:
  - username: zbx-service
    role: Super admin role
    password: ${ZBX_SERVICE_PASSWORD}
    groups:
      - Templar Users

All references are by name — the executor resolves IDs at runtime. In a scroll, decree accepts a file path, an inline dict, or a list mixing both.

Named constants for gui_access: DEFAULT, INTERNAL, LDAP, DISABLED. Named constants for permission: NONE, READ, READ_WRITE. Severity uses comma-separated names instead of bitmasks: NOT_CLASSIFIED, INFORMATION, WARNING, AVERAGE, HIGH, DISASTER.

If a user has token defined and the token already exists, the executor raises an error. Set force_token: true to delete and recreate the token.

The add_user CLI command is a shorthand that feeds a file containing add_user: into the decree pipeline.

Scroll

A scroll is a static YAML file describing a full deployment sequence. Stages execute in a fixed pipeline order: bootstraptemplatesstate.

stages:
  - stage: bootstrap
    set_super_admin:
      password: ${ZBX_ADMIN_PASSWORD}
    set_macro:
      - name: SNMP_COMMUNITY
        value: public
      - name: DB_PASSWORD
        value: ${DB_PASSWORD}
        type: secret

  - stage: templates
    apply:
      - templates.yml
      - media-types.yml

  - stage: state
    decree:
      user_group:
        - name: Templar Users
          gui_access: INTERNAL
      add_user:
        - username: zbx-service
          role: Super admin role
          password: ${ZBX_SERVICE_PASSWORD}
zbxtemplar-exec scroll deploy.scroll.yml --token $ZBX_TOKEN
zbxtemplar-exec scroll deploy.scroll.yml --from-stage state
zbxtemplar-exec scroll deploy.scroll.yml --only-stage bootstrap

File paths in scroll actions resolve relative to the scroll file's directory, not the working directory. String values may contain ${ENV_VAR} references, resolved from the OS environment before any API calls. Missing variables cause a pre-flight failure — no partial execution.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

zbxtemplar-0.5.0.tar.gz (30.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

zbxtemplar-0.5.0-py3-none-any.whl (28.0 kB view details)

Uploaded Python 3

File details

Details for the file zbxtemplar-0.5.0.tar.gz.

File metadata

  • Download URL: zbxtemplar-0.5.0.tar.gz
  • Upload date:
  • Size: 30.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for zbxtemplar-0.5.0.tar.gz
Algorithm Hash digest
SHA256 f18b3cb03a6039ac3bfb6c22fd4935c0a221680ad3b67cbbe25b16872a0adc38
MD5 27a7c59106b4cf8fc4d89c99a2e750c8
BLAKE2b-256 92e0636b98c329bbf60d77b316f3442884b83f3231d963a1b73f0f98532bc3ea

See more details on using hashes here.

File details

Details for the file zbxtemplar-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: zbxtemplar-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 28.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for zbxtemplar-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 288d58c19e1d2a783849e9cb5b02ce89694d238cf86292705fc21857e2dbe28a
MD5 41088193a46667b021dd2a42919b8630
BLAKE2b-256 c892ae8c46377759def2185c76f61dd78aed76aa7285219e26a6009a6a7d4777

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page