Merge pull request #2018 from crazy-max/driver-client-meta

driver(docker): opt to set additional dial meta to the client
This commit is contained in:
CrazyMax
2023-10-16 16:14:34 -07:00
committed by GitHub
22 changed files with 137 additions and 93 deletions

View File

@@ -428,6 +428,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

View File

@@ -29,7 +29,7 @@ func (*factory) Usage() string {
return "docker-container"
}
func (*factory) Priority(ctx context.Context, endpoint string, api dockerclient.APIClient) int {
func (*factory) Priority(ctx context.Context, endpoint string, api dockerclient.APIClient, dialMeta map[string][]string) int {
if api == nil {
return priorityUnsupported
}

View File

@@ -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 {
@@ -54,7 +58,7 @@ func (d *Driver) Rm(ctx context.Context, force, rmVolume, rmDaemon bool) error {
func (d *Driver) Client(ctx context.Context) (*client.Client, error) {
opts := []client.ClientOpt{
client.WithContextDialer(func(context.Context, string) (net.Conn, error) {
return d.DockerAPI.DialHijack(ctx, "/grpc", "h2c", nil)
return d.DockerAPI.DialHijack(ctx, "/grpc", "h2c", d.DialMeta)
}), client.WithSessionDialer(func(ctx context.Context, proto string, meta map[string][]string) (net.Conn, error) {
return d.DockerAPI.DialHijack(ctx, "/session", proto, meta)
}),
@@ -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 {

View File

@@ -26,12 +26,12 @@ func (*factory) Usage() string {
return "docker"
}
func (*factory) Priority(ctx context.Context, endpoint string, api dockerclient.APIClient) int {
func (*factory) Priority(ctx context.Context, endpoint string, api dockerclient.APIClient, dialMeta map[string][]string) int {
if api == nil {
return priorityUnsupported
}
c, err := api.DialHijack(ctx, "/grpc", "h2c", nil)
c, err := api.DialHijack(ctx, "/grpc", "h2c", dialMeta)
if err != nil {
return priorityUnsupported
}

View File

@@ -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
}

View File

@@ -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")
}

View File

@@ -34,7 +34,7 @@ func (*factory) Usage() string {
return DriverName
}
func (*factory) Priority(ctx context.Context, endpoint string, api dockerclient.APIClient) int {
func (*factory) Priority(ctx context.Context, endpoint string, api dockerclient.APIClient, dialMeta map[string][]string) int {
if api == nil {
return priorityUnsupported
}

View File

@@ -2,7 +2,6 @@ package driver
import (
"context"
"net"
"os"
"sort"
"strings"
@@ -18,7 +17,7 @@ import (
type Factory interface {
Name() string
Usage() string
Priority(ctx context.Context, endpoint string, api dockerclient.APIClient) int
Priority(ctx context.Context, endpoint string, api dockerclient.APIClient, dialMeta map[string][]string) int
New(ctx context.Context, cfg InitConfig) (Driver, error)
AllowsInstances() bool
}
@@ -58,8 +57,8 @@ type InitConfig struct {
DriverOpts map[string]string
Auth Auth
Platforms []specs.Platform
// ContextPathHash can be used for determining pods in the driver instance
ContextPathHash string
ContextPathHash string // can be used for determining pods in the driver instance
DialMeta map[string][]string
}
var drivers map[string]Factory
@@ -71,7 +70,7 @@ func Register(f Factory) {
drivers[f.Name()] = f
}
func GetDefaultFactory(ctx context.Context, ep string, c dockerclient.APIClient, instanceRequired bool) (Factory, error) {
func GetDefaultFactory(ctx context.Context, ep string, c dockerclient.APIClient, instanceRequired bool, dialMeta map[string][]string) (Factory, error) {
if len(drivers) == 0 {
return nil, errors.Errorf("no drivers available")
}
@@ -84,7 +83,7 @@ func GetDefaultFactory(ctx context.Context, ep string, c dockerclient.APIClient,
if instanceRequired && !f.AllowsInstances() {
continue
}
dd = append(dd, p{f: f, priority: f.Priority(ctx, ep, c)})
dd = append(dd, p{f: f, priority: f.Priority(ctx, ep, c, dialMeta)})
}
sort.Slice(dd, func(i, j int) bool {
return dd[i].priority < dd[j].priority
@@ -104,7 +103,7 @@ func GetFactory(name string, instanceRequired bool) (Factory, error) {
return nil, errors.Errorf("failed to find driver %q", name)
}
func GetDriver(ctx context.Context, name string, f Factory, endpointAddr string, api dockerclient.APIClient, auth Auth, kcc KubeClientConfig, flags []string, files map[string][]byte, do map[string]string, platforms []specs.Platform, contextPathHash string) (*DriverHandle, error) {
func GetDriver(ctx context.Context, name string, f Factory, endpointAddr string, api dockerclient.APIClient, auth Auth, kcc KubeClientConfig, flags []string, files map[string][]byte, do map[string]string, platforms []specs.Platform, contextPathHash string, dialMeta map[string][]string) (*DriverHandle, error) {
ic := InitConfig{
EndpointAddr: endpointAddr,
DockerAPI: api,
@@ -115,11 +114,12 @@ func GetDriver(ctx context.Context, name string, f Factory, endpointAddr string,
Auth: auth,
Platforms: platforms,
ContextPathHash: contextPathHash,
DialMeta: dialMeta,
Files: files,
}
if f == nil {
var err error
f, err = GetDefaultFactory(ctx, endpointAddr, api, false)
f, err = GetDefaultFactory(ctx, endpointAddr, api, false, dialMeta)
if err != nil {
return nil, err
}
@@ -150,13 +150,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 +161,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 +169,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
}

View File

@@ -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
}

View File

@@ -35,7 +35,7 @@ func (*factory) Usage() string {
return "remote"
}
func (*factory) Priority(ctx context.Context, endpoint string, api dockerclient.APIClient) int {
func (*factory) Priority(ctx context.Context, endpoint string, api dockerclient.APIClient, dialMeta map[string][]string) int {
if util.IsValidEndpoint(endpoint) != nil {
return priorityUnsupported
}