Skip to content

Commit e087b47

Browse files
committed
import: Raise error if the imported image is filtered out
During import, if an image does not match the host's platform, it won't have any children labels set, which will result in the Garbage Collector deleting its content later, resulting in an unusable image. In this case, we should fail early. This can still be bypassed by using ctr import --all-platforms. Signed-off-by: Claudiu Belu <[email protected]>
1 parent c23f52a commit e087b47

3 files changed

Lines changed: 52 additions & 5 deletions

File tree

images/handlers.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ var (
4040
// This applies only to a single descriptor in a handler
4141
// chain and does not apply to descendant descriptors.
4242
ErrStopHandler = fmt.Errorf("stop handler")
43+
44+
// ErrEmptyWalk is used when the WalkNotEmpty handlers return no
45+
// children (e.g.: they were filtered out).
46+
ErrEmptyWalk = fmt.Errorf("image might be filtered out")
4347
)
4448

4549
// Handler handles image manifests
@@ -99,6 +103,36 @@ func Walk(ctx context.Context, handler Handler, descs ...ocispec.Descriptor) err
99103
}
100104
}
101105
}
106+
return nil
107+
}
108+
109+
// WalkNotEmpty works the same way Walk does, with the exception that it ensures that
110+
// some children are still found by Walking the descriptors (for example, not all of
111+
// them have been filtered out by one of the handlers). If there are no children,
112+
// then an ErrEmptyWalk error is returned.
113+
func WalkNotEmpty(ctx context.Context, handler Handler, descs ...ocispec.Descriptor) error {
114+
isEmpty := true
115+
var notEmptyHandler HandlerFunc = func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
116+
children, err := handler.Handle(ctx, desc)
117+
if err != nil {
118+
return children, err
119+
}
120+
121+
if len(children) > 0 {
122+
isEmpty = false
123+
}
124+
125+
return children, nil
126+
}
127+
128+
err := Walk(ctx, notEmptyHandler, descs...)
129+
if err != nil {
130+
return err
131+
}
132+
133+
if isEmpty {
134+
return ErrEmptyWalk
135+
}
102136

103137
return nil
104138
}

import.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ func (c *Client) Import(ctx context.Context, reader io.Reader, opts ...ImportOpt
185185

186186
handler = images.FilterPlatforms(handler, platformMatcher)
187187
handler = images.SetChildrenLabels(cs, handler)
188-
if err := images.Walk(ctx, handler, index); err != nil {
188+
if err := images.WalkNotEmpty(ctx, handler, index); err != nil {
189189
return nil, err
190190
}
191191

integration/client/import_test.go

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"io/ioutil"
2626
"math/rand"
2727
"reflect"
28+
"runtime"
2829
"testing"
2930

3031
. "github.com/containerd/containerd"
@@ -98,7 +99,8 @@ func TestImport(t *testing.T) {
9899
empty := []byte("{}")
99100
version := []byte("1.0")
100101

101-
c1, d2 := createConfig()
102+
c1, d2 := createConfig(runtime.GOOS, runtime.GOARCH)
103+
badConfig, _ := createConfig("foo", "lish")
102104

103105
m1, d3, expManifest := createManifest(c1, [][]byte{b1})
104106

@@ -172,6 +174,17 @@ func TestImport(t *testing.T) {
172174
checkManifest(ctx, t, imgs[0].Target, nil)
173175
},
174176
},
177+
{
178+
Name: "DockerV2.1-BadOSArch",
179+
Writer: tartest.TarAll(
180+
tc.Dir("bd765cd43e95212f7aa2cab51d0a", 0755),
181+
tc.File("bd765cd43e95212f7aa2cab51d0a/json", empty, 0644),
182+
tc.File("bd765cd43e95212f7aa2cab51d0a/layer.tar", b1, 0644),
183+
tc.File("bd765cd43e95212f7aa2cab51d0a/VERSION", version, 0644),
184+
tc.File("e95212f7aa2cab51d0abd765cd43.json", badConfig, 0644),
185+
tc.File("manifest.json", []byte(`[{"Config":"e95212f7aa2cab51d0abd765cd43.json","RepoTags":["test-import:notlatest", "another/repo:tag"],"Layers":["bd765cd43e95212f7aa2cab51d0a/layer.tar"]}]`), 0644),
186+
),
187+
},
175188
{
176189
Name: "OCI-BadFormat",
177190
Writer: tartest.TarAll(
@@ -302,10 +315,10 @@ func createContent(size int64, seed int64) ([]byte, digest.Digest) {
302315
return b, digest.FromBytes(b)
303316
}
304317

305-
func createConfig() ([]byte, digest.Digest) {
318+
func createConfig(osName, archName string) ([]byte, digest.Digest) {
306319
image := ocispec.Image{
307-
OS: "any",
308-
Architecture: "any",
320+
OS: osName,
321+
Architecture: archName,
309322
Author: "test",
310323
}
311324
b, _ := json.Marshal(image)

0 commit comments

Comments
 (0)