Skip to content

states/docker_container: pass temp_container_name, not the dict, to _replace#68968

Open
SAY-5 wants to merge 1 commit intosaltstack:3007.xfrom
SAY-5:fix/docker-container-replace-temp-name-68959
Open

states/docker_container: pass temp_container_name, not the dict, to _replace#68968
SAY-5 wants to merge 1 commit intosaltstack:3007.xfrom
SAY-5:fix/docker-container-replace-temp-name-68959

Conversation

@SAY-5
Copy link
Copy Markdown

@SAY-5 SAY-5 commented Apr 20, 2026

What does this PR do?

Fixes a wrong-argument bug in salt/states/docker_container.py's running() state.

running() creates a temp container from docker.create and captures two related values:

  • temp_container — the full dict returned by docker.create
  • temp_container_nametemp_container["Name"], a string

The detected-config-diff path correctly passes the string to the local _replace(orig, new) helper:

if not _replace(name, temp_container_name):

The skip_comparison / force=True path (also reached from mod_watch) passed the dict instead:

if not _replace(name, temp_container):  # <-- wrong argument

_replace immediately calls docker.rm(name, stop=True) on the original container and then docker.rename(new, orig). docker.rename's first argument is forwarded to inspect_container, which expects a string name/ID. Handing it a dict raises a CommandExecutionError — and by then the original container has already been removed. The state returns result: False, but the minion is left with the original container destroyed and the temp container stranded under its generated temp name.

This PR passes temp_container_name on the second call site too, matching the first path.

What issues does this PR fix or reference?

Fixes #68959

Previous Behavior

docker_container.running with force=True (or triggered via mod_watch) on an existing container whose spec matches the desired spec would:

  1. Remove the original container via docker.rm.
  2. Fail to rename the temp container (docker.rename raises on the dict argument).
  3. Return result: False with the original container destroyed and the temp container present but renamed to something like Salt_Temp_XXXX.

New Behavior

_replace(name, temp_container_name) is called with the string container name on both paths. The force-replace path now correctly swaps the temp container into place, matching the non-force path's behaviour.

Merge requirements satisfied?

  • Changelog: changelog/68959.fixed.md
  • Tests — this is a pure wrong-argument fix that mirrors the existing _replace(name, temp_container_name) call site at line ~1890. Happy to add a targeted regression test against docker.rename if maintainers prefer.

Commits signed with GPG?

Commits are DCO-signed off (Signed-off-by: SAY-5 <SAY-5@users.noreply.github.com>) per the repository's contribution flow.

…replace

running() builds a temp_container dict from docker.create and derives
temp_container_name from it. The detected-config-diff path already
calls _replace(name, temp_container_name). The skip_comparison /
force=True path (reached via mod_watch and when the caller forces a
re-create) passed the dict itself instead.

_replace immediately calls docker.rm(name) on the original container
and then docker.rename(new, orig). docker.rename forwards its first
argument to inspect_container, which expects a string name/ID -
handing it a dict raises, after the original container has already
been removed. The state returns result: False but the minion is left
with the original container destroyed and the temp container stranded
under its generated name (saltstack#68959).

Pass temp_container_name on this call site too so both replace paths
are consistent.

Signed-off-by: SAY-5 <SAY-5@users.noreply.github.com>

Fixes saltstack#68959
@SAY-5 SAY-5 requested a review from a team as a code owner April 20, 2026 18:37
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.

1 participant