Skip to content

Commit 926f17e

Browse files
committed
Add test for dangling SOCI index v2 reference
If an image manifest contains a reference to a SOCI index, but the SOCI index doesn't exist in the registry, the snapshotter should try to use that SOCI index, but then fallback to non-lazy loading when it can't find the SOCI index. This adds a test to verify that. Signed-off-by: Kern Walster <[email protected]>
1 parent 9fae581 commit 926f17e

File tree

1 file changed

+91
-0
lines changed

1 file changed

+91
-0
lines changed

integration/pull_modes_test.go

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"github.com/awslabs/soci-snapshotter/config"
2525
"github.com/awslabs/soci-snapshotter/util/dockershell"
2626
"github.com/awslabs/soci-snapshotter/util/testutil"
27+
"github.com/containerd/containerd/reference"
2728
"github.com/containerd/platforms"
2829
)
2930

@@ -252,3 +253,93 @@ func testV1IsNotUsedWhenDisabled(t *testing.T, imgName string) {
252253
t.Fatalf("expected no digest, got %s", indexDigestUsed)
253254
}
254255
}
256+
257+
func TestDanglingV2Annotation(t *testing.T) {
258+
for _, imgName := range pullModesImages {
259+
t.Run(imgName, func(t *testing.T) {
260+
testDanglingV2Annotation(t, imgName)
261+
})
262+
}
263+
}
264+
265+
func testDanglingV2Annotation(t *testing.T, imgName string) {
266+
regConfig := newRegistryConfig()
267+
sh, done := newShellWithRegistry(t, regConfig)
268+
defer done()
269+
270+
rebootContainerd(t, sh, "", "")
271+
272+
srcInfo := dockerhub(imgName)
273+
dstInfo := regConfig.mirror(imgName)
274+
275+
sh.X("nerdctl", "pull", "--all-platforms", srcInfo.ref)
276+
sh.X("soci", "convert", "--min-layer-size", "0", srcInfo.ref, dstInfo.ref)
277+
278+
manifest, err := getManifestDigest(sh, dstInfo.ref, platforms.DefaultSpec())
279+
if err != nil {
280+
t.Fatalf("could not get manifest digest: %v", err)
281+
}
282+
283+
v2IndexDigest, err := sh.OLog("soci",
284+
"index", "list",
285+
"-q", "--ref", srcInfo.ref,
286+
"--platform", platforms.Format(platforms.DefaultSpec()),
287+
)
288+
if err != nil {
289+
t.Fatal(err)
290+
}
291+
292+
// Nither nerdctl nor ctr expose a way to "elevate" a platform-specific
293+
// manifest to a top level image directly, so we do a little registry dance:
294+
// push image:tag
295+
// pull image@sha256:... (the specific manifest we want to elevate)
296+
// tag image@sha256:... image/dangling:tag
297+
// push image/dangling:tag
298+
//
299+
// After this, image/dangling:tag refers to a single manifest that is platform specific.
300+
// We use this to separate an image manifest that contains a reference to a SOCI index
301+
// from the SOCI index itself to verify that it correctly pulls the image without lazy loading.
302+
platformManifestRef, err := reference.Parse(dstInfo.ref)
303+
if err != nil {
304+
t.Fatalf("could not get parse destination ref: %v", err)
305+
}
306+
danglingRef := platformManifestRef
307+
danglingRef.Locator += "/dangling" // image/dangling:tag
308+
309+
platformManifestRef.Object = "@" + manifest // image@sha256...
310+
311+
sh.X("nerdctl", "login", "--username", regConfig.user, "--password", regConfig.pass, platformManifestRef.String())
312+
sh.X("nerdctl", "push", "--platform", platforms.DefaultString(), dstInfo.ref)
313+
sh.X("nerdctl", "pull", platformManifestRef.String())
314+
sh.X("nerdctl", "image", "tag", platformManifestRef.String(), danglingRef.String())
315+
// Push a v1 index as well to verify that we do not fall back if we don't find the SOCI v2 index
316+
sh.X("nerdctl", "push", "--snapshotter", "soci", "--soci-min-layer-size", "0", danglingRef.String())
317+
318+
m := rebootContainerd(t, sh, "", getSnapshotterConfigToml(t, withPullModes(config.DefaultPullModes())))
319+
320+
rsm, doneRsm := testutil.NewRemoteSnapshotMonitor(m)
321+
defer doneRsm()
322+
var foundNoIndexMessage bool
323+
var indexDigestUsed string
324+
m.Add("Look for digest", func(s string) {
325+
if strings.Contains(s, "no valid SOCI index found") {
326+
foundNoIndexMessage = true
327+
}
328+
structuredLog := make(map[string]string)
329+
err := json.Unmarshal([]byte(s), &structuredLog)
330+
if err != nil {
331+
return
332+
}
333+
if structuredLog["msg"] == "fetching SOCI artifacts using index descriptor" {
334+
indexDigestUsed = structuredLog["digest"]
335+
}
336+
})
337+
sh.X("nerdctl", "pull", "--snapshotter", "soci", danglingRef.String())
338+
rsm.CheckAllLocalSnapshots(t)
339+
if !foundNoIndexMessage {
340+
t.Fatalf("did not find the message that no index was found")
341+
}
342+
if strings.Trim(string(v2IndexDigest), "\n") != indexDigestUsed {
343+
t.Fatalf("expected v2 index digest %s, got %s", v2IndexDigest, indexDigestUsed)
344+
}
345+
}

0 commit comments

Comments
 (0)