From 8cbb7a93198ef308b9d1a87254977fc57afaaeba Mon Sep 17 00:00:00 2001 From: CrazyMax Date: Mon, 19 Jun 2023 06:10:10 +0200 Subject: [PATCH] build: fix host-gateway handling Signed-off-by: CrazyMax --- build/build.go | 2 +- build/utils.go | 17 ++++++++++++----- driver/manager.go | 40 ++++++++++++++++++++++++++++++++++++++-- 3 files changed, 51 insertions(+), 8 deletions(-) diff --git a/build/build.go b/build/build.go index b480187a336..0d7ef093811 100644 --- a/build/build.go +++ b/build/build.go @@ -645,7 +645,7 @@ func toSolveOpt(ctx context.Context, node builder.Node, multiDriver bool, opt Op } // setup extrahosts - extraHosts, err := toBuildkitExtraHosts(opt.ExtraHosts, nodeDriver.IsMobyDriver()) + extraHosts, err := toBuildkitExtraHosts(ctx, opt.ExtraHosts, nodeDriver) if err != nil { return nil, nil, err } diff --git a/build/utils.go b/build/utils.go index 03a85ca4b4a..ee86ff93a37 100644 --- a/build/utils.go +++ b/build/utils.go @@ -3,10 +3,12 @@ package build import ( "archive/tar" "bytes" + "context" "net" "os" "strings" + "github.com/docker/buildx/driver" "github.com/docker/cli/opts" "github.com/docker/docker/builder/remotecontext/urlutil" "github.com/moby/buildkit/util/gitutil" @@ -57,7 +59,7 @@ func isArchive(header []byte) bool { } // toBuildkitExtraHosts converts hosts from docker key:value format to buildkit's csv format -func toBuildkitExtraHosts(inp []string, mobyDriver bool) (string, error) { +func toBuildkitExtraHosts(ctx context.Context, inp []string, nodeDriver *driver.DriverHandle) (string, error) { if len(inp) == 0 { return "", nil } @@ -67,11 +69,16 @@ func toBuildkitExtraHosts(inp []string, mobyDriver bool) (string, error) { if !ok || host == "" || ip == "" { return "", errors.Errorf("invalid host %s", h) } - // Skip IP address validation for "host-gateway" string with moby driver - if !mobyDriver || ip != mobyHostGatewayName { - if net.ParseIP(ip) == nil { - return "", errors.Errorf("invalid host %s", h) + // If the IP Address is a "host-gateway", replace this value with the + // IP address provided by the worker's label. + if ip == mobyHostGatewayName { + hgip, err := nodeDriver.HostGatewayIP(ctx) + if err != nil { + return "", errors.Wrap(err, "unable to derive the IP value for host-gateway") } + ip = hgip.String() + } else if net.ParseIP(ip) == nil { + return "", errors.Errorf("invalid host %s", h) } hosts = append(hosts, host+"="+ip) } diff --git a/driver/manager.go b/driver/manager.go index 657e5094db3..b4ec318f396 100644 --- a/driver/manager.go +++ b/driver/manager.go @@ -2,17 +2,17 @@ package driver import ( "context" + "net" "os" "sort" "strings" "sync" - "k8s.io/client-go/rest" - dockerclient "github.com/docker/docker/client" "github.com/moby/buildkit/client" specs "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" + "k8s.io/client-go/rest" ) type Factory interface { @@ -154,6 +154,9 @@ type DriverHandle struct { 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) { @@ -178,3 +181,36 @@ 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 +}