Skip to content

Commit 56b5d24

Browse files
Adam FurbeeAdam Furbee
authored andcommitted
Adding crane annotate command
1 parent 59a4b85 commit 56b5d24

File tree

3 files changed

+94
-0
lines changed

3 files changed

+94
-0
lines changed

cmd/crane/cmd/annotate.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// Copyright 2021 Google LLC All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package cmd
16+
17+
import (
18+
"fmt"
19+
20+
"github.com/google/go-containerregistry/pkg/crane"
21+
v1 "github.com/google/go-containerregistry/pkg/v1"
22+
"github.com/google/go-containerregistry/pkg/v1/mutate"
23+
"github.com/spf13/cobra"
24+
)
25+
26+
// NewCmdAnnotate creates a new cobra.Command for the annotate subcommand.
27+
func NewCmdAnnotate(options *[]crane.Option) *cobra.Command {
28+
var annotations map[string]string
29+
var newRef string
30+
31+
annotateCmd := &cobra.Command{
32+
Use: "annotate",
33+
Short: "Modify image or index annotations. The manifest is updated there on the registry.",
34+
Args: cobra.ExactArgs(1),
35+
RunE: func(c *cobra.Command, args []string) error {
36+
ref := args[0]
37+
38+
desc, err := crane.Head(ref, *options...)
39+
if err != nil {
40+
return err
41+
}
42+
43+
if newRef == "" {
44+
newRef = ref
45+
}
46+
47+
if desc.MediaType.IsIndex() {
48+
d, err := crane.Get(ref, *options...)
49+
if err != nil {
50+
return err
51+
}
52+
idx, err := d.ImageIndex()
53+
if err != nil {
54+
return err
55+
}
56+
annotated := mutate.Annotations(idx, annotations).(v1.ImageIndex)
57+
err = crane.PushIndex(annotated, newRef, *options...)
58+
if err != nil {
59+
return err
60+
}
61+
fmt.Println("Index pushed with annotations.")
62+
} else if desc.MediaType.IsImage() {
63+
img, err := crane.Pull(ref, *options...)
64+
if err != nil {
65+
return err
66+
}
67+
annotated := mutate.Annotations(img, annotations).(v1.Image)
68+
err = crane.Push(annotated, newRef, *options...)
69+
if err != nil {
70+
return err
71+
}
72+
fmt.Println("Image pushed with annotations.")
73+
} else {
74+
return fmt.Errorf("unsupported manifest type only indexes and images are currently supported: %s", desc.ArtifactType)
75+
}
76+
77+
return nil
78+
},
79+
}
80+
annotateCmd.Flags().StringToStringVarP(&annotations, "annotation", "a", nil, "New annotations to add")
81+
annotateCmd.Flags().StringVarP(&newRef, "tag", "t", "", "New tag reference to apply to annotated image/index. If not provided, push by digest to the original repository.")
82+
return annotateCmd
83+
}

cmd/crane/cmd/root.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ func New(use, short string, options []crane.Option) *cobra.Command {
108108
}
109109

110110
root.AddCommand(
111+
NewCmdAnnotate(&options),
111112
NewCmdAppend(&options),
112113
NewCmdAuth(options, "crane", "auth"),
113114
NewCmdBlob(&options),

pkg/crane/push.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,16 @@ func Push(img v1.Image, dst string, opt ...Option) error {
5353
return remote.Write(tag, img, o.Remote...)
5454
}
5555

56+
// PushIndex pushes the v1.ImageIndex idx to a registry as dst.
57+
func PushIndex(idx v1.ImageIndex, dst string, opt ...Option) error {
58+
o := makeOptions(opt...)
59+
tag, err := name.ParseReference(dst, o.Name...)
60+
if err != nil {
61+
return fmt.Errorf("parsing reference %q: %w", dst, err)
62+
}
63+
return remote.Put(tag, idx, o.Remote...)
64+
}
65+
5666
// Upload pushes the v1.Layer to a given repo.
5767
func Upload(layer v1.Layer, repo string, opt ...Option) error {
5868
o := makeOptions(opt...)

0 commit comments

Comments
 (0)