diff --git a/cmd/buildah/bud.go b/cmd/buildah/bud.go index 944cc9d15..b603bf266 100644 --- a/cmd/buildah/bud.go +++ b/cmd/buildah/bud.go @@ -47,7 +47,7 @@ var ( Name: "runtime-flag", Usage: "add global flags for the container runtime", }, - cli.StringFlag{ + cli.StringSliceFlag{ Name: "tag, t", Usage: "`tag` to apply to the built image", }, @@ -70,8 +70,13 @@ var ( func budCmd(c *cli.Context) error { output := "" - if c.IsSet("tag") { - output = c.String("tag") + tags := []string{} + if c.IsSet("tag") || c.IsSet("t") { + tags = c.StringSlice("tag") + if len(tags) > 0 { + output = tags[0] + tags = tags[1:] + } } registry := DefaultRegistry if c.IsSet("registry") { @@ -194,6 +199,7 @@ func budCmd(c *cli.Context) error { SignaturePolicyPath: signaturePolicy, Args: args, Output: output, + AdditionalTags: tags, Runtime: runtime, RuntimeArgs: runtimeFlags, } diff --git a/commit.go b/commit.go index f90dbf41c..a073add41 100644 --- a/commit.go +++ b/commit.go @@ -1,8 +1,12 @@ package buildah import ( + "fmt" + "github.com/containers/image/copy" + "github.com/containers/image/docker/reference" "github.com/containers/image/signature" + "github.com/containers/image/storage" "github.com/containers/image/types" "github.com/containers/storage/pkg/archive" ) @@ -19,10 +23,32 @@ type CommitOptions struct { // specified, indicating that the shared, system-wide default policy // should be used. SignaturePolicyPath string + // AdditionalTags is a list of additional names to add to the image, if + // the transport to which we're writing the image gives us a way to add + // them. + AdditionalTags []string +} + +func expandTags(tags []string) ([]string, error) { + expanded := []string{} + for _, tag := range tags { + name, err := reference.ParseNormalizedNamed(tag) + if err != nil { + return nil, fmt.Errorf("error parsing tag %q: %v", tag, err) + } + name = reference.TagNameOnly(name) + tag = "" + if tagged, ok := name.(reference.NamedTagged); ok { + tag = ":" + tagged.Tag() + } + expanded = append(expanded, name.Name()+tag) + } + return expanded, nil } // Commit writes the contents of the container, along with its updated -// configuration, to a new image in the specified location. +// configuration, to a new image in the specified location, and if we know how, +// add any additional tags that were specified. func (b *Builder) Commit(dest types.ImageReference, options CommitOptions) error { policy, err := signature.DefaultPolicy(getSystemContext(options.SignaturePolicyPath)) if err != nil { @@ -37,5 +63,20 @@ func (b *Builder) Commit(dest types.ImageReference, options CommitOptions) error return err } err = copy.Image(policyContext, dest, src, getCopyOptions()) + switch dest.Transport().Name() { + case storage.Transport.Name(): + tags, err := expandTags(options.AdditionalTags) + if err != nil { + return err + } + img, err := storage.Transport.GetStoreImage(b.store, dest) + if err != nil { + return err + } + err = b.store.SetNames(img.ID, append(img.Names, tags...)) + if err != nil { + return fmt.Errorf("error setting image names to %v: %v", append(img.Names, tags...), err) + } + } return err } diff --git a/imagebuildah/build.go b/imagebuildah/build.go index bf56d3c47..d5d96fac5 100644 --- a/imagebuildah/build.go +++ b/imagebuildah/build.go @@ -70,6 +70,9 @@ type BuildOptions struct { Args map[string]string // Name of the image to write to. Output string + // Additional tags to add to the image that we write, if we know of a + // way to add them. + AdditionalTags []string // Log is a callback that will print a progress message. If no value // is supplied, the message will be sent to Err (or os.Stderr, if Err // is nil) by default. @@ -101,6 +104,7 @@ type Executor struct { transientMounts []Mount compression archive.Compression output string + additionalTags []string log func(format string, args ...interface{}) out io.Writer err io.Writer @@ -376,6 +380,7 @@ func NewExecutor(store storage.Store, options BuildOptions) (*Executor, error) { transientMounts: options.TransientMounts, compression: options.Compression, output: options.Output, + additionalTags: options.AdditionalTags, signaturePolicyPath: options.SignaturePolicyPath, systemContext: makeSystemContext(options.SignaturePolicyPath), volumeCache: make(map[string]string), @@ -520,6 +525,7 @@ func (b *Executor) Commit(ib *imagebuilder.Builder) (err error) { options := buildah.CommitOptions{ Compression: b.compression, SignaturePolicyPath: b.signaturePolicyPath, + AdditionalTags: b.additionalTags, } return b.builder.Commit(imageRef, options) } diff --git a/tests/bud.bats b/tests/bud.bats index f3ed7f2a4..141dc9cf7 100644 --- a/tests/bud.bats +++ b/tests/bud.bats @@ -168,3 +168,20 @@ load helpers run buildah --debug=false images -q [ "$output" = "" ] } + +@test "bud-additional-tags" { + target=scratch-image + target2=another-scratch-image + target3=so-many-scratch-images + buildah bud --signature-policy ${TESTSDIR}/policy.json -t ${target} -t ${target2} -t ${target3} ${TESTSDIR}/bud/from-scratch + run buildah --debug=false images + cid=$(buildah from ${target}) + buildah rm ${cid} + cid=$(buildah from library/${target2}) + buildah rm ${cid} + cid=$(buildah from ${target3}:latest) + buildah rm ${cid} + buildah rmi $(buildah --debug=false images -q) + run buildah --debug=false images -q + [ "$output" = "" ] +}