homelab/services/device-inventory/README.md
Dan V e1a482c500 feat(device-inventory): add hooks system and DNS updater hook
- Add Hook interface (filter + execute contract) in server/hooks/hook.h
- Add HookRunner in server/hooks/hook_runner.h: spawns a detached thread
  per matching hook, with try/catch protection against crashes
- Add DnsUpdaterHook in server/hooks/dns_updater_hook.{h,cpp}:
  triggers on server name changes, logs in to Technitium, deletes the
  old A record (ignores 404), and adds the new A record
  Config via env vars: TECHNITIUM_HOST/PORT/USER/PASS/ZONE, DNS_TTL
- Add Database::get_nics_for_server() to resolve a server's IPv4 address
- Wire HookRunner into InventoryServer; cmd_edit_server now fires hooks
  with before/after Server snapshots
- Update CMakeLists.txt to include dns_updater_hook.cpp
- Document env vars in Dockerfile

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-24 14:58:36 +01:00

138 lines
3.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# device-inventory
A lightweight hardware inventory tracker built in C++17.
Uses a **client/server** model: the server owns the file-backed database and
exposes a TCP interface on localhost; the CLI client connects to it to run
commands.
---
## Architecture
```
┌──────────────┐ TCP (localhost:9876) ┌─────────────────────┐
│ inventory-cli│ ─────────────────────► │ inventory-server │
│ (CLI client)│ ◄───────────────────── │ database ► file.db │
└──────────────┘ └─────────────────────┘
```
* **inventory-server** loads the inventory file on start, accepts one
command per connection, and flushes changes to disk after every mutation.
* **inventory-cli** a thin CLI that translates subcommands into protocol
messages, connects to the server, and pretty-prints the response.
---
## Build
Requires CMake ≥ 3.16 and a C++17-capable compiler.
```bash
cd device-inventory
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build
```
Binaries end up in `build/inventory-server` and `build/inventory-cli`.
---
## Running
### Start the server
```bash
./build/inventory-server # uses inventory.db in CWD
./build/inventory-server --port 9876 --db /var/lib/inventory/data.db
```
The server reloads the file every time it restarts. On the very first run the
file is created automatically.
### Use the CLI
```bash
# Shorthand for the examples below
cli="./build/inventory-cli"
```
---
## Commands
### Servers
```bash
# Add a server
$cli add-server "web01" "192.168.1.10" "Rack A" "Primary web server"
# List all servers
$cli list-servers
# Edit a field (fields: name | hostname | location | description)
$cli edit-server 1 hostname "10.0.0.1"
$cli edit-server 1 description "Retired do not use"
```
### Part types
```bash
# Add a part type
$cli add-part-type "RAM" "Memory modules"
$cli add-part-type "SSD" "Solid-state storage"
# List all part types
$cli list-part-types
# Edit a field (fields: name | description)
$cli edit-part-type 1 description "DDR4/DDR5 memory"
```
### Parts
```bash
# Add a part to a server
# add-part <server_id> <part_type_id> <name> <serial> <description>
$cli add-part 1 1 "16 GB DDR4" "SN-MEM-001" "DIMM slot A1"
$cli add-part 1 2 "Samsung 870 EVO 1 TB" "SN-SSD-004" "Primary OS drive"
# List parts of a server
$cli list-parts 1
# Edit a field (fields: name | serial | description | server_id | part_type_id)
$cli edit-part 2 serial "SN-SSD-005"
$cli edit-part 2 server_id 3
```
---
## Database file format
Plain text, one record per line safe to inspect or diff with standard tools.
```
# device-inventory database
META|<next_server_id>|<next_part_type_id>|<next_part_id>
S|<id>|<name>|<hostname>|<location>|<description>
PT|<id>|<name>|<description>
P|<id>|<server_id>|<part_type_id>|<name>|<serial>|<description>
```
Pipe characters and backslashes inside field values are escaped with `\|`
and `\\` respectively.
---
## Wire protocol
Commands are newline-terminated lines; fields are separated by ASCII SOH
(`0x01`). Each connection carries exactly one request/response pair.
```
Client → Server: COMMAND\x01arg1\x01arg2\n
Server → Client: OK\n
field1\x01field2\x01...\n ← 0 or more data rows
END\n
-- or --
ERR <message>\n
```