From af93e4009bc30451b91cae737ad4ec05a1aa88e3 Mon Sep 17 00:00:00 2001 From: Eli Uriegas Date: Tue, 2 Jul 2019 23:24:25 +0000 Subject: [PATCH] ctr: Add images tag subcommand Adds a subcommand for tagging images managed by containerd. Usage: ctr images tag docker.io/library/alpine:latest docker.io/library/alpine:new Comes with a --force flag to allow you to gracefully overwrite image references that already exist. Signed-off-by: Eli Uriegas --- cmd/ctr/commands/images/images.go | 1 + cmd/ctr/commands/images/tag.go | 88 +++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 cmd/ctr/commands/images/tag.go diff --git a/cmd/ctr/commands/images/images.go b/cmd/ctr/commands/images/images.go index ca6dd6857..44e5fca91 100644 --- a/cmd/ctr/commands/images/images.go +++ b/cmd/ctr/commands/images/images.go @@ -46,6 +46,7 @@ var Command = cli.Command{ pullCommand, pushCommand, removeCommand, + tagCommand, setLabelsCommand, }, } diff --git a/cmd/ctr/commands/images/tag.go b/cmd/ctr/commands/images/tag.go new file mode 100644 index 000000000..7c5d2a96a --- /dev/null +++ b/cmd/ctr/commands/images/tag.go @@ -0,0 +1,88 @@ +/* + 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 images + +import ( + "fmt" + + "github.com/containerd/containerd/cmd/ctr/commands" + "github.com/containerd/containerd/errdefs" + "github.com/urfave/cli" +) + +var tagCommand = cli.Command{ + Name: "tag", + Usage: "tag an image", + ArgsUsage: "[flags] [, ...]", + Description: `Tag an image for use in containerd.`, + Flags: []cli.Flag{ + cli.BoolFlag{ + Name: "force", + Usage: "force target_ref to be created, regardless if it already exists", + }, + }, + Action: func(context *cli.Context) error { + var ( + ref = context.Args().First() + ) + if ref == "" { + return fmt.Errorf("please provide an image reference to tag from") + } + if context.NArg() <= 1 { + return fmt.Errorf("please provide an image reference to tag to") + } + + client, ctx, cancel, err := commands.NewClient(context) + if err != nil { + return err + } + defer cancel() + + ctx, done, err := client.WithLease(ctx) + if err != nil { + return err + } + defer done(ctx) + + imageService := client.ImageService() + image, err := imageService.Get(ctx, ref) + if err != nil { + return err + } + // Support multiple references for one command run + for _, targetRef := range context.Args()[1:] { + image.Name = targetRef + // Attempt to create the image first + if _, err = imageService.Create(ctx, image); err != nil { + // If user has specified force and the image already exists then + // delete the original image and attempt to create the new one + if errdefs.IsAlreadyExists(err) && context.Bool("force") { + if err = imageService.Delete(ctx, targetRef); err != nil { + return err + } + if _, err = imageService.Create(ctx, image); err != nil { + return err + } + } else { + return err + } + } + fmt.Println(targetRef) + } + return nil + }, +}