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 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
+