docs: migrate worker implementation plans
Все проверки выполнены успешно
CI / test (push) Successful in 30s
Docker / Build and publish worker image (push) Successful in 10m49s
Все проверки выполнены успешно
CI / test (push) Successful in 30s
Docker / Build and publish worker image (push) Successful in 10m49s
Этот коммит содержится в:
165
docs/inventory.md
Обычный файл
165
docs/inventory.md
Обычный файл
@@ -0,0 +1,165 @@
|
||||
# Worker Host Inventory
|
||||
|
||||
## Purpose And Boundary
|
||||
|
||||
Inventory connects checks to the host, service, Compose project, domain, and
|
||||
deployment that they observe. The worker collects facts; the RSMon control
|
||||
plane validates identity, applies account scope, reconciles lifecycle, and
|
||||
persists the inventory projection.
|
||||
|
||||
The control-plane inventory entities remain `Server`, `ServerIp`, `Site`,
|
||||
`Deployment`, `Domain`, `Repo`, and `site_repos`. Their API and rstuff stream
|
||||
projection are control-plane concerns. This repository owns only local
|
||||
discovery and worker-originated reports.
|
||||
|
||||
## Existing Collectors
|
||||
|
||||
Current state:
|
||||
|
||||
- `internal/webapp/inventory.go` discovers Linux processes, command lines,
|
||||
working directories, TCP listeners, and basic resource facts.
|
||||
- snapshots are stored in the local web-console SQLite database;
|
||||
- `internal/distworker/server_metrics.go` reports bounded process/network host
|
||||
snapshots, but not normalized application inventory;
|
||||
- external `deploymentd` remains the implemented authoritative collector for
|
||||
nginx, Docker Compose, and host inventory on the control plane.
|
||||
|
||||
The worker does not currently send an inventory report to the control plane.
|
||||
It must not claim deploymentd parity until the protocol, ingestion, and
|
||||
reconciliation tests below are complete.
|
||||
|
||||
## Target Package Layout
|
||||
|
||||
Move collection ownership out of `internal/webapp`:
|
||||
|
||||
```text
|
||||
internal/inventory/
|
||||
collector.go orchestration and partial-success envelope
|
||||
process_linux.go procfs process and listener discovery
|
||||
docker.go Docker and Compose discovery behind capability
|
||||
nginx.go read-only nginx virtual-host discovery
|
||||
systemd.go allowlisted unit discovery
|
||||
normalize.go stable IDs and control-plane report conversion
|
||||
store.go optional local snapshot interface
|
||||
```
|
||||
|
||||
The web console consumes a read-only snapshot interface. The runner consumes a
|
||||
bounded report interface. Collectors return per-section errors; one failed
|
||||
section does not discard successful sections.
|
||||
|
||||
## Report Contract
|
||||
|
||||
Add a typed `WorkerInventoryReport` branch to `internal/wire`:
|
||||
|
||||
```json
|
||||
{
|
||||
"kind": "result",
|
||||
"inventory": {
|
||||
"schema": "rsmon.worker.inventory.v1",
|
||||
"report_id": "uuid",
|
||||
"server_id": 42,
|
||||
"collected_at": "2026-07-13T15:00:00Z",
|
||||
"full_snapshot": true,
|
||||
"host": {},
|
||||
"addresses": [],
|
||||
"processes": [],
|
||||
"compose_projects": [],
|
||||
"nginx_sites": [],
|
||||
"systemd_units": [],
|
||||
"errors": [{"section": "docker", "code": "unavailable"}]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Constraints:
|
||||
|
||||
- `report_id` is stable across transport retries and unique across collection
|
||||
runs.
|
||||
- `server_id` comes from authenticated `WorkerInit.ServerID`, never local env.
|
||||
- A full snapshot permits missing-item reconciliation; partial reports do not.
|
||||
- Section and total item counts, strings, labels, and serialized bytes are
|
||||
bounded before enqueue.
|
||||
- Environment variable values, file contents, process environments, container
|
||||
secrets, and Compose `.env` values are never included.
|
||||
- The control plane rejects a report when the worker is not linked to the
|
||||
server or the private worker's account does not own it.
|
||||
|
||||
## Normalization
|
||||
|
||||
Stable local identity keys:
|
||||
|
||||
- process app: executable plus canonical working directory;
|
||||
- Compose site: Docker Compose project name plus canonical project directory;
|
||||
- Compose deployment: project plus service name;
|
||||
- nginx deployment: canonical config path;
|
||||
- domain: normalized lowercase hostname without trailing dot;
|
||||
- systemd service: unit name.
|
||||
|
||||
Container IDs and PIDs are observations, not stable entity IDs. Never use them
|
||||
as the sole upsert key. Every deployment includes `last_seen_at`; only a full
|
||||
successful section can mark previously observed entities missing.
|
||||
|
||||
## Collector Requirements
|
||||
|
||||
### Processes
|
||||
|
||||
- Group related processes deterministically by executable, working directory,
|
||||
and parent relationship.
|
||||
- Parse TCP and UDP listeners for IPv4 and IPv6.
|
||||
- Do not read another process's environment.
|
||||
- Exclude kernel threads and the worker itself from application suggestions.
|
||||
|
||||
### Docker And Compose
|
||||
|
||||
- Disabled without an explicit Docker capability.
|
||||
- Prefer Docker/Compose JSON output and labels; do not parse human tables.
|
||||
- Collect project, service, image, state, ports, mount paths, health, and
|
||||
Traefik host rules. Exclude environment values and registry credentials.
|
||||
- Treat Docker socket access as root-equivalent and report the capability to
|
||||
the operator.
|
||||
|
||||
### Nginx
|
||||
|
||||
- Read only configured allowlisted roots.
|
||||
- Collect config path, listen values, server names, auth presence, root path,
|
||||
and proxy presence. Do not send certificate private-key paths or contents.
|
||||
|
||||
### Host And Server IPs
|
||||
|
||||
- Collect hostname, OS/kernel summary, and valid non-loopback addresses.
|
||||
- Do not guess a primary address; report interface and route metadata so the
|
||||
control plane can apply policy.
|
||||
|
||||
## Relationship To deploymentd And rstuff
|
||||
|
||||
Worker reports and deploymentd ingest are complementary producers of the same
|
||||
control-plane projection. During migration:
|
||||
|
||||
- deploymentd remains authoritative for sections it currently reports;
|
||||
- worker inventory is feature-gated per server;
|
||||
- every row records source and source report ID;
|
||||
- reconciliation occurs per source and section to prevent one producer from
|
||||
deleting another producer's observations;
|
||||
- the rstuff `rsmon.inventory.v1` stream remains a control-plane output/input,
|
||||
not a worker protocol.
|
||||
|
||||
## Delivery Phases
|
||||
|
||||
1. Start and stop the existing process collector; move it behind an interface.
|
||||
2. Add typed report and control-plane ingestion for process/host/address data.
|
||||
3. Add read-only Docker and Compose discovery.
|
||||
4. Add nginx and systemd discovery.
|
||||
5. Add source-aware reconciliation and deploymentd comparison mode.
|
||||
6. Enable monitor suggestions only after operators confirm discovered targets.
|
||||
|
||||
## Acceptance Tests
|
||||
|
||||
- A worker restart preserves no false stable identity based on PID/container ID.
|
||||
- A failed Docker section does not erase successful nginx or process data.
|
||||
- Partial reports never mark absent deployments missing.
|
||||
- Full reports reconcile only rows owned by the same source and section.
|
||||
- Cross-account and worker/server mismatch reports are rejected.
|
||||
- Fixture snapshots prove no environment values or credential-like fields are
|
||||
serialized.
|
||||
- Worker and deploymentd fixtures normalize equivalent Compose/nginx entities
|
||||
to the same control-plane identity without deleting each other's rows.
|
||||
Ссылка в новой задаче
Block a user