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 2 commits 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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 38 additions & 15 deletions cmd/crane/cmd/mutate.go
Original file line number Diff line number Diff line change
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,34 +42,52 @@ func NewCmdMutate(options *[]crane.Option) *cobra.Command {
var user string
var workdir string
var ports []string
var ociEmptyBase bool
var newPlatform string

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 @@ -196,9 +217,11 @@ 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")
// Using "set-platform" to avoid clobbering "platform" persistent flag.
mutateCmd.Flags().StringVar(&newPlatform, "set-platform", "", "New platform to set in the form os/arch[/variant][:osversion] (e.g. linux/amd64)")
return mutateCmd

return mutateCmd
}

// validateKeyVals ensures no values are empty, returns error if they are
Expand Down
Loading