diff --git a/driver/docker-container/driver.go b/driver/docker-container/driver.go index d42d233a9..ab09305df 100644 --- a/driver/docker-container/driver.go +++ b/driver/docker-container/driver.go @@ -399,6 +399,10 @@ func (d *Driver) Features(ctx context.Context) map[driver.Feature]bool { } } +func (d *Driver) HostGatewayIP(ctx context.Context) (net.IP, error) { + return nil, errors.New("host-gateway is not supported by the docker-container driver") +} + func demuxConn(c net.Conn) net.Conn { pr, pw := io.Pipe() // TODO: rewrite parser with Reader() to avoid goroutine switch diff --git a/driver/docker/driver.go b/driver/docker/driver.go index e31175c33..8f33e4731 100644 --- a/driver/docker/driver.go +++ b/driver/docker/driver.go @@ -4,6 +4,7 @@ import ( "context" "net" "strings" + "sync" "github.com/docker/buildx/driver" "github.com/docker/buildx/util/progress" @@ -15,6 +16,9 @@ import ( type Driver struct { factory driver.Factory driver.InitConfig + + features features + hostGateway hostGateway } func (d *Driver) Bootstrap(ctx context.Context, l progress.Logger) error { @@ -70,24 +74,67 @@ func (d *Driver) Client(ctx context.Context) (*client.Client, error) { return client.New(ctx, "", opts...) } +type features struct { + once sync.Once + list map[driver.Feature]bool +} + func (d *Driver) Features(ctx context.Context) map[driver.Feature]bool { - var useContainerdSnapshotter bool - c, err := d.Client(ctx) - if err == nil { - workers, _ := c.ListWorkers(ctx) + d.features.once.Do(func() { + var useContainerdSnapshotter bool + if c, err := d.Client(ctx); err == nil { + workers, _ := c.ListWorkers(ctx) + for _, w := range workers { + if _, ok := w.Labels["org.mobyproject.buildkit.worker.snapshotter"]; ok { + useContainerdSnapshotter = true + } + } + c.Close() + } + d.features.list = map[driver.Feature]bool{ + driver.OCIExporter: useContainerdSnapshotter, + driver.DockerExporter: useContainerdSnapshotter, + driver.CacheExport: useContainerdSnapshotter, + driver.MultiPlatform: useContainerdSnapshotter, + } + }) + return d.features.list +} + +type hostGateway struct { + once sync.Once + ip net.IP + err error +} + +func (d *Driver) HostGatewayIP(ctx context.Context) (net.IP, error) { + d.hostGateway.once.Do(func() { + c, err := d.Client(ctx) + if err != nil { + d.hostGateway.err = err + return + } + defer c.Close() + workers, err := c.ListWorkers(ctx) + if err != nil { + d.hostGateway.err = errors.Wrap(err, "listing workers") + return + } for _, w := range workers { - if _, ok := w.Labels["org.mobyproject.buildkit.worker.snapshotter"]; ok { - useContainerdSnapshotter = true + // should match github.com/docker/docker/builder/builder-next/worker/label.HostGatewayIP const + if v, ok := w.Labels["org.mobyproject.buildkit.worker.moby.host-gateway-ip"]; ok && v != "" { + ip := net.ParseIP(v) + if ip == nil { + d.hostGateway.err = errors.Errorf("failed to parse host-gateway IP: %s", v) + return + } + d.hostGateway.ip = ip + return } } - c.Close() - } - return map[driver.Feature]bool{ - driver.OCIExporter: useContainerdSnapshotter, - driver.DockerExporter: useContainerdSnapshotter, - driver.CacheExport: useContainerdSnapshotter, - driver.MultiPlatform: useContainerdSnapshotter, - } + d.hostGateway.err = errors.New("host-gateway IP not found") + }) + return d.hostGateway.ip, d.hostGateway.err } func (d *Driver) Factory() driver.Factory { diff --git a/driver/driver.go b/driver/driver.go index 8642a543c..16d43d7af 100644 --- a/driver/driver.go +++ b/driver/driver.go @@ -3,6 +3,7 @@ package driver import ( "context" "io" + "net" "github.com/docker/buildx/store" "github.com/docker/buildx/util/progress" @@ -60,6 +61,7 @@ type Driver interface { Rm(ctx context.Context, force, rmVolume, rmDaemon bool) error Client(ctx context.Context) (*client.Client, error) Features(ctx context.Context) map[Feature]bool + HostGatewayIP(ctx context.Context) (net.IP, error) IsMobyDriver() bool Config() InitConfig } diff --git a/driver/kubernetes/driver.go b/driver/kubernetes/driver.go index 55c7853da..b67c1203a 100644 --- a/driver/kubernetes/driver.go +++ b/driver/kubernetes/driver.go @@ -236,3 +236,7 @@ func (d *Driver) Features(ctx context.Context) map[driver.Feature]bool { driver.MultiPlatform: true, // Untested (needs multiple Driver instances) } } + +func (d *Driver) HostGatewayIP(ctx context.Context) (net.IP, error) { + return nil, errors.New("host-gateway is not supported by the kubernetes driver") +} diff --git a/driver/manager.go b/driver/manager.go index b4ec318f3..de71746ef 100644 --- a/driver/manager.go +++ b/driver/manager.go @@ -2,7 +2,6 @@ package driver import ( "context" - "net" "os" "sort" "strings" @@ -150,13 +149,8 @@ type DriverHandle struct { client *client.Client err error once sync.Once - featuresOnce sync.Once - features map[Feature]bool historyAPISupportedOnce sync.Once historyAPISupported bool - hostGatewayIPOnce sync.Once - hostGatewayIP net.IP - hostGatewayIPErr error } func (d *DriverHandle) Client(ctx context.Context) (*client.Client, error) { @@ -166,13 +160,6 @@ func (d *DriverHandle) Client(ctx context.Context) (*client.Client, error) { return d.client, d.err } -func (d *DriverHandle) Features(ctx context.Context) map[Feature]bool { - d.featuresOnce.Do(func() { - d.features = d.Driver.Features(ctx) - }) - return d.features -} - func (d *DriverHandle) HistoryAPISupported(ctx context.Context) bool { d.historyAPISupportedOnce.Do(func() { if c, err := d.Client(ctx); err == nil { @@ -181,36 +168,3 @@ func (d *DriverHandle) HistoryAPISupported(ctx context.Context) bool { }) return d.historyAPISupported } - -func (d *DriverHandle) HostGatewayIP(ctx context.Context) (net.IP, error) { - d.hostGatewayIPOnce.Do(func() { - if !d.Driver.IsMobyDriver() { - d.hostGatewayIPErr = errors.New("host-gateway is only supported with the docker driver") - return - } - c, err := d.Client(ctx) - if err != nil { - d.hostGatewayIPErr = err - return - } - workers, err := c.ListWorkers(ctx) - if err != nil { - d.hostGatewayIPErr = errors.Wrap(err, "listing workers") - return - } - for _, w := range workers { - // should match github.com/docker/docker/builder/builder-next/worker/label.HostGatewayIP const - if v, ok := w.Labels["org.mobyproject.buildkit.worker.moby.host-gateway-ip"]; ok && v != "" { - ip := net.ParseIP(v) - if ip == nil { - d.hostGatewayIPErr = errors.Errorf("failed to parse host-gateway IP: %s", v) - return - } - d.hostGatewayIP = ip - return - } - } - d.hostGatewayIPErr = errors.New("host-gateway IP not found") - }) - return d.hostGatewayIP, d.hostGatewayIPErr -} diff --git a/driver/remote/driver.go b/driver/remote/driver.go index c12cf995b..2efd22636 100644 --- a/driver/remote/driver.go +++ b/driver/remote/driver.go @@ -2,6 +2,8 @@ package remote import ( "context" + "errors" + "net" "github.com/docker/buildx/driver" "github.com/docker/buildx/util/progress" @@ -91,6 +93,10 @@ func (d *Driver) Features(ctx context.Context) map[driver.Feature]bool { } } +func (d *Driver) HostGatewayIP(ctx context.Context) (net.IP, error) { + return nil, errors.New("host-gateway is not supported by the remote driver") +} + func (d *Driver) Factory() driver.Factory { return d.factory }