Repository navigation
Converge one Domain and record the vhost a run replaced - #133
Conversation
domains.yml takes cloudfall_domains_domain_id and renders only that Domain; the converge_domains MCP tool gains an optional domain that limits the run to the Domain's proxy server and refuses an unknown id before the inventory render. Without it the tool runs as before. The nginx site role hashes the file at proxy.configurationPath before its first render, and the DeploymentReceipt records it as previousConfigurationSha256 (null when no file was there). The schema change is additive, so older receipts still load. Fixes #116 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A link at proxy.configurationPath (the Debian sites-enabled layout) gave stat no checksum, so the receipt task failed after the render went live. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…attern Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2769e37 to
21ee8e5
Compare
|
@romamo Decided without waiting: Why: S-004-2, S-004-11 and S-004-17 ask for exactly this; the receipt field is optional, so older receipts still load. Without Reply with a comment starting with |
Summary
The engine side of spec 004 (
docs/specs/004-domains-apply.md):domains.ymltakescloudfall_domains_domain_idand renders only that Domain; without it the loop is the same as before. The playbook edit is theloop:expression onlyconverge_domainsMCP tool gains an optionaldomain. Given, the SDK looks the Domain up in the validated config, runsdomains.ymlwith--limit <proxy.server>and the domain id, so no other host is contacted; an unknown id exitsPRECONDITION(lifecycle_domain_missing) before the inventory render. Omitted, the argv and extra vars are exactly today's. The tool's handling moved intocloudfall.lifecycle.converge_domains(DomainsRun), andrun_engine_playbooktakes an optionallimitcloudfall_nginx_sitehashes the file atproxy.configurationPathonce, before its first render, and the receipt records it aspreviousConfigurationSha256(nullwhen no file was there). The receipt schema gains the optional field (sha256 or null), so receipts without it still loadThe
cloudfall domains applycommand is #117; the criteria here are proven at the engine and MCP layer.Fixes #116
Test plan
engine/tests/test_domains_one_domain.py: the realdomains.ymlloop evaluated with Ansible's templating (S-004-2, S-004-17); the role's own receipt tasks run for real byansible-playbookon localhost against a hand-written vhost and against no file, receipt validated against the schema (S-004-11)sdk/tests/test_domains_converge.py: argv of the run for one Domain (--limit h2, the domain id) and without one (unchanged), unknown id refused before any step, a failing playbook (a rejectednginx -t) surfaces aslifecycle_execution_failed, which the tool answers asENGINE_STEP_FAILED(S-004-2, S-004-13, S-004-17);converge_domainsover the realmcp servestdio transport with an unknown domain (S-004-17);services statusloads a receipt without the field, withnull, and with a hash, and refuses a malformed one (S-004-12)uv run ruff check .,uv run mypy,ansible-playbook --syntax-checkondomains.yml, and the tests of the touched files pass locally.ansible-lint engine/ansiblereported only role-not-found syntax errors on playbooks this PR doesn't touch, becauseANSIBLE_CONFIGcould not be set in this session; CI sets itdomains.ymlon a Debian host with Nginx. The full suite is left to CIPlan
domain, each with its testspecs.py coverage --spec 004)🤖 Generated with Claude Code