Orchestrata Ultimate › Gates › fleet-drift

Gate: fleet-drift (ADR-0077)

Purpose Detect drift between the OpenTofu declaration and the live Incus fleets, and between terraform and the committed env/*.env endpoints, "instead of discovered"
Where it runs scripts/check_infra_drift.py: the user unit orchestrata-infra-drift.service on orchestrata-infra-drift.timer (hourly), and scripts/health_check.py. scripts/check_env_fleet_agreement.py: the orchestrata arm of deploy/ship.sh verify
Trigger The timer; every ship of orchestrata-ultimate
Exact command /opt/orchestrata/.venv/bin/python /opt/orchestrata/scripts/check_infra_drift.py --report /var/lib/orchestrata/terraform/drift-latest.json (unit ExecStart); uv run python scripts/check_env_fleet_agreement.py (ship)
Blocks Infra drift: exit 1 on drift, bridge drift, a missing state, no usable binary, or an init, plan or output error; a failed drift unit then fails the promote's verify stage. Env agreement: exit 1 fails the ship with "env files drifted from terraform"
Ruling / ADR ADR-0077 item 4 ("missing is FAIL, never skip"); related: RUL-003 (configuration from env files)

Both gates were added on 2026-10-08: the drift gate and its timer in f2cef12cb ("execute ADR-0077 — every Incus environment imported into OpenTofu, zero-diff, drift gate + timer"), the agreement gate in 96087d9ce and its ship wiring in 8d6a282dc.

Infra drift: check_infra_drift.py

From the module docstring (AST toolkit, 2026-10-23):

  1. tofu plan -detailed-exitcode over infra/terraform: exit 0 is zero-diff, exit 2 is drift ("a container, bridge, ACL or profile no longer matches the declaration"), anything else is a tool error.
  2. The three bridge keys the provider never writes to state (ipv4.address, ipv4.nat, ipv6.address) are proven live with incus network get against the root's bridge_expected_config output, "so the plan's silence on them is never mistaken for proof".

Verdicts, as run_gate writes them into the JSON report: zero-diff (exit 0), no-root (exit 0 with a NOTE, for a checkout with no IaC root), missing-state, no-binary, init-error, drift, plan-error, bridge-drift (all exit 1). "A missing state is a failure, never a skip: the September state was lost to a worktree gc and nothing noticed."

Diagram projects-orchestrata-ultimate-gates-fleet-drift-1

Measured state, 2026-10-23. orchestrata-infra-drift.timer is disabled and inactive. The last report, /var/lib/orchestrata/terraform/drift-latest.json, was written at 2026-10-22T19:01:27+00:00: verdict drift, plan_exit 2, 18 drift lines, no bridge drift, binary ~/bin/tofu. The session's improvement log records the history as finding F5: the gate "has been red since 2026-10-20 10:00 (last pass 09:02); its timer then stopped firing until the promote's assets stage re-armed it, and with Persistent=true it fired at once and failed the promote's verify stage." The planned correction: 3 to add (prolog node-1..3), 14 to change. The causes are listed on the Deployment page.

Env agreement: check_env_fleet_agreement.py

env/test.env, env/dev.env and the TEST_* keys of .env.example are derived from tofu output -json by infra/gen_env.py. The gate (FleetAgreementGate.check) re-derives them for the test and dev profiles and fails on:

The prod profile is not gated: env/prod.env "deliberately routes through the coordinators". Why it exists, from the docstring: on 2026-10-08 .env.example had carried TEST_MEMGRAPH_URI on the retired prod-bridge address for two months with nothing checking it; and the 2026-09-21 CHANGEME sweep had commented TEST_MEMGRAPH_URI out of the host .env.

Output: one FAIL: <file>: <KEY>: declared '<value>', derived '<value>' line per violation, or env/fleet agreement OK: test, dev derived from terraform match their committed files and .env.example. Every recorded ship log of 2026-10-22 read for these pages (orch_ship10 to orch_ship14_promote, ship15_nopromote) printed the OK line.

Typical failures and how to fix them

Symptom Fix
DRIFT: ... lines from the drift gate The infra/README.md rule: "A diff means the .tf must change to match reality - never the reverse." Change the .tf, or apply a change Mohamed ruled
MISSING STATE: ... the fleet is not imported Run infra/terraform/import.sh (ADR-0077 items 3–4); the state lives at /var/lib/orchestrata/terraform/fleet.tfstate, never in a checkout
no OpenTofu Set $TOFU, put tofu on PATH, or install a terraform at or above the 1.6.0 floor
A promote fails its verify stage on the drift unit The drift gate is red (F5 above); fix the drift, not the promote
Ship fails "env files drifted from terraform" uv run python infra/gen_env.py --profile test --write env/test.env (the ship message); never hand-edit a derived key