Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support mutating scratch images #1882

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
51 changes: 37 additions & 14 deletions cmd/crane/cmd/mutate.go
Expand Up @@ -20,9 +20,12 @@ import (
"strings"

"github.com/google/go-containerregistry/pkg/crane"
"github.com/google/go-containerregistry/pkg/logs"
"github.com/google/go-containerregistry/pkg/name"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/empty"
"github.com/google/go-containerregistry/pkg/v1/mutate"
"github.com/google/go-containerregistry/pkg/v1/types"
"github.com/spf13/cobra"
)

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

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

if len(annotations) != 0 {
desc, err := crane.Head(ref, *options...)
if err != nil {
return err
if ref == "scratch" {
// you can not write over the original image if the original image is scratch
if newRef == "" {
return errors.New("you must specify tag when a scratch base is used")
}
if desc.MediaType.IsIndex() {
return errors.New("mutating annotations on an index is not yet supported")
// Use an empty image.
logs.Warn.Printf("scratch base specified, using empty image")
img = empty.Image
if ociEmptyBase {
img = mutate.MediaType(img, types.OCIManifestSchema1)
img = mutate.ConfigMediaType(img, types.OCIConfigJSON)
}
} else {
// Pull image and get config.
if len(annotations) != 0 {
desc, err := crane.Head(ref, *options...)
if err != nil {
return err
}
if desc.MediaType.IsIndex() {
return errors.New("mutating annotations on an index is not yet supported")
}
}
}

if newRepo != "" && newRef != "" {
return errors.New("repository can't be set when a tag is specified")
}
if newRepo != "" && newRef != "" {
return errors.New("repository can't be set when a tag is specified")
}

img, err := crane.Pull(ref, *options...)
if err != nil {
return fmt.Errorf("pulling %s: %w", ref, err)
img, err = crane.Pull(ref, *options...)
if err != nil {
return fmt.Errorf("pulling %s: %w", ref, err)
}
}

if len(newLayers) != 0 {
img, err = crane.Append(img, newLayers...)
if err != nil {
Expand Down Expand Up @@ -183,6 +204,8 @@ func NewCmdMutate(options *[]crane.Option) *cobra.Command {
mutateCmd.Flags().StringVarP(&user, "user", "u", "", "New user to set")
mutateCmd.Flags().StringVarP(&workdir, "workdir", "w", "", "New working dir to set")
mutateCmd.Flags().StringSliceVar(&ports, "exposed-ports", nil, "New ports to expose")
mutateCmd.Flags().BoolVar(&ociEmptyBase, "oci-empty-base", false, "If true, scratch base image will have OCI media types instead of Docker")

return mutateCmd
}

Expand Down