From e33ffd11a8eae3cd2382bf86e9c75f1ced5fadab Mon Sep 17 00:00:00 2001 From: roman-kiselenko Date: Tue, 5 Dec 2023 12:46:57 +0300 Subject: [PATCH] add label flags to ctr import checking if labels exists in the image checking import options and assign it, add integration tests Signed-off-by: roman-kiselenko --- client/import.go | 16 +++++++++++++++- cmd/ctr/commands/images/import.go | 12 +++++++++++- integration/client/import_test.go | 25 +++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/client/import.go b/client/import.go index 42aca54e7faaa..90e2a8936507d 100644 --- a/client/import.go +++ b/client/import.go @@ -37,6 +37,7 @@ type importOpts struct { platformMatcher platforms.MatchComparer compress bool discardLayers bool + imageLabels map[string]string } // ImportOpt allows the caller to specify import specific options @@ -51,6 +52,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 // manifest in the index. func WithDigestRef(f func(digest.Digest) string) ImportOpt { @@ -208,7 +217,12 @@ func (c *Client) Import(ctx context.Context, reader io.Reader, opts ...ImportOpt } 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 !errdefs.IsNotFound(err) { return nil, err diff --git a/cmd/ctr/commands/images/import.go b/cmd/ctr/commands/images/import.go index 724964b549def..bb663904a161e 100644 --- a/cmd/ctr/commands/images/import.go +++ b/cmd/ctr/commands/images/import.go @@ -98,7 +98,7 @@ If foobar.tar contains an OCI ref named "latest" and anonymous ref "sha256:deadb 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", }, - }, commands.SnapshotterFlags...), + }, append(commands.SnapshotterFlags, commands.LabelFlag)...), Action: func(context *cli.Context) error { var ( @@ -123,6 +123,11 @@ If foobar.tar contains an OCI ref named "latest" and anonymous ref "sha256:deadb overwrite = true } + labels := context.StringSlice("label") + if len(labels) > 0 { + opts = append(opts, image.WithImageLabels(commands.LabelArgs(labels))) + } + if context.Bool("digests") { opts = append(opts, image.WithDigestRef(prefix, overwrite, !context.Bool("skip-digest-for-named"))) } else { @@ -237,6 +242,11 @@ If foobar.tar contains an OCI ref named "latest" and anonymous ref "sha256:deadb 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) if err != nil { return err diff --git a/integration/client/import_test.go b/integration/client/import_test.go index dbabeb44ac90f..18e3cfea5ab63 100644 --- a/integration/client/import_test.go +++ b/integration/client/import_test.go @@ -176,6 +176,8 @@ func TestImport(t *testing.T) { m1, d3, expManifest := createManifest(c1, [][]byte{b1}) + importLabels := map[string]string{"foo": "bar"} + provider := client.ContentStore() checkManifest := func(ctx context.Context, t *testing.T, d ocispec.Descriptor, expManifest *ocispec.Manifest) { @@ -284,6 +286,29 @@ func TestImport(t *testing.T) { checkManifest(ctx, t, 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(t *testing.T, 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", Writer: tartest.TarAll(