Skip to content

Commit b792f1f

Browse files
authored
Merge pull request containerd#3822 from haytok/nerdctl_issue_3806
fix: save multiple images for the same image id to a tar archive
2 parents 343a122 + 9a6426d commit b792f1f

File tree

2 files changed

+59
-3
lines changed

2 files changed

+59
-3
lines changed

cmd/nerdctl/image/image_save_test.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,3 +138,60 @@ func TestSave(t *testing.T) {
138138

139139
testCase.Run(t)
140140
}
141+
142+
// TestSaveMultipleImagesWithSameIDAndLoad tests https://github.com/containerd/nerdctl/issues/3806
143+
func TestSaveMultipleImagesWithSameIDAndLoad(t *testing.T) {
144+
testCase := nerdtest.Setup()
145+
146+
// This test relies on the fact that we can remove the common image, which definitely conflicts with others,
147+
// hence the private mode.
148+
// Further note though, that this will hide the fact this the save command could fail if some layers are missing.
149+
// See https://github.com/containerd/nerdctl/issues/3425 and others for details.
150+
testCase.Require = nerdtest.Private
151+
152+
if runtime.GOOS == "windows" {
153+
testCase.Require = nerdtest.IsFlaky("https://github.com/containerd/nerdctl/issues/3524")
154+
}
155+
156+
testCase.SubTests = []*test.Case{
157+
{
158+
Description: "Issue #3568 - Save multiple container images with the same image ID but different image names",
159+
NoParallel: true,
160+
Cleanup: func(data test.Data, helpers test.Helpers) {
161+
if data.Get("id") != "" {
162+
helpers.Anyhow("rmi", "-f", data.Get("id"))
163+
}
164+
},
165+
Setup: func(data test.Data, helpers test.Helpers) {
166+
helpers.Ensure("pull", "--quiet", testutil.CommonImage)
167+
img := nerdtest.InspectImage(helpers, testutil.CommonImage)
168+
var id string
169+
if nerdtest.IsDocker() {
170+
id = img.ID
171+
} else {
172+
id = strings.Split(img.RepoDigests[0], ":")[1]
173+
}
174+
helpers.Ensure("tag", testutil.CommonImage, data.Identifier())
175+
tarPath := filepath.Join(data.TempDir(), "out.tar")
176+
helpers.Ensure("save", "-o", tarPath, testutil.CommonImage, data.Identifier())
177+
helpers.Ensure("rmi", "-f", id)
178+
helpers.Ensure("load", "-i", tarPath)
179+
data.Set("id", id)
180+
},
181+
Command: func(data test.Data, helpers test.Helpers) test.TestableCommand {
182+
return helpers.Command("images", "--no-trunc")
183+
},
184+
Expected: func(data test.Data, helpers test.Helpers) *test.Expected {
185+
return &test.Expected{
186+
ExitCode: 0,
187+
Errors: []error{},
188+
Output: func(stdout string, info string, t *testing.T) {
189+
assert.Equal(t, strings.Count(stdout, data.Get("id")), 2)
190+
},
191+
}
192+
},
193+
},
194+
}
195+
196+
testCase.Run(t)
197+
}

pkg/cmd/image/save.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,8 @@ func Save(ctx context.Context, client *containerd.Client, images []string, optio
5656
}
5757

5858
imgName := found.Image.Name
59-
imgDigest := found.Image.Target.Digest.String()
60-
if _, ok := savedImages[imgDigest]; !ok {
61-
savedImages[imgDigest] = struct{}{}
59+
if _, ok := savedImages[imgName]; !ok {
60+
savedImages[imgName] = struct{}{}
6261
exportOpts = append(exportOpts, archive.WithImage(imageStore, imgName))
6362
}
6463
return nil

0 commit comments

Comments
 (0)