From f706576500c24c9f2f17bea2bdeea3afc39584b1 Mon Sep 17 00:00:00 2001 From: Jian Zeng Date: Sun, 5 Mar 2023 18:56:30 +0800 Subject: [PATCH] feat: tag image using Transfer api Signed-off-by: Jian Zeng --- cmd/ctr/commands/images/tag.go | 19 +++++++++++++++- pkg/transfer/archive/importer.go | 5 ++-- pkg/transfer/image/imagestore.go | 6 ++--- pkg/transfer/local/tag.go | 39 ++++++++++++++++++++++++++++++++ pkg/transfer/local/transfer.go | 7 ++++-- 5 files changed, 68 insertions(+), 8 deletions(-) create mode 100644 pkg/transfer/local/tag.go diff --git a/cmd/ctr/commands/images/tag.go b/cmd/ctr/commands/images/tag.go index 893065ee8..7a4eb1119 100644 --- a/cmd/ctr/commands/images/tag.go +++ b/cmd/ctr/commands/images/tag.go @@ -19,9 +19,11 @@ package images import ( "fmt" + "github.com/urfave/cli" + "github.com/containerd/containerd/cmd/ctr/commands" "github.com/containerd/containerd/errdefs" - "github.com/urfave/cli" + "github.com/containerd/containerd/pkg/transfer/image" ) var tagCommand = cli.Command{ @@ -34,6 +36,10 @@ var tagCommand = cli.Command{ Name: "force", Usage: "Force target_ref to be created, regardless if it already exists", }, + cli.BoolTFlag{ + Name: "local", + Usage: "run tag locally rather than through transfer API", + }, }, Action: func(context *cli.Context) error { var ( @@ -52,6 +58,17 @@ var tagCommand = cli.Command{ } defer cancel() + if !context.BoolT("local") { + for _, targetRef := range context.Args()[1:] { + err = client.Transfer(ctx, image.NewStore(ref), image.NewStore(targetRef)) + if err != nil { + return err + } + fmt.Println(targetRef) + } + return nil + } + ctx, done, err := client.WithLease(ctx) if err != nil { return err diff --git a/pkg/transfer/archive/importer.go b/pkg/transfer/archive/importer.go index 6519d5e44..a9c4cea93 100644 --- a/pkg/transfer/archive/importer.go +++ b/pkg/transfer/archive/importer.go @@ -20,14 +20,15 @@ import ( "context" "io" + "github.com/containerd/typeurl/v2" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" + transferapi "github.com/containerd/containerd/api/types/transfer" "github.com/containerd/containerd/content" "github.com/containerd/containerd/images/archive" "github.com/containerd/containerd/log" "github.com/containerd/containerd/pkg/streaming" tstreaming "github.com/containerd/containerd/pkg/transfer/streaming" - "github.com/containerd/typeurl/v2" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) type ImportOpt func(*ImageImportStream) diff --git a/pkg/transfer/image/imagestore.go b/pkg/transfer/image/imagestore.go index b26f25605..46bc03b4d 100644 --- a/pkg/transfer/image/imagestore.go +++ b/pkg/transfer/image/imagestore.go @@ -20,6 +20,9 @@ import ( "context" "fmt" + "github.com/containerd/typeurl/v2" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/containerd/containerd/api/types" transfertypes "github.com/containerd/containerd/api/types/transfer" "github.com/containerd/containerd/content" @@ -31,8 +34,6 @@ import ( "github.com/containerd/containerd/pkg/transfer/plugins" "github.com/containerd/containerd/platforms" "github.com/containerd/containerd/remotes" - "github.com/containerd/typeurl/v2" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) func init() { @@ -357,7 +358,6 @@ func (is *Store) UnpackPlatforms() []transfer.UnpackConfiguration { } func (is *Store) MarshalAny(context.Context, streaming.StreamCreator) (typeurl.Any, error) { - //unpack.Platform s := &transfertypes.ImageStore{ Name: is.imageName, Labels: is.imageLabels, diff --git a/pkg/transfer/local/tag.go b/pkg/transfer/local/tag.go new file mode 100644 index 000000000..8928a4a5f --- /dev/null +++ b/pkg/transfer/local/tag.go @@ -0,0 +1,39 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package local + +import ( + "context" + + "github.com/containerd/containerd/pkg/transfer" +) + +func (ts *localTransferService) tag(ctx context.Context, ig transfer.ImageGetter, is transfer.ImageStorer, tops *transfer.Config) error { + ctx, done, err := ts.withLease(ctx) + if err != nil { + return err + } + defer done(ctx) + + img, err := ig.Get(ctx, ts.images) + if err != nil { + return err + } + + _, err = is.Store(ctx, img.Target, ts.images) + return err +} diff --git a/pkg/transfer/local/transfer.go b/pkg/transfer/local/transfer.go index 68a1ea7c4..5cf7008c3 100644 --- a/pkg/transfer/local/transfer.go +++ b/pkg/transfer/local/transfer.go @@ -22,6 +22,9 @@ import ( "io" "time" + "github.com/containerd/typeurl/v2" + "golang.org/x/sync/semaphore" + "github.com/containerd/containerd/content" "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/images" @@ -29,8 +32,6 @@ import ( "github.com/containerd/containerd/pkg/kmutex" "github.com/containerd/containerd/pkg/transfer" "github.com/containerd/containerd/pkg/unpack" - "github.com/containerd/typeurl/v2" - "golang.org/x/sync/semaphore" ) type localTransferService struct { @@ -74,6 +75,8 @@ func (ts *localTransferService) Transfer(ctx context.Context, src interface{}, d return ts.push(ctx, s, d, topts) case transfer.ImageExporter: return ts.exportStream(ctx, s, d, topts) + case transfer.ImageStorer: + return ts.tag(ctx, s, d, topts) } case transfer.ImageImporter: switch d := dest.(type) {