Merge pull request #9476 from roman-kiselenko/label-images-on-import

add label flags to ctr import
This commit is contained in:
Fu Wei 2024-01-08 09:04:44 +00:00 committed by GitHub
commit 781d027ba8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 51 additions and 2 deletions

View File

@ -38,6 +38,7 @@ type importOpts struct {
compress bool compress bool
discardLayers bool discardLayers bool
skipMissing bool skipMissing bool
imageLabels map[string]string
} }
// ImportOpt allows the caller to specify import specific options // ImportOpt allows the caller to specify import specific options
@ -52,6 +53,14 @@ func WithImageRefTranslator(f func(string) string) ImportOpt {
} }
} }
// WithImageLabels are the image labels to apply to a new image
func WithImageLabels(labels map[string]string) ImportOpt {
return func(c *importOpts) error {
c.imageLabels = labels
return nil
}
}
// WithDigestRef is used to create digest images for each // WithDigestRef is used to create digest images for each
// manifest in the index. // manifest in the index.
func WithDigestRef(f func(digest.Digest) string) ImportOpt { func WithDigestRef(f func(digest.Digest) string) ImportOpt {
@ -223,7 +232,12 @@ func (c *Client) Import(ctx context.Context, reader io.Reader, opts ...ImportOpt
} }
for i := range imgs { for i := range imgs {
img, err := is.Update(ctx, imgs[i], "target") fieldsPath := []string{"target"}
if iopts.imageLabels != nil {
fieldsPath = append(fieldsPath, "labels")
imgs[i].Labels = iopts.imageLabels
}
img, err := is.Update(ctx, imgs[i], fieldsPath...)
if err != nil { if err != nil {
if !errdefs.IsNotFound(err) { if !errdefs.IsNotFound(err) {
return nil, err return nil, err

View File

@ -98,7 +98,7 @@ If foobar.tar contains an OCI ref named "latest" and anonymous ref "sha256:deadb
Name: "discard-unpacked-layers", Name: "discard-unpacked-layers",
Usage: "Allow the garbage collector to clean layers up from the content store after unpacking, cannot be used with --no-unpack, false by default", Usage: "Allow the garbage collector to clean layers up from the content store after unpacking, cannot be used with --no-unpack, false by default",
}, },
}, commands.SnapshotterFlags...), }, append(commands.SnapshotterFlags, commands.LabelFlag)...),
Action: func(context *cli.Context) error { Action: func(context *cli.Context) error {
var ( var (
@ -123,6 +123,11 @@ If foobar.tar contains an OCI ref named "latest" and anonymous ref "sha256:deadb
overwrite = true overwrite = true
} }
labels := context.StringSlice("label")
if len(labels) > 0 {
opts = append(opts, image.WithImageLabels(commands.LabelArgs(labels)))
}
if context.Bool("digests") { if context.Bool("digests") {
opts = append(opts, image.WithDigestRef(prefix, overwrite, !context.Bool("skip-digest-for-named"))) opts = append(opts, image.WithDigestRef(prefix, overwrite, !context.Bool("skip-digest-for-named")))
} else { } else {
@ -237,6 +242,11 @@ If foobar.tar contains an OCI ref named "latest" and anonymous ref "sha256:deadb
opts = append(opts, containerd.WithDiscardUnpackedLayers()) opts = append(opts, containerd.WithDiscardUnpackedLayers())
} }
labels := context.StringSlice("label")
if len(labels) > 0 {
opts = append(opts, containerd.WithImageLabels(commands.LabelArgs(labels)))
}
ctx, done, err := client.WithLease(ctx) ctx, done, err := client.WithLease(ctx)
if err != nil { if err != nil {
return err return err

View File

@ -173,6 +173,8 @@ func TestImport(t *testing.T) {
m1, d3, expManifest := createManifest(c1, [][]byte{b1}) m1, d3, expManifest := createManifest(c1, [][]byte{b1})
importLabels := map[string]string{"foo": "bar"}
c2, _ := createConfig(runtime.GOOS, runtime.GOARCH, "test2") c2, _ := createConfig(runtime.GOOS, runtime.GOARCH, "test2")
m2, d5, _ := createManifest(c2, [][]byte{{1, 2, 3, 4, 5}}) m2, d5, _ := createManifest(c2, [][]byte{{1, 2, 3, 4, 5}})
@ -315,6 +317,29 @@ func TestImport(t *testing.T) {
checkManifest(ctx, t, client.ContentStore(), imgs[0].Target, expManifest) checkManifest(ctx, t, client.ContentStore(), imgs[0].Target, expManifest)
}, },
}, },
{
Name: "OCI-Labels",
Writer: tartest.TarAll(
tc.Dir(ocispec.ImageBlobsDir, 0o755),
tc.Dir(ocispec.ImageBlobsDir+"/sha256", 0o755),
tc.File(ocispec.ImageBlobsDir+"/sha256/"+d1.Encoded(), b1, 0o644),
tc.File(ocispec.ImageBlobsDir+"/sha256/"+d2.Encoded(), c1, 0o644),
tc.File(ocispec.ImageBlobsDir+"/sha256/"+d3.Encoded(), m1, 0o644),
tc.File(ocispec.ImageIndexFile, createIndex(m1, "latest", "docker.io/lib/img:ok"), 0o644),
tc.File(ocispec.ImageLayoutFile, []byte(`{"imageLayoutVersion":"`+ocispec.ImageLayoutVersion+`"}`), 0o644),
),
Check: func(ctx context.Context, t *testing.T, _ *Client, imgs []images.Image) {
for i := range imgs {
if !reflect.DeepEqual(imgs[i].Labels, importLabels) {
t.Fatalf("DeepEqual on labels failed img.Labels: %+v expected: %+v", imgs[i].Labels, importLabels)
}
}
},
Opts: []ImportOpt{
WithImageLabels(importLabels),
WithImageRefTranslator(archive.AddRefPrefix("localhost:5000/myimage")),
},
},
{ {
Name: "OCIPrefixName", Name: "OCIPrefixName",
Writer: tartest.TarAll( Writer: tartest.TarAll(