fix(image): avoid dangling-ref name collision on rmi -f for running images - #5127
Open
pujitha24 wants to merge 1 commit into
Open
fix(image): avoid dangling-ref name collision on rmi -f for running images#5127pujitha24 wants to merge 1 commit into
rmi -f for running images#5127pujitha24 wants to merge 1 commit into
Conversation
… images
Motivation:
`nerdctl rmi -f` on an image that is still used by a running container
keeps a dangling ref alive (renaming the image before deleting its
original name) so containerd does not garbage-collect the layers.
That dangling ref was always named with the literal string ":". Since
containerd's image store requires unique names, force-removing a
second running image's image in the same run made the second `Create`
fail with "image \":\": already exists", aborting the whole command.
Approach:
Name the dangling ref after its content digest (":<digest>") instead
of the fixed ":" literal, so each kept-alive ref gets a distinct name.
The one remaining consumer that special-cased the exact ":" name
(pkg/imgutil filtering, used by `--filter reference=...` to skip
dangling images without erroring on their unparsable name) is updated
to match on the ":" prefix instead. Also tolerate AlreadyExists on the
Create call: if two different tags happen to share the same digest and
are both force-removed as running images in one invocation, the second
Create legitimately no-ops (the digest is already pinned).
Validation:
This is a name-collision defect in pkg/cmd/image/remove.go, reproducible
against containerd's real images.Store semantics without a live daemon.
Added pkg/cmd/image/remove_test.go, whose
TestDanglingImageNameIsUniquePerDigest exercises a fake images.Store
that enforces the same create-time uniqueness constraint containerd
does, and asserts the new per-digest naming avoids the collision.
I confirmed this test fails against the old behavior (temporarily
reverting the helper to return the literal ":") and passes against the
fix.
Ran:
- go build ./... (and GOOS=linux, GOOS=windows) - all pass
- go vet ./pkg/cmd/image/... ./pkg/imgutil/... - clean
- gofmt -l on the changed files - no output
- go test ./pkg/... - all pass, including the new test
- go test ./pkg/cmd/image/... -run TestDanglingImageNameIsUniquePerDigest -v - PASS
This sandbox is macOS without containerd/runc installed, so the repo's
documented integration suite (go test -p 1 ./cmd/nerdctl/... against a
real containerd store, per docs/testing/README.md) could not be run;
confirmed those tests fail uniformly here (binary not found) regardless
of this change. The added unit test is a targeted regression test for
the digest-collision defect, not a full CLI-level reproduction.
Report: containerd#4109
Signed-off-by: Pujitha Paladugu <10557236+pujitha24@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation:
nerdctl rmi -fon an image that is still used by a running containerkeeps a dangling ref alive (renaming the image before deleting its
original name) so containerd does not garbage-collect the layers.
That dangling ref was always named with the literal string ":". Since
containerd's image store requires unique names, force-removing a
second running image's image in the same run made the second
Createfail with "image ":": already exists", aborting the whole command.
Approach:
Name the dangling ref after its content digest (":") instead
of the fixed ":" literal, so each kept-alive ref gets a distinct name.
The one remaining consumer that special-cased the exact ":" name
(pkg/imgutil filtering, used by
--filter reference=...to skipdangling images without erroring on their unparsable name) is updated
to match on the ":" prefix instead. Also tolerate AlreadyExists on the
Create call: if two different tags happen to share the same digest and
are both force-removed as running images in one invocation, the second
Create legitimately no-ops (the digest is already pinned).
Validation:
This is a name-collision defect in pkg/cmd/image/remove.go, reproducible
against containerd's real images.Store semantics without a live daemon.
Added pkg/cmd/image/remove_test.go, whose
TestDanglingImageNameIsUniquePerDigest exercises a fake images.Store
that enforces the same create-time uniqueness constraint containerd
does, and asserts the new per-digest naming avoids the collision.
I confirmed this test fails against the old behavior (temporarily
reverting the helper to return the literal ":") and passes against the
fix.
Ran:
This sandbox is macOS without containerd/runc installed, so the repo's
documented integration suite (go test -p 1 ./cmd/nerdctl/... against a
real containerd store, per docs/testing/README.md) could not be run;
confirmed those tests fail uniformly here (binary not found) regardless
of this change. The added unit test is a targeted regression test for
the digest-collision defect, not a full CLI-level reproduction.
Report: #4109
Signed-off-by: Pujitha Paladugu 10557236+pujitha24@users.noreply.github.com
Fixes #4109