From 3b69482a2f69a6ebd5e6b364bde67b1c332c7e3b Mon Sep 17 00:00:00 2001 From: Tonis Tiigi Date: Wed, 4 Nov 2020 13:04:04 -0800 Subject: [PATCH 1/2] docker-container: ensure credentials are passed when pulling buildkit image Signed-off-by: Tonis Tiigi --- build/build.go | 14 +++++++------- commands/inspect.go | 6 +++--- driver/docker-container/driver.go | 15 +++++++++++---- driver/docker/driver.go | 2 +- driver/driver.go | 11 ++++++++--- driver/kubernetes/driver.go | 2 +- util/imagetools/inspect.go | 22 ++++++++++++++++++++++ 7 files changed, 53 insertions(+), 19 deletions(-) diff --git a/build/build.go b/build/build.go index fd75c44b..4a366ab5 100644 --- a/build/build.go +++ b/build/build.go @@ -127,7 +127,7 @@ func allIndexes(l int) []int { return out } -func ensureBooted(ctx context.Context, drivers []DriverInfo, idxs []int, pw progress.Writer) ([]*client.Client, error) { +func ensureBooted(ctx context.Context, drivers []DriverInfo, idxs []int, auth Auth, pw progress.Writer) ([]*client.Client, error) { clients := make([]*client.Client, len(drivers)) eg, ctx := errgroup.WithContext(ctx) @@ -135,7 +135,7 @@ func ensureBooted(ctx context.Context, drivers []DriverInfo, idxs []int, pw prog for _, i := range idxs { func(i int) { eg.Go(func() error { - c, err := driver.Boot(ctx, drivers[i].Driver, pw) + c, err := driver.Boot(ctx, drivers[i].Driver, auth, pw) if err != nil { return err } @@ -172,7 +172,7 @@ func splitToDriverPairs(availablePlatforms map[string]int, opt map[string]Option return m } -func resolveDrivers(ctx context.Context, drivers []DriverInfo, opt map[string]Options, pw progress.Writer) (map[string][]driverPair, []*client.Client, error) { +func resolveDrivers(ctx context.Context, drivers []DriverInfo, auth Auth, opt map[string]Options, pw progress.Writer) (map[string][]driverPair, []*client.Client, error) { availablePlatforms := map[string]int{} for i, d := range drivers { @@ -199,7 +199,7 @@ func resolveDrivers(ctx context.Context, drivers []DriverInfo, opt map[string]Op for k, opt := range opt { m[k] = []driverPair{{driverIndex: 0, platforms: opt.Platforms}} } - clients, err := ensureBooted(ctx, drivers, driverIndexes(m), pw) + clients, err := ensureBooted(ctx, drivers, driverIndexes(m), auth, pw) if err != nil { return nil, nil, err } @@ -209,7 +209,7 @@ func resolveDrivers(ctx context.Context, drivers []DriverInfo, opt map[string]Op // map based on existing platforms if !undetectedPlatform { m := splitToDriverPairs(availablePlatforms, opt) - clients, err := ensureBooted(ctx, drivers, driverIndexes(m), pw) + clients, err := ensureBooted(ctx, drivers, driverIndexes(m), auth, pw) if err != nil { return nil, nil, err } @@ -217,7 +217,7 @@ func resolveDrivers(ctx context.Context, drivers []DriverInfo, opt map[string]Op } // boot all drivers in k - clients, err := ensureBooted(ctx, drivers, allIndexes(len(drivers)), pw) + clients, err := ensureBooted(ctx, drivers, allIndexes(len(drivers)), auth, pw) if err != nil { return nil, nil, err } @@ -506,7 +506,7 @@ func Build(ctx context.Context, drivers []DriverInfo, opt map[string]Options, do } } - m, clients, err := resolveDrivers(ctx, drivers, opt, pw) + m, clients, err := resolveDrivers(ctx, drivers, auth, opt, pw) if err != nil { close(pw.Status()) <-pw.Done() diff --git a/commands/inspect.go b/commands/inspect.go index 5c7e2a33..ccf1dc34 100644 --- a/commands/inspect.go +++ b/commands/inspect.go @@ -81,7 +81,7 @@ func runInspect(dockerCli command.Cli, in inspectOptions) error { if in.bootstrap { var ok bool - ok, err = boot(ctx, ngi) + ok, err = boot(ctx, ngi, dockerCli) if err != nil { return err } @@ -153,7 +153,7 @@ func inspectCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command { return cmd } -func boot(ctx context.Context, ngi *nginfo) (bool, error) { +func boot(ctx context.Context, ngi *nginfo, dockerCli command.Cli) (bool, error) { toBoot := make([]int, 0, len(ngi.drivers)) for i, d := range ngi.drivers { if d.err != nil || d.di.Err != nil || d.di.Driver == nil || d.info == nil { @@ -176,7 +176,7 @@ func boot(ctx context.Context, ngi *nginfo) (bool, error) { func(idx int) { eg.Go(func() error { pw := mw.WithPrefix(ngi.ng.Nodes[idx].Name, len(toBoot) > 1) - _, err := driver.Boot(ctx, ngi.drivers[idx].di.Driver, pw) + _, err := driver.Boot(ctx, ngi.drivers[idx].di.Driver, dockerCli.ConfigFile(), pw) if err != nil { ngi.drivers[idx].err = err } diff --git a/driver/docker-container/driver.go b/driver/docker-container/driver.go index 49dcb502..d340f0e9 100644 --- a/driver/docker-container/driver.go +++ b/driver/docker-container/driver.go @@ -12,6 +12,7 @@ import ( "github.com/docker/buildx/driver" "github.com/docker/buildx/driver/bkimage" + "github.com/docker/buildx/util/imagetools" "github.com/docker/buildx/util/progress" "github.com/docker/docker/api/types" dockertypes "github.com/docker/docker/api/types" @@ -31,12 +32,12 @@ type Driver struct { env []string } -func (d *Driver) Bootstrap(ctx context.Context, l progress.Logger) error { +func (d *Driver) Bootstrap(ctx context.Context, auth driver.Auth, l progress.Logger) error { return progress.Wrap("[internal] booting buildkit", l, func(sub progress.SubLogger) error { _, err := d.DockerAPI.ContainerInspect(ctx, d.Name) if err != nil { if dockerclient.IsErrNotFound(err) { - return d.create(ctx, sub) + return d.create(ctx, auth, sub) } return err } @@ -52,14 +53,20 @@ func (d *Driver) Bootstrap(ctx context.Context, l progress.Logger) error { }) } -func (d *Driver) create(ctx context.Context, l progress.SubLogger) error { +func (d *Driver) create(ctx context.Context, auth driver.Auth, l progress.SubLogger) error { imageName := bkimage.DefaultImage if d.image != "" { imageName = d.image } if err := l.Wrap("pulling image "+imageName, func() error { - rc, err := d.DockerAPI.ImageCreate(ctx, imageName, types.ImageCreateOptions{}) + ra, err := imagetools.RegistryAuthForRef(imageName, auth) + if err != nil { + return err + } + rc, err := d.DockerAPI.ImageCreate(ctx, imageName, types.ImageCreateOptions{ + RegistryAuth: ra, + }) if err != nil { return err } diff --git a/driver/docker/driver.go b/driver/docker/driver.go index 44ef69d4..d42542cf 100644 --- a/driver/docker/driver.go +++ b/driver/docker/driver.go @@ -15,7 +15,7 @@ type Driver struct { driver.InitConfig } -func (d *Driver) Bootstrap(ctx context.Context, l progress.Logger) error { +func (d *Driver) Bootstrap(ctx context.Context, _ driver.Auth, l progress.Logger) error { return nil } diff --git a/driver/driver.go b/driver/driver.go index da66c6c7..c82d5440 100644 --- a/driver/driver.go +++ b/driver/driver.go @@ -5,6 +5,7 @@ import ( "github.com/docker/buildx/store" "github.com/docker/buildx/util/progress" + clitypes "github.com/docker/cli/cli/config/types" "github.com/moby/buildkit/client" "github.com/pkg/errors" ) @@ -44,9 +45,13 @@ type Info struct { DynamicNodes []store.Node } +type Auth interface { + GetAuthConfig(registryHostname string) (clitypes.AuthConfig, error) +} + type Driver interface { Factory() Factory - Bootstrap(context.Context, progress.Logger) error + Bootstrap(context.Context, Auth, progress.Logger) error Info(context.Context) (*Info, error) Stop(ctx context.Context, force bool) error Rm(ctx context.Context, force bool) error @@ -54,7 +59,7 @@ type Driver interface { Features() map[Feature]bool } -func Boot(ctx context.Context, d Driver, pw progress.Writer) (*client.Client, error) { +func Boot(ctx context.Context, d Driver, auth Auth, pw progress.Writer) (*client.Client, error) { try := 0 for { info, err := d.Info(ctx) @@ -66,7 +71,7 @@ func Boot(ctx context.Context, d Driver, pw progress.Writer) (*client.Client, er if try > 2 { return nil, errors.Errorf("failed to bootstrap %T driver in attempts", d) } - if err := d.Bootstrap(ctx, func(s *client.SolveStatus) { + if err := d.Bootstrap(ctx, auth, func(s *client.SolveStatus) { if pw != nil { pw.Status() <- s } diff --git a/driver/kubernetes/driver.go b/driver/kubernetes/driver.go index 03bbe67b..802dabec 100644 --- a/driver/kubernetes/driver.go +++ b/driver/kubernetes/driver.go @@ -44,7 +44,7 @@ type Driver struct { podChooser podchooser.PodChooser } -func (d *Driver) Bootstrap(ctx context.Context, l progress.Logger) error { +func (d *Driver) Bootstrap(ctx context.Context, auth driver.Auth, l progress.Logger) error { return progress.Wrap("[internal] booting buildkit", l, func(sub progress.SubLogger) error { _, err := d.deploymentClient.Get(ctx, d.deployment.Name, metav1.GetOptions{}) if err != nil { diff --git a/util/imagetools/inspect.go b/util/imagetools/inspect.go index f09b3247..71dc67f9 100644 --- a/util/imagetools/inspect.go +++ b/util/imagetools/inspect.go @@ -3,6 +3,8 @@ package imagetools import ( "bytes" "context" + "encoding/base64" + "encoding/json" "io" "net/http" @@ -107,3 +109,23 @@ func toCredentialsFunc(a Auth) func(string) (string, string, error) { return ac.Username, ac.Password, nil } } + +func RegistryAuthForRef(ref string, a Auth) (string, error) { + r, err := parseRef(ref) + if err != nil { + return "", err + } + host := reference.Domain(r) + if host == "docker.io" { + host = "https://index.docker.io/v1/" + } + ac, err := a.GetAuthConfig(host) + if err != nil { + return "", err + } + buf, err := json.Marshal(ac) + if err != nil { + return "", err + } + return base64.URLEncoding.EncodeToString(buf), nil +} From ea19cf9d8d11ecc4860b4c4aa80b65563e7cec7a Mon Sep 17 00:00:00 2001 From: Tonis Tiigi Date: Wed, 4 Nov 2020 14:39:54 -0800 Subject: [PATCH 2/2] inspect: make sure to show boot error from driver Signed-off-by: Tonis Tiigi --- commands/inspect.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/commands/inspect.go b/commands/inspect.go index ccf1dc34..546706b4 100644 --- a/commands/inspect.go +++ b/commands/inspect.go @@ -79,12 +79,14 @@ func runInspect(dockerCli command.Cli, in inspectOptions) error { err = loadNodeGroupData(timeoutCtx, dockerCli, ngi) + var bootNgi *nginfo if in.bootstrap { var ok bool ok, err = boot(ctx, ngi, dockerCli) if err != nil { return err } + bootNgi = ngi if ok { ngi = &nginfo{ng: ng} err = loadNodeGroupData(ctx, dockerCli, ngi) @@ -113,6 +115,8 @@ func runInspect(dockerCli command.Cli, in inspectOptions) error { fmt.Fprintf(w, "Error:\t%s\n", err.Error()) } else if err := ngi.drivers[i].err; err != nil { fmt.Fprintf(w, "Error:\t%s\n", err.Error()) + } else if bootNgi != nil && len(bootNgi.drivers) > i && bootNgi.drivers[i].err != nil { + fmt.Fprintf(w, "Error:\t%s\n", bootNgi.drivers[i].err.Error()) } else { fmt.Fprintf(w, "Status:\t%s\n", ngi.drivers[i].info.Status) if len(n.Flags) > 0 {