zbxctl 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- zbxctl-0.2.0/PKG-INFO +722 -0
- zbxctl-0.2.0/README.md +681 -0
- zbxctl-0.2.0/pyproject.toml +79 -0
- zbxctl-0.2.0/setup.cfg +4 -0
- zbxctl-0.2.0/tests/test_e2e.py +489 -0
- zbxctl-0.2.0/zbx/__init__.py +4 -0
- zbxctl-0.2.0/zbx/agent_deployer.py +362 -0
- zbxctl-0.2.0/zbx/cli.py +111 -0
- zbxctl-0.2.0/zbx/commands/__init__.py +1 -0
- zbxctl-0.2.0/zbx/commands/agent.py +300 -0
- zbxctl-0.2.0/zbx/commands/apply.py +103 -0
- zbxctl-0.2.0/zbx/commands/diff.py +43 -0
- zbxctl-0.2.0/zbx/commands/export.py +395 -0
- zbxctl-0.2.0/zbx/commands/inventory.py +275 -0
- zbxctl-0.2.0/zbx/commands/plan.py +43 -0
- zbxctl-0.2.0/zbx/commands/scaffold.py +222 -0
- zbxctl-0.2.0/zbx/commands/schema.py +192 -0
- zbxctl-0.2.0/zbx/commands/validate.py +40 -0
- zbxctl-0.2.0/zbx/config_loader.py +147 -0
- zbxctl-0.2.0/zbx/deployer.py +569 -0
- zbxctl-0.2.0/zbx/diff_engine.py +446 -0
- zbxctl-0.2.0/zbx/formatter.py +229 -0
- zbxctl-0.2.0/zbx/models.py +506 -0
- zbxctl-0.2.0/zbx/py.typed +0 -0
- zbxctl-0.2.0/zbx/zabbix_client.py +535 -0
- zbxctl-0.2.0/zbxctl.egg-info/PKG-INFO +722 -0
- zbxctl-0.2.0/zbxctl.egg-info/SOURCES.txt +29 -0
- zbxctl-0.2.0/zbxctl.egg-info/dependency_links.txt +1 -0
- zbxctl-0.2.0/zbxctl.egg-info/entry_points.txt +2 -0
- zbxctl-0.2.0/zbxctl.egg-info/requires.txt +16 -0
- zbxctl-0.2.0/zbxctl.egg-info/top_level.txt +1 -0
zbxctl-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,722 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: zbxctl
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Zabbix configuration as code — manage monitoring via Git
|
|
5
|
+
Author-email: Pau Santana <pausantanapi2@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/psantana5/zbx
|
|
8
|
+
Project-URL: Repository, https://github.com/psantana5/zbx
|
|
9
|
+
Project-URL: Bug Tracker, https://github.com/psantana5/zbx/issues
|
|
10
|
+
Project-URL: Changelog, https://github.com/psantana5/zbx/blob/main/CHANGELOG.md
|
|
11
|
+
Keywords: zabbix,monitoring,infrastructure-as-code,devops,gitops
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: System Administrators
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: System :: Monitoring
|
|
22
|
+
Classifier: Topic :: System :: Systems Administration
|
|
23
|
+
Classifier: Topic :: Utilities
|
|
24
|
+
Requires-Python: >=3.11
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
Requires-Dist: typer[all]>=0.12
|
|
27
|
+
Requires-Dist: requests>=2.31
|
|
28
|
+
Requires-Dist: pydantic>=2.5
|
|
29
|
+
Requires-Dist: pyyaml>=6.0
|
|
30
|
+
Requires-Dist: rich>=13.7
|
|
31
|
+
Requires-Dist: python-dotenv>=1.0
|
|
32
|
+
Requires-Dist: paramiko>=3.4
|
|
33
|
+
Provides-Extra: dev
|
|
34
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
35
|
+
Requires-Dist: pytest-mock>=3.12; extra == "dev"
|
|
36
|
+
Requires-Dist: responses>=0.25; extra == "dev"
|
|
37
|
+
Requires-Dist: mypy>=1.8; extra == "dev"
|
|
38
|
+
Requires-Dist: ruff>=0.3; extra == "dev"
|
|
39
|
+
Requires-Dist: build>=1.0; extra == "dev"
|
|
40
|
+
Requires-Dist: twine>=5.0; extra == "dev"
|
|
41
|
+
|
|
42
|
+
# zbx — Zabbix Configuration as Code
|
|
43
|
+
|
|
44
|
+
Manage Zabbix templates, items, triggers and discovery rules through YAML files
|
|
45
|
+
and Git — the same mental model as Terraform or Ansible.
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
zbx plan configs/ See what would change
|
|
49
|
+
zbx apply configs/ Apply changes to Zabbix
|
|
50
|
+
zbx diff configs/ Compare local config against Zabbix
|
|
51
|
+
zbx validate configs/ Validate YAML schema (no Zabbix connection)
|
|
52
|
+
zbx export linux Export an existing template to YAML
|
|
53
|
+
zbx scaffold my-check Bootstrap a new monitoring check folder
|
|
54
|
+
|
|
55
|
+
zbx inventory list List all hosts in Zabbix
|
|
56
|
+
zbx inventory apply inventory.yaml Create or update hosts in Zabbix
|
|
57
|
+
|
|
58
|
+
zbx agent diff <host> Preview agent-side changes
|
|
59
|
+
zbx agent deploy <host> Deploy scripts and UserParameters via SSH
|
|
60
|
+
zbx agent test <host> Verify keys with zabbix_agentd -t
|
|
61
|
+
|
|
62
|
+
zbx agent deploy <host> --from-check configs/checks/my-check/
|
|
63
|
+
zbx agent test <host> --from-check configs/checks/my-check/
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Why zbx?
|
|
69
|
+
|
|
70
|
+
| Pain | Solution |
|
|
71
|
+
|---|---|
|
|
72
|
+
| Zabbix templates live only in the web UI | Store everything as YAML in Git |
|
|
73
|
+
| No audit trail for monitoring changes | Every change is a commit |
|
|
74
|
+
| Hard to review or approve changes | PR-based workflow, same as application code |
|
|
75
|
+
| Drift between environments | `zbx diff` catches it |
|
|
76
|
+
| Manual script deployment to monitored hosts | `zbx agent deploy` handles it |
|
|
77
|
+
| No way to automate template rollout | CI/CD friendly CLI |
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Installation
|
|
82
|
+
|
|
83
|
+
Requirements: Python 3.11+
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
git clone https://github.com/psantana5/zbx
|
|
87
|
+
cd zbx
|
|
88
|
+
pip install -e .
|
|
89
|
+
|
|
90
|
+
zbx --version
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Configuration
|
|
96
|
+
|
|
97
|
+
Copy `.env.example` to `.env` and fill in the connection details:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
cp .env.example .env
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
ZBX_URL=http://zabbix.example.com/zabbix
|
|
105
|
+
ZBX_USER=Admin
|
|
106
|
+
ZBX_PASSWORD=secret
|
|
107
|
+
ZBX_VERIFY_SSL=true
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Or export the variables directly (useful in CI/CD):
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
export ZBX_URL=http://zabbix.example.com/zabbix
|
|
114
|
+
export ZBX_USER=Admin
|
|
115
|
+
export ZBX_PASSWORD=secret
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Two-Layer Deployment Model
|
|
121
|
+
|
|
122
|
+
zbx manages both sides of Zabbix monitoring:
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
Layer 1 — Zabbix server config (templates, items, triggers, discovery rules)
|
|
126
|
+
configs/templates/ YAML templates
|
|
127
|
+
configs/hosts/ Host playbooks (which templates to link, which macros to set)
|
|
128
|
+
|
|
129
|
+
zbx plan / apply / diff / validate / export
|
|
130
|
+
|
|
131
|
+
Layer 2 — Monitored host agent config (scripts + UserParameters)
|
|
132
|
+
scripts/ Agent scripts versioned in Git
|
|
133
|
+
inventory.yaml Host inventory with agent deployment config
|
|
134
|
+
|
|
135
|
+
zbx inventory apply Create/update hosts in Zabbix
|
|
136
|
+
zbx agent deploy SSH into host, deploy scripts, write UserParameters
|
|
137
|
+
zbx agent test Run zabbix_agentd -t to verify keys
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Quick Start
|
|
143
|
+
|
|
144
|
+
### 1. Define a template
|
|
145
|
+
|
|
146
|
+
```yaml
|
|
147
|
+
# configs/templates/linux-observability.yaml
|
|
148
|
+
|
|
149
|
+
template: linux-observability
|
|
150
|
+
name: "Linux Observability"
|
|
151
|
+
description: "Core performance metrics for Linux servers"
|
|
152
|
+
groups:
|
|
153
|
+
- Templates
|
|
154
|
+
- Templates/Linux
|
|
155
|
+
|
|
156
|
+
items:
|
|
157
|
+
- name: CPU utilization
|
|
158
|
+
key: system.cpu.util
|
|
159
|
+
interval: 30s
|
|
160
|
+
value_type: float
|
|
161
|
+
units: "%"
|
|
162
|
+
|
|
163
|
+
- name: Available memory
|
|
164
|
+
key: vm.memory.size[available]
|
|
165
|
+
interval: 60s
|
|
166
|
+
value_type: unsigned
|
|
167
|
+
units: B
|
|
168
|
+
|
|
169
|
+
triggers:
|
|
170
|
+
- name: High CPU utilization (>90% for 5 min)
|
|
171
|
+
expression: avg(/linux-observability/system.cpu.util,5m) > 90
|
|
172
|
+
severity: high
|
|
173
|
+
|
|
174
|
+
discovery_rules:
|
|
175
|
+
- name: Mounted filesystem discovery
|
|
176
|
+
key: vfs.fs.discovery
|
|
177
|
+
interval: 1h
|
|
178
|
+
item_prototypes:
|
|
179
|
+
- name: "Filesystem {#FSNAME}: used space (%)"
|
|
180
|
+
key: "vfs.fs.size[{#FSNAME},pused]"
|
|
181
|
+
interval: 5m
|
|
182
|
+
value_type: float
|
|
183
|
+
units: "%"
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### 2. Plan, then apply
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
zbx plan configs/templates/linux-observability.yaml
|
|
190
|
+
zbx apply configs/templates/linux-observability.yaml
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### 3. Define a host and link the template
|
|
194
|
+
|
|
195
|
+
```yaml
|
|
196
|
+
# configs/hosts/webserver01.yaml
|
|
197
|
+
|
|
198
|
+
host: webserver01
|
|
199
|
+
templates:
|
|
200
|
+
- linux-observability
|
|
201
|
+
macros:
|
|
202
|
+
- macro: "{$CUSTOM_THRESHOLD}"
|
|
203
|
+
value: "90"
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
zbx apply configs/hosts/webserver01.yaml
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## Commands
|
|
213
|
+
|
|
214
|
+
### zbx plan
|
|
215
|
+
|
|
216
|
+
Shows what would be created, modified or removed. No changes are made.
|
|
217
|
+
|
|
218
|
+
```
|
|
219
|
+
+ template: linux-observability
|
|
220
|
+
+ item: CPU utilization (system.cpu.util)
|
|
221
|
+
+ item: Available memory (vm.memory.size[available])
|
|
222
|
+
+ trigger: High CPU utilization (>90% for 5 min)
|
|
223
|
+
+ discovery_rule: Mounted filesystem discovery
|
|
224
|
+
|
|
225
|
+
Plan: 4 to add, 0 to modify, 0 to remove
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### zbx apply
|
|
229
|
+
|
|
230
|
+
Applies the configuration. Shows the plan first, then prompts for confirmation.
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
zbx apply configs/ # interactive confirmation
|
|
234
|
+
zbx apply configs/ --auto-approve # skip confirmation (CI/CD)
|
|
235
|
+
zbx apply configs/ --dry-run # same as plan
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### zbx diff
|
|
239
|
+
|
|
240
|
+
Compares local YAML state against the current Zabbix configuration.
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
zbx diff configs/
|
|
244
|
+
zbx diff configs/templates/nginx.yaml
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### zbx validate
|
|
248
|
+
|
|
249
|
+
Validates YAML files against the schema without connecting to Zabbix.
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
zbx validate configs/
|
|
253
|
+
zbx validate configs/ --verbose
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### zbx export
|
|
257
|
+
|
|
258
|
+
Exports an existing Zabbix template to YAML. Use this to migrate existing
|
|
259
|
+
templates to Git.
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
zbx export "Linux by Zabbix agent"
|
|
263
|
+
zbx export "Linux by Zabbix agent" --output configs/templates/linux-zabbix-agent.yaml
|
|
264
|
+
zbx export linux # partial name search
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### zbx scaffold
|
|
268
|
+
|
|
269
|
+
Bootstraps a new self-contained monitoring check folder under `configs/checks/`.
|
|
270
|
+
The generated skeleton includes a `check.yaml`, a placeholder script and a `README.md`.
|
|
271
|
+
|
|
272
|
+
```bash
|
|
273
|
+
zbx scaffold my-check-name
|
|
274
|
+
# creates configs/checks/my-check-name/{check.yaml, my_check_name.py, README.md}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
After scaffolding, edit the generated files and follow the contributor workflow
|
|
278
|
+
described in [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
## Inventory and Host Management
|
|
283
|
+
|
|
284
|
+
### inventory.yaml
|
|
285
|
+
|
|
286
|
+
The inventory defines all hosts that should exist in Zabbix and how to connect
|
|
287
|
+
to them. It also defines agent-side deployment config (scripts and UserParameters).
|
|
288
|
+
|
|
289
|
+
```yaml
|
|
290
|
+
# inventory.yaml
|
|
291
|
+
|
|
292
|
+
hosts:
|
|
293
|
+
- host: webserver01
|
|
294
|
+
name: "Web Server 01"
|
|
295
|
+
ip: 192.168.1.101
|
|
296
|
+
port: 10050
|
|
297
|
+
groups:
|
|
298
|
+
- Linux servers
|
|
299
|
+
- Web servers
|
|
300
|
+
status: enabled
|
|
301
|
+
|
|
302
|
+
agent:
|
|
303
|
+
ssh_user: deploy
|
|
304
|
+
sudo: true
|
|
305
|
+
scripts:
|
|
306
|
+
- source: scripts/check_nginx.sh
|
|
307
|
+
dest: /usr/local/scripts/zabbix/check_nginx.sh
|
|
308
|
+
owner: zabbix
|
|
309
|
+
group: zabbix
|
|
310
|
+
mode: "0755"
|
|
311
|
+
userparameters:
|
|
312
|
+
- name: nginx
|
|
313
|
+
path: /etc/zabbix/zabbix_agentd.d/userparameters_nginx.conf
|
|
314
|
+
parameters:
|
|
315
|
+
- key: nginx.active_connections
|
|
316
|
+
command: /usr/local/scripts/zabbix/check_nginx.sh connections
|
|
317
|
+
- key: nginx.requests_per_sec
|
|
318
|
+
command: /usr/local/scripts/zabbix/check_nginx.sh rps
|
|
319
|
+
restart_agent: false
|
|
320
|
+
test_keys:
|
|
321
|
+
- nginx.active_connections
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
**Localhost shortcut:** If `ip` is `127.0.0.1`, `localhost`, or `::1`, zbx
|
|
325
|
+
skips SSH entirely and runs all commands locally via subprocess. No SSH key
|
|
326
|
+
setup required. `zbx agent deploy` will prompt for your sudo password once
|
|
327
|
+
at startup (hidden input) and use it for all writes to `/etc/zabbix/`.
|
|
328
|
+
|
|
329
|
+
### zbx inventory
|
|
330
|
+
|
|
331
|
+
```bash
|
|
332
|
+
zbx inventory list # table of all hosts in Zabbix
|
|
333
|
+
zbx inventory apply inventory.yaml # create or update hosts
|
|
334
|
+
zbx inventory apply inventory.yaml --dry-run
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
### zbx agent
|
|
338
|
+
|
|
339
|
+
The agent commands deploy scripts and UserParameters to monitored hosts.
|
|
340
|
+
Scripts are stored in `scripts/` (or inside a check folder) in the repo and
|
|
341
|
+
versioned in Git. zbx computes a SHA-256 checksum before every deploy —
|
|
342
|
+
only changed files are transferred.
|
|
343
|
+
|
|
344
|
+
```bash
|
|
345
|
+
zbx agent diff webserver01 # show what would change on the host
|
|
346
|
+
zbx agent deploy webserver01 # copy scripts, write userparameters
|
|
347
|
+
zbx agent deploy webserver01 --dry-run
|
|
348
|
+
zbx agent deploy webserver01 --auto-approve # skip confirmation (CI/CD)
|
|
349
|
+
zbx agent test webserver01 # run zabbix_agentd -t for each test_key
|
|
350
|
+
zbx agent test webserver01 --key nginx.active_connections # ad-hoc test
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
#### `--from-check` — deploy a self-contained check
|
|
354
|
+
|
|
355
|
+
If a check lives under `configs/checks/`, you can deploy its scripts and
|
|
356
|
+
UserParameters without touching `inventory.yaml`. zbx merges the check's
|
|
357
|
+
`agent:` block into the host's existing config automatically:
|
|
358
|
+
|
|
359
|
+
```bash
|
|
360
|
+
zbx agent diff webserver01 --from-check configs/checks/nginx/
|
|
361
|
+
zbx agent deploy webserver01 --from-check configs/checks/nginx/
|
|
362
|
+
zbx agent test webserver01 --from-check configs/checks/nginx/
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
For **remote hosts**, zbx connects over SSH (Paramiko). The user running zbx
|
|
366
|
+
must have SSH key access to the host. Password auth is not supported — use
|
|
367
|
+
`ssh-copy-id` to set up key-based auth first.
|
|
368
|
+
|
|
369
|
+
For **localhost**, zbx uses subprocess. If `sudo: true` is set in the agent
|
|
370
|
+
config, `zbx agent deploy` prompts for your sudo password once before making
|
|
371
|
+
any writes.
|
|
372
|
+
|
|
373
|
+
---
|
|
374
|
+
|
|
375
|
+
## Full Deployment Workflow
|
|
376
|
+
|
|
377
|
+
### Option A — traditional (script + separate template)
|
|
378
|
+
|
|
379
|
+
```bash
|
|
380
|
+
# 1. Add monitoring scripts to the repo
|
|
381
|
+
cp /path/to/script.py scripts/
|
|
382
|
+
git add scripts/script.py
|
|
383
|
+
|
|
384
|
+
# 2. Define the template (server side)
|
|
385
|
+
vim configs/templates/my-template.yaml
|
|
386
|
+
|
|
387
|
+
# 3. Define the inventory entry with agent config (host side)
|
|
388
|
+
vim inventory.yaml
|
|
389
|
+
|
|
390
|
+
# 4. Define the host playbook (template linking + macros)
|
|
391
|
+
vim configs/hosts/myhost.yaml
|
|
392
|
+
|
|
393
|
+
# 5. Deploy — server side
|
|
394
|
+
zbx validate configs/
|
|
395
|
+
zbx plan configs/
|
|
396
|
+
zbx apply configs/
|
|
397
|
+
|
|
398
|
+
# 6. Deploy — host agent side
|
|
399
|
+
zbx inventory apply inventory.yaml # ensure host exists in Zabbix
|
|
400
|
+
zbx agent diff myhost # preview
|
|
401
|
+
zbx agent deploy myhost # copy scripts + write userparameters
|
|
402
|
+
zbx agent test myhost # verify keys
|
|
403
|
+
|
|
404
|
+
# 7. Commit everything
|
|
405
|
+
git add configs/ scripts/ inventory.yaml
|
|
406
|
+
git commit -m "feat: add monitoring for myhost"
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
### Option B — self-contained check (recommended for new contributions)
|
|
410
|
+
|
|
411
|
+
```bash
|
|
412
|
+
# 1. Bootstrap the check folder
|
|
413
|
+
zbx scaffold my-check
|
|
414
|
+
|
|
415
|
+
# 2. Write the script and fill in check.yaml
|
|
416
|
+
vim configs/checks/my-check/my_check.py
|
|
417
|
+
vim configs/checks/my-check/check.yaml
|
|
418
|
+
|
|
419
|
+
# 3. Validate and preview
|
|
420
|
+
zbx validate configs/checks/my-check/
|
|
421
|
+
zbx plan configs/checks/my-check/
|
|
422
|
+
|
|
423
|
+
# 4. Apply the template to Zabbix
|
|
424
|
+
zbx apply configs/checks/my-check/
|
|
425
|
+
|
|
426
|
+
# 5. Deploy script to host (no inventory.yaml changes needed)
|
|
427
|
+
zbx agent deploy myhost --from-check configs/checks/my-check/
|
|
428
|
+
zbx agent test myhost --from-check configs/checks/my-check/
|
|
429
|
+
|
|
430
|
+
# 6. Commit
|
|
431
|
+
git add configs/checks/my-check/
|
|
432
|
+
git commit -m "feat(check): add my-check monitoring"
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
---
|
|
436
|
+
|
|
437
|
+
## YAML Schema Reference
|
|
438
|
+
|
|
439
|
+
### Template
|
|
440
|
+
|
|
441
|
+
| Field | Type | Required | Description |
|
|
442
|
+
|---|---|---|---|
|
|
443
|
+
| `template` | string | yes | Technical name (used as Zabbix host name) |
|
|
444
|
+
| `name` | string | no | Display name (defaults to `template`) |
|
|
445
|
+
| `description` | string | no | Human-readable description |
|
|
446
|
+
| `groups` | list[string] | no | Template groups (default: `["Templates"]`) |
|
|
447
|
+
| `items` | list[Item] | no | Monitored items |
|
|
448
|
+
| `triggers` | list[Trigger] | no | Alert triggers |
|
|
449
|
+
| `discovery_rules` | list[DiscoveryRule] | no | LLD rules |
|
|
450
|
+
|
|
451
|
+
### Item
|
|
452
|
+
|
|
453
|
+
| Field | Type | Default | Description |
|
|
454
|
+
|---|---|---|---|
|
|
455
|
+
| `name` | string | required | Display name |
|
|
456
|
+
| `key` | string | required | Zabbix item key |
|
|
457
|
+
| `interval` | string | `60s` | Collection interval (`30s`, `5m`, `1h`) |
|
|
458
|
+
| `type` | enum | `zabbix_agent` | Item type |
|
|
459
|
+
| `value_type` | enum | `float` | Data type |
|
|
460
|
+
| `units` | string | `""` | Unit label (`%`, `B`, `bps`) |
|
|
461
|
+
| `history` | string | `90d` | History retention |
|
|
462
|
+
| `trends` | string | `365d` | Trends retention |
|
|
463
|
+
| `enabled` | bool | `true` | Whether the item is active |
|
|
464
|
+
| `params` | string | `""` | Formula for `calculated` items; JSONPath/regex for `http_agent` |
|
|
465
|
+
|
|
466
|
+
Item types: `zabbix_agent`, `zabbix_agent_active`, `zabbix_trapper`,
|
|
467
|
+
`simple_check`, `calculated`, `http_agent`, `snmp_v2c`, `dependent`
|
|
468
|
+
|
|
469
|
+
> **`calculated` items require `params`** — set it to the formula string,
|
|
470
|
+
> e.g. `params: "avg(/mytemplate/my.key,5m)"`. Omitting it causes
|
|
471
|
+
> `Invalid parameter "/1": the parameter "params" is missing` from the API.
|
|
472
|
+
|
|
473
|
+
Value types: `float`, `unsigned`, `char`, `text`, `log`
|
|
474
|
+
|
|
475
|
+
### ItemPrototype (inside DiscoveryRule)
|
|
476
|
+
|
|
477
|
+
| Field | Type | Default | Description |
|
|
478
|
+
|---|---|---|---|
|
|
479
|
+
| `name` | string | required | Display name |
|
|
480
|
+
| `key` | string | required | Item key (may contain LLD macros) |
|
|
481
|
+
| `type` | enum | `zabbix_agent` | Item type |
|
|
482
|
+
| `value_type` | enum | `float` | Data type |
|
|
483
|
+
| `master_item_key` | string | no | Key of master item (for `dependent` type) |
|
|
484
|
+
| `preprocessing` | list[Preprocessing] | `[]` | Preprocessing steps |
|
|
485
|
+
|
|
486
|
+
Preprocessing types: `jsonpath`, `regex`, `multiplier`, `trim`,
|
|
487
|
+
`not_match_regex`, `check_not_supported`, `discard_unchanged`
|
|
488
|
+
|
|
489
|
+
### Trigger
|
|
490
|
+
|
|
491
|
+
| Field | Type | Default | Description |
|
|
492
|
+
|---|---|---|---|
|
|
493
|
+
| `name` | string | required | Trigger name |
|
|
494
|
+
| `expression` | string | required | Zabbix trigger expression |
|
|
495
|
+
| `severity` | enum | `average` | Alert severity |
|
|
496
|
+
| `description` | string | `""` | Description or runbook notes |
|
|
497
|
+
| `enabled` | bool | `true` | Whether the trigger is active |
|
|
498
|
+
|
|
499
|
+
Severities: `not_classified`, `information`, `warning`, `average`, `high`, `disaster`
|
|
500
|
+
|
|
501
|
+
### DiscoveryRule
|
|
502
|
+
|
|
503
|
+
| Field | Type | Default | Description |
|
|
504
|
+
|---|---|---|---|
|
|
505
|
+
| `name` | string | required | Rule name |
|
|
506
|
+
| `key` | string | required | LLD key |
|
|
507
|
+
| `interval` | string | `1h` | Discovery interval |
|
|
508
|
+
| `type` | enum | `zabbix_agent` | Same values as Item type |
|
|
509
|
+
| `item_prototypes` | list[ItemPrototype] | `[]` | Item prototypes |
|
|
510
|
+
| `trigger_prototypes` | list[TriggerPrototype] | `[]` | Trigger prototypes |
|
|
511
|
+
|
|
512
|
+
### Host (playbook)
|
|
513
|
+
|
|
514
|
+
```yaml
|
|
515
|
+
host: myhost # must match the technical hostname in Zabbix
|
|
516
|
+
templates:
|
|
517
|
+
- linux-observability # templates to link
|
|
518
|
+
- custom-template
|
|
519
|
+
macros:
|
|
520
|
+
- macro: "{$THRESHOLD}"
|
|
521
|
+
value: "90"
|
|
522
|
+
description: "Alert threshold percentage"
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
### InventoryHost
|
|
526
|
+
|
|
527
|
+
```yaml
|
|
528
|
+
host: myhost
|
|
529
|
+
name: "My Host Display Name"
|
|
530
|
+
ip: 192.168.1.100
|
|
531
|
+
port: 10050
|
|
532
|
+
groups:
|
|
533
|
+
- Linux servers
|
|
534
|
+
description: "Optional description"
|
|
535
|
+
status: enabled # enabled or disabled
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
---
|
|
539
|
+
|
|
540
|
+
## Project Structure
|
|
541
|
+
|
|
542
|
+
```
|
|
543
|
+
zbx/
|
|
544
|
+
├── zbx/
|
|
545
|
+
│ ├── cli.py Typer app + command registration
|
|
546
|
+
│ ├── models.py Pydantic models (Template, Item, Trigger, DiscoveryRule,
|
|
547
|
+
│ │ Host, InventoryHost, AgentConfig, ScriptDeploy, ...)
|
|
548
|
+
│ ├── config_loader.py YAML loading and schema validation
|
|
549
|
+
│ ├── zabbix_client.py Zabbix JSON-RPC HTTP client (version-aware auth)
|
|
550
|
+
│ ├── diff_engine.py Desired vs current state comparison
|
|
551
|
+
│ ├── deployer.py Apply logic for templates and hosts
|
|
552
|
+
│ ├── agent_deployer.py SSH/local agent deployment (scripts + UserParameters)
|
|
553
|
+
│ ├── formatter.py Rich CLI output
|
|
554
|
+
│ └── commands/
|
|
555
|
+
│ ├── apply.py zbx apply
|
|
556
|
+
│ ├── plan.py zbx plan
|
|
557
|
+
│ ├── diff.py zbx diff
|
|
558
|
+
│ ├── validate.py zbx validate
|
|
559
|
+
│ ├── export.py zbx export
|
|
560
|
+
│ ├── scaffold.py zbx scaffold
|
|
561
|
+
│ ├── inventory.py zbx inventory list / apply
|
|
562
|
+
│ └── agent.py zbx agent diff / deploy / test
|
|
563
|
+
├── configs/
|
|
564
|
+
│ ├── templates/ Standalone template YAML files
|
|
565
|
+
│ │ ├── linux-observability.yaml
|
|
566
|
+
│ │ └── nginx.yaml
|
|
567
|
+
│ ├── checks/ Self-contained monitoring checks
|
|
568
|
+
│ │ ├── CONTRIBUTING.md How to add a new check
|
|
569
|
+
│ │ └── s3-monitoring/ Reference example
|
|
570
|
+
│ │ ├── check.yaml template + agent deployment block
|
|
571
|
+
│ │ └── README.md
|
|
572
|
+
│ └── hosts/ Host playbook YAML files
|
|
573
|
+
│ └── zabbixtest3100.yaml
|
|
574
|
+
├── scripts/ Agent scripts (legacy; prefer configs/checks/ for new work)
|
|
575
|
+
│ └── README.md
|
|
576
|
+
├── inventory.yaml Host inventory (groups, IPs, agent config)
|
|
577
|
+
├── .github/
|
|
578
|
+
│ ├── workflows/
|
|
579
|
+
│ │ └── ai-maintainer.yml Automated issue processing via Claude
|
|
580
|
+
│ └── scripts/
|
|
581
|
+
│ └── ai_maintainer.py Agentic implementation
|
|
582
|
+
├── CONTRIBUTING.md
|
|
583
|
+
├── pyproject.toml
|
|
584
|
+
├── .env.example
|
|
585
|
+
└── README.md
|
|
586
|
+
```
|
|
587
|
+
|
|
588
|
+
---
|
|
589
|
+
|
|
590
|
+
## Zabbix API Compatibility
|
|
591
|
+
|
|
592
|
+
| Zabbix version | Notes |
|
|
593
|
+
|---|---|
|
|
594
|
+
| < 5.4 | `user` field in login |
|
|
595
|
+
| >= 5.4 | `username` field in login |
|
|
596
|
+
| >= 6.2 | Templates require `templategroup`, not `hostgroup` |
|
|
597
|
+
| >= 6.4 | Auth token sent as `Authorization: Bearer` header (not in payload) |
|
|
598
|
+
|
|
599
|
+
zbx detects the API version on first connect via `apiinfo.version` and
|
|
600
|
+
adjusts automatically.
|
|
601
|
+
|
|
602
|
+
---
|
|
603
|
+
|
|
604
|
+
## Git Workflow
|
|
605
|
+
|
|
606
|
+
```bash
|
|
607
|
+
git checkout -b monitoring/add-redis-template
|
|
608
|
+
|
|
609
|
+
vim configs/templates/redis.yaml
|
|
610
|
+
|
|
611
|
+
zbx validate configs/templates/redis.yaml
|
|
612
|
+
|
|
613
|
+
ZBX_URL=http://zabbix-staging zbx plan configs/templates/redis.yaml
|
|
614
|
+
|
|
615
|
+
git add configs/templates/redis.yaml
|
|
616
|
+
git commit -m "feat: add Redis monitoring template"
|
|
617
|
+
git push origin monitoring/add-redis-template
|
|
618
|
+
|
|
619
|
+
# After PR approval
|
|
620
|
+
zbx apply configs/templates/redis.yaml --auto-approve
|
|
621
|
+
```
|
|
622
|
+
|
|
623
|
+
---
|
|
624
|
+
|
|
625
|
+
## CI/CD Integration
|
|
626
|
+
|
|
627
|
+
```yaml
|
|
628
|
+
# .github/workflows/zbx-apply.yml
|
|
629
|
+
name: Deploy monitoring config
|
|
630
|
+
|
|
631
|
+
on:
|
|
632
|
+
push:
|
|
633
|
+
branches: [main]
|
|
634
|
+
paths: [configs/**]
|
|
635
|
+
|
|
636
|
+
jobs:
|
|
637
|
+
apply:
|
|
638
|
+
runs-on: ubuntu-latest
|
|
639
|
+
steps:
|
|
640
|
+
- uses: actions/checkout@v4
|
|
641
|
+
- uses: actions/setup-python@v5
|
|
642
|
+
with:
|
|
643
|
+
python-version: "3.11"
|
|
644
|
+
- run: pip install -e .
|
|
645
|
+
- run: zbx validate configs/
|
|
646
|
+
- run: zbx apply configs/ --auto-approve
|
|
647
|
+
env:
|
|
648
|
+
ZBX_URL: ${{ secrets.ZBX_URL }}
|
|
649
|
+
ZBX_USER: ${{ secrets.ZBX_USER }}
|
|
650
|
+
ZBX_PASSWORD: ${{ secrets.ZBX_PASSWORD }}
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
---
|
|
654
|
+
|
|
655
|
+
## Safety Behaviour
|
|
656
|
+
|
|
657
|
+
- zbx never deletes items, triggers or discovery rules that exist in Zabbix
|
|
658
|
+
but are absent from config. It logs a warning instead. Removal must be done
|
|
659
|
+
manually — this is an intentional safety net.
|
|
660
|
+
- `zbx apply` always shows the plan and asks for confirmation unless
|
|
661
|
+
`--auto-approve` is passed.
|
|
662
|
+
- All write operations are idempotent — running `zbx apply` twice produces
|
|
663
|
+
the same result.
|
|
664
|
+
- `zbx agent deploy` uses SHA-256 checksums to skip files that have not
|
|
665
|
+
changed.
|
|
666
|
+
|
|
667
|
+
---
|
|
668
|
+
|
|
669
|
+
## Extending zbx
|
|
670
|
+
|
|
671
|
+
| What to add | Where |
|
|
672
|
+
|---|---|
|
|
673
|
+
| New resource type (host groups, macros) | Model in `models.py`, CRUD in `zabbix_client.py`, diff in `diff_engine.py`, apply in `deployer.py` |
|
|
674
|
+
| New CLI command | `zbx/commands/<cmd>.py`, registered in `cli.py` |
|
|
675
|
+
| Custom output format | `formatter.py` |
|
|
676
|
+
| New agent check step | `agent_deployer.py` |
|
|
677
|
+
| New monitoring check | `zbx scaffold <name>` → fill in `configs/checks/<name>/` |
|
|
678
|
+
|
|
679
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for the full contributor guide.
|
|
680
|
+
|
|
681
|
+
---
|
|
682
|
+
|
|
683
|
+
## AI Maintainer
|
|
684
|
+
|
|
685
|
+
The repository includes a GitHub Actions workflow that automatically processes
|
|
686
|
+
issues labeled **`ai-task`** using **Claude** (via GitHub Models API).
|
|
687
|
+
|
|
688
|
+
### How it works
|
|
689
|
+
|
|
690
|
+
1. Open an issue describing the change, bug fix or new check needed.
|
|
691
|
+
2. Add the `ai-task` label.
|
|
692
|
+
3. The workflow triggers, runs an agentic loop:
|
|
693
|
+
- reads the issue and explores the codebase,
|
|
694
|
+
- writes the necessary files,
|
|
695
|
+
- validates any YAML,
|
|
696
|
+
- commits and pushes to a new branch,
|
|
697
|
+
- opens a pull request.
|
|
698
|
+
4. A comment is posted on the issue with a link to the PR.
|
|
699
|
+
|
|
700
|
+
### Writing effective `ai-task` issues
|
|
701
|
+
|
|
702
|
+
Be specific. Good example:
|
|
703
|
+
|
|
704
|
+
> **Add a PostgreSQL monitoring check**
|
|
705
|
+
>
|
|
706
|
+
> Add `configs/checks/postgres/` that monitors:
|
|
707
|
+
> - Active connections (`pg_stat_activity` count) — trigger: warning > 200, high > 400
|
|
708
|
+
> - Replication lag in seconds
|
|
709
|
+
> - Database size in bytes
|
|
710
|
+
>
|
|
711
|
+
> Script should output plain numbers. Use `psql` to query.
|
|
712
|
+
|
|
713
|
+
### Manual re-run
|
|
714
|
+
|
|
715
|
+
**Actions → AI Maintainer → Run workflow** → enter the issue number.
|
|
716
|
+
|
|
717
|
+
---
|
|
718
|
+
|
|
719
|
+
## License
|
|
720
|
+
|
|
721
|
+
MIT
|
|
722
|
+
|