imagetools: give imagetools create a progress bar

Signed-off-by: Justin Chadwell <me@jedevc.com>
pull/1137/head
Justin Chadwell 3 years ago
parent 37ca8631f9
commit 4ecca34a42

@ -1,6 +1,7 @@
package commands package commands
import ( import (
"context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"os" "os"
@ -9,6 +10,7 @@ import (
"github.com/docker/buildx/store" "github.com/docker/buildx/store"
"github.com/docker/buildx/store/storeutil" "github.com/docker/buildx/store/storeutil"
"github.com/docker/buildx/util/imagetools" "github.com/docker/buildx/util/imagetools"
"github.com/docker/buildx/util/progress"
"github.com/docker/cli/cli/command" "github.com/docker/cli/cli/command"
"github.com/docker/distribution/reference" "github.com/docker/distribution/reference"
"github.com/moby/buildkit/util/appcontext" "github.com/moby/buildkit/util/appcontext"
@ -25,6 +27,7 @@ type createOptions struct {
tags []string tags []string
dryrun bool dryrun bool
actionAppend bool actionAppend bool
progress string
} }
func runCreate(dockerCli command.Cli, in createOptions, args []string) error { func runCreate(dockerCli command.Cli, in createOptions, args []string) error {
@ -177,18 +180,45 @@ func runCreate(dockerCli command.Cli, in createOptions, args []string) error {
// new resolver cause need new auth // new resolver cause need new auth
r = imagetools.New(imageopt) r = imagetools.New(imageopt)
ctx2, cancel := context.WithCancel(context.TODO())
defer cancel()
printer := progress.NewPrinter(ctx2, os.Stderr, os.Stderr, in.progress)
eg, _ := errgroup.WithContext(ctx)
pw := progress.WithPrefix(printer, "internal", true)
for _, t := range tags { for _, t := range tags {
if err := r.Copy(ctx, srcs, t); err != nil { t := t
return err eg.Go(func() error {
} return progress.Wrap(fmt.Sprintf("pushing %s", t.String()), pw.Write, func(sub progress.SubLogger) error {
eg2, _ := errgroup.WithContext(ctx)
for _, s := range srcs {
if reference.Domain(s.Ref) == reference.Domain(t) && reference.Path(s.Ref) == reference.Path(t) {
continue
}
s := s
eg2.Go(func() error {
sub.Log(1, []byte(fmt.Sprintf("copying %s from %s to %s\n", s.Desc.Digest.String(), s.Ref.String(), t.String())))
return r.Copy(ctx, s, t)
})
}
if err := eg2.Wait(); err != nil {
return err
}
sub.Log(1, []byte(fmt.Sprintf("pushing %s to %s\n", desc.Digest.String(), t.String())))
return r.Push(ctx, t, desc, dt)
})
})
}
if err := r.Push(ctx, t, desc, dt); err != nil { err = eg.Wait()
return err err1 := printer.Wait()
} if err == nil {
fmt.Println(t.String()) err = err1
} }
return nil return err
} }
func parseSources(in []string) ([]*imagetools.Source, error) { func parseSources(in []string) ([]*imagetools.Source, error) {
@ -261,6 +291,7 @@ func createCmd(dockerCli command.Cli, opts RootOptions) *cobra.Command {
flags.StringArrayVarP(&options.tags, "tag", "t", []string{}, "Set reference for new image") flags.StringArrayVarP(&options.tags, "tag", "t", []string{}, "Set reference for new image")
flags.BoolVar(&options.dryrun, "dry-run", false, "Show final image instead of pushing") flags.BoolVar(&options.dryrun, "dry-run", false, "Show final image instead of pushing")
flags.BoolVar(&options.actionAppend, "append", false, "Append to existing manifest") flags.BoolVar(&options.actionAppend, "append", false, "Append to existing manifest")
flags.StringVar(&options.progress, "progress", "auto", `Set type of progress output ("auto", "plain", "tty"). Use plain to show container output`)
return cmd return cmd
} }

@ -15,6 +15,7 @@ Create a new image based on source images
| [`--builder`](#builder) | `string` | | Override the configured builder instance | | [`--builder`](#builder) | `string` | | Override the configured builder instance |
| [`--dry-run`](#dry-run) | | | Show final image instead of pushing | | [`--dry-run`](#dry-run) | | | Show final image instead of pushing |
| [`-f`](#file), [`--file`](#file) | `stringArray` | | Read source descriptor from file | | [`-f`](#file), [`--file`](#file) | `stringArray` | | Read source descriptor from file |
| `--progress` | `string` | `auto` | Set type of progress output (`auto`, `plain`, `tty`). Use plain to show container output |
| [`-t`](#tag), [`--tag`](#tag) | `stringArray` | | Set reference for new image | | [`-t`](#tag), [`--tag`](#tag) | `stringArray` | | Set reference for new image |

@ -170,30 +170,23 @@ func (r *Resolver) Push(ctx context.Context, ref reference.Named, desc ocispec.D
return err return err
} }
func (r *Resolver) Copy(ctx context.Context, srcs []*Source, dest reference.Named) error { func (r *Resolver) Copy(ctx context.Context, src *Source, dest reference.Named) error {
dest = reference.TagNameOnly(dest) dest = reference.TagNameOnly(dest)
p, err := r.resolver().Pusher(ctx, dest.String()) p, err := r.resolver().Pusher(ctx, dest.String())
if err != nil { if err != nil {
return err return err
} }
for _, src := range srcs { srcRef := reference.TagNameOnly(src.Ref)
if reference.Domain(src.Ref) == reference.Domain(dest) && reference.Path(src.Ref) == reference.Path(dest) { f, err := r.resolver().Fetcher(ctx, srcRef.String())
continue if err != nil {
} return err
srcRef := reference.TagNameOnly(src.Ref)
f, err := r.resolver().Fetcher(ctx, srcRef.String())
if err != nil {
return err
}
err = contentutil.CopyChain(ctx, contentutil.FromPusher(p), contentutil.FromFetcher(f), src.Desc)
if err != nil {
return err
}
} }
err = contentutil.CopyChain(ctx, contentutil.FromPusher(p), contentutil.FromFetcher(f), src.Desc)
if err != nil {
return err
}
return nil return nil
} }

Loading…
Cancel
Save