Skip to content

fix: retire deactivated-profile containers on apply/upgrade (#795) - #806

Closed
VijitSingh97 wants to merge 2 commits into
developfrom
fix/795-apply-profile-deactivation
Closed

fix: retire deactivated-profile containers on apply/upgrade (#795)#806
VijitSingh97 wants to merge 2 commits into
developfrom
fix/795-apply-profile-deactivation

Conversation

@VijitSingh97

Copy link
Copy Markdown
Collaborator

Closes #795

Root cause

apply never stops a deactivated-profile container itself — it delegated the whole cleanup to docker compose up -d --remove-orphans, whose comment claimed "--remove-orphans drops monerod when a local→remote switch deactivates the local_node profile". That claim doesn't hold: a profile-disabled service is still defined, so compose does not count its container as an orphan — and while the container survives, newer compose treats the service as enabled again. Net effect on the bench repro: the switch dropped local_tari from COMPOSE_PROFILES, then the TARI_MEM_LIMIT diff that rides every tari switch (auto-calc → the remote-mode 0m placeholder) made the same compose up recreate the node the switch had just turned off.

So the issue's hypothesis was close but the mechanism is one level down: there is no pithead-built recreate list at all — the "recreate set" is compose's own resolved-config diff, and the bug was that nothing removed the container before compose ran, so compose still considered the service live.

monerod was equally affected (local_node, same delegation to --remove-orphans#103's e2e only ever proved fresh-remote), and so were the two payout-confirmation wallets (wallet-rpc/payout_confirm, tari-wallet/tari_payout_confirm) when a view key is cleared. upgrade re-renders .env from config.json too, so a mode switch staged in config could land there with the same hole.

Fix

One shared guard, remove_deactivated_profile_containers: after the .env commit and before the recreate up, stop and remove every container whose compose profile is not active in the committed .env (the four profile-gated services). Keyed off the committed .env rather than this run's diff, so an interrupted apply's marker retry (#125 path) converges too. Called from both apply and upgrade. Bind-mounted chain data is untouched, exactly as the apply preview always promised.

Coverage

Stack tier (the lowest tier that honestly proves the transition): the shared docker stub now models per-service container state as flag files (compose --profile X ps -aq svc / rm -sf svc), and new black-box cases drive the real apply through:

  • tari local→remote: container absent afterwards, monerod untouched, operator told, and the removal lands before the recreate up;
  • monerod local→remote: same end state;
  • steady remote-state re-apply: no container found, no removal message.

Testing

  • tests/stack/run.sh: 1693 passed, 0 failed
  • tests/stack/test_compose.sh: green
  • make lint: green
  • Patch coverage: bash-only diff — diff-cover has no Python lines to measure here; the stack suite above is the owning tier.

🤖 Generated with Claude Code

VijitSingh97 and others added 2 commits July 31, 2026 23:46
A local→remote node switch dropped the node's profile token from
COMPOSE_PROFILES, but nothing stopped the running container: compose
does not treat a profile-disabled service as an orphan (the
--remove-orphans comment claimed otherwise), and while the container
survives, newer compose treats the service as enabled again — so the
TARI_MEM_LIMIT diff that rides every tari switch recreated the very
node the switch had just removed, leaving a full minotari node running
offline against a remote-mode config.

apply and upgrade now stop and remove every container whose compose
profile the committed .env switched off — monerod (local_node), tari
(local_tari), and the two payout-confirmation wallets — before the
recreate `up`, keyed off the committed .env (not this run's diff) so
an interrupted apply's marker retry converges too. Bind-mounted chain
data is untouched.

Stack tier covers the transition end-to-end: the docker stub models
per-service container state as flag files, and the new cases drive the
tari and monerod local→remote switches through the real apply and
assert the container is absent afterwards (plus removal-before-up
ordering, and a quiet steady-state re-apply).

Closes #795

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Ponytail-review pass: same logic, one variable per arm instead of two.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@VijitSingh97

Copy link
Copy Markdown
Collaborator Author

Superseded by #804, which landed the same root cause (profile-disabled services are still defined, so --remove-orphans never drops them — independently confirmed here) with the removal hooked into compose_up_checked, a strictly broader placement than this PR's apply/upgrade call sites, plus equivalent stack-tier coverage of both node switches, the payout wallets, and removal-before-up ordering. Nothing left to salvage.

🤖 Generated with Claude Code

@VijitSingh97
VijitSingh97 deleted the fix/795-apply-profile-deactivation branch August 1, 2026 15:35
@VijitSingh97

Copy link
Copy Markdown
Collaborator Author

Post-close review notes, for the record:

  • The "a surviving container makes newer compose treat the profile-off service as enabled again and recreate it on an unrelated env change" claim in the body did not reproduce on docker 29.0.1 / compose v2 — with the profile off, an env change to the service leaves the old container untouched. Possibly podman/compose-version-specific on the bench; end state of both fixes is identical either way.
  • The CHANGELOG hunk here lands inside the already-released [1.15.0] section; per repo convention the apply leaves the deactivated-profile tari container running after a local→remote switch #795 entry belongs in the next chore(release) prep commit.
  • Worth salvaging someday: the existence-gated, operator-visible "Removing the container" log line is nicer UX than fix(cli): remove profile-deactivated containers before every compose up #804's silent idempotent removal — the follow-up to reach for if silent self-heal on up ever confuses an operator.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

apply leaves the deactivated-profile tari container running after a local→remote switch

1 participant