Skip to content

Commit af93e40

Browse files
committed
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 <[email protected]>
1 parent 876c889 commit af93e40

2 files changed

Lines changed: 89 additions & 0 deletions

File tree

cmd/ctr/commands/images/images.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ var Command = cli.Command{
4646
pullCommand,
4747
pushCommand,
4848
removeCommand,
49+
tagCommand,
4950
setLabelsCommand,
5051
},
5152
}

cmd/ctr/commands/images/tag.go

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
Copyright The containerd Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package images
18+
19+
import (
20+
"fmt"
21+
22+
"github.com/containerd/containerd/cmd/ctr/commands"
23+
"github.com/containerd/containerd/errdefs"
24+
"github.com/urfave/cli"
25+
)
26+
27+
var tagCommand = cli.Command{
28+
Name: "tag",
29+
Usage: "tag an image",
30+
ArgsUsage: "[flags] <source_ref> <target_ref> [<target_ref>, ...]",
31+
Description: `Tag an image for use in containerd.`,
32+
Flags: []cli.Flag{
33+
cli.BoolFlag{
34+
Name: "force",
35+
Usage: "force target_ref to be created, regardless if it already exists",
36+
},
37+
},
38+
Action: func(context *cli.Context) error {
39+
var (
40+
ref = context.Args().First()
41+
)
42+
if ref == "" {
43+
return fmt.Errorf("please provide an image reference to tag from")
44+
}
45+
if context.NArg() <= 1 {
46+
return fmt.Errorf("please provide an image reference to tag to")
47+
}
48+
49+
client, ctx, cancel, err := commands.NewClient(context)
50+
if err != nil {
51+
return err
52+
}
53+
defer cancel()
54+
55+
ctx, done, err := client.WithLease(ctx)
56+
if err != nil {
57+
return err
58+
}
59+
defer done(ctx)
60+
61+
imageService := client.ImageService()
62+
image, err := imageService.Get(ctx, ref)
63+
if err != nil {
64+
return err
65+
}
66+
// Support multiple references for one command run
67+
for _, targetRef := range context.Args()[1:] {
68+
image.Name = targetRef
69+
// Attempt to create the image first
70+
if _, err = imageService.Create(ctx, image); err != nil {
71+
// If user has specified force and the image already exists then
72+
// delete the original image and attempt to create the new one
73+
if errdefs.IsAlreadyExists(err) && context.Bool("force") {
74+
if err = imageService.Delete(ctx, targetRef); err != nil {
75+
return err
76+
}
77+
if _, err = imageService.Create(ctx, image); err != nil {
78+
return err
79+
}
80+
} else {
81+
return err
82+
}
83+
}
84+
fmt.Println(targetRef)
85+
}
86+
return nil
87+
},
88+
}

0 commit comments

Comments
 (0)