Skip to content

Commit c4c4310

Browse files
committed
support mutating scratch images
1 parent 8dadbe7 commit c4c4310

File tree

1 file changed

+37
-14
lines changed

1 file changed

+37
-14
lines changed

cmd/crane/cmd/mutate.go

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,12 @@ import (
2020
"strings"
2121

2222
"github.com/google/go-containerregistry/pkg/crane"
23+
"github.com/google/go-containerregistry/pkg/logs"
2324
"github.com/google/go-containerregistry/pkg/name"
2425
v1 "github.com/google/go-containerregistry/pkg/v1"
26+
"github.com/google/go-containerregistry/pkg/v1/empty"
2527
"github.com/google/go-containerregistry/pkg/v1/mutate"
28+
"github.com/google/go-containerregistry/pkg/v1/types"
2629
"github.com/spf13/cobra"
2730
)
2831

@@ -39,33 +42,51 @@ func NewCmdMutate(options *[]crane.Option) *cobra.Command {
3942
var user string
4043
var workdir string
4144
var ports []string
45+
var ociEmptyBase bool
4246

4347
mutateCmd := &cobra.Command{
4448
Use: "mutate",
4549
Short: "Modify image labels and annotations. The container must be pushed to a registry, and the manifest is updated there.",
4650
Args: cobra.ExactArgs(1),
4751
RunE: func(c *cobra.Command, args []string) error {
48-
// Pull image and get config.
4952
ref := args[0]
53+
var img v1.Image
54+
var err error
5055

51-
if len(annotations) != 0 {
52-
desc, err := crane.Head(ref, *options...)
53-
if err != nil {
54-
return err
56+
if ref == "scratch" {
57+
// you can not write over the original image if the original image is scratch
58+
if newRef == "" {
59+
return errors.New("you must specify tag when a scratch base is used")
5560
}
56-
if desc.MediaType.IsIndex() {
57-
return errors.New("mutating annotations on an index is not yet supported")
61+
// Use an empty image.
62+
logs.Warn.Printf("scratch base specified, using empty image")
63+
img = empty.Image
64+
if ociEmptyBase {
65+
img = mutate.MediaType(img, types.OCIManifestSchema1)
66+
img = mutate.ConfigMediaType(img, types.OCIConfigJSON)
67+
}
68+
} else {
69+
// Pull image and get config.
70+
if len(annotations) != 0 {
71+
desc, err := crane.Head(ref, *options...)
72+
if err != nil {
73+
return err
74+
}
75+
if desc.MediaType.IsIndex() {
76+
return errors.New("mutating annotations on an index is not yet supported")
77+
}
5878
}
59-
}
6079

61-
if newRepo != "" && newRef != "" {
62-
return errors.New("repository can't be set when a tag is specified")
63-
}
80+
if newRepo != "" && newRef != "" {
81+
return errors.New("repository can't be set when a tag is specified")
82+
}
6483

65-
img, err := crane.Pull(ref, *options...)
66-
if err != nil {
67-
return fmt.Errorf("pulling %s: %w", ref, err)
84+
img, err = crane.Pull(ref, *options...)
85+
if err != nil {
86+
return fmt.Errorf("pulling %s: %w", ref, err)
87+
}
6888
}
89+
6990
if len(newLayers) != 0 {
7091
img, err = crane.Append(img, newLayers...)
7192
if err != nil {
@@ -183,6 +204,8 @@ func NewCmdMutate(options *[]crane.Option) *cobra.Command {
183204
mutateCmd.Flags().StringVarP(&user, "user", "u", "", "New user to set")
184205
mutateCmd.Flags().StringVarP(&workdir, "workdir", "w", "", "New working dir to set")
185206
mutateCmd.Flags().StringSliceVar(&ports, "exposed-ports", nil, "New ports to expose")
207+
mutateCmd.Flags().BoolVar(&ociEmptyBase, "oci-empty-base", false, "If true, scratch base image will have OCI media types instead of Docker")
208+
186209
return mutateCmd
187210
}
188211

0 commit comments

Comments
 (0)