github.com/pdmccormick/importable-docker-buildx@v0.0.0-20240426161518-e47091289030/driver/docker/driver.go (about)

     1  package docker
     2  
     3  import (
     4  	"context"
     5  	"net"
     6  	"strings"
     7  	"sync"
     8  
     9  	"github.com/docker/buildx/driver"
    10  	"github.com/docker/buildx/util/progress"
    11  	"github.com/moby/buildkit/client"
    12  	"github.com/pkg/errors"
    13  )
    14  
    15  type Driver struct {
    16  	factory driver.Factory
    17  	driver.InitConfig
    18  
    19  	// if you add fields, remember to update docs:
    20  	// https://github.com/docker/docs/blob/main/content/build/drivers/docker.md
    21  	features    features
    22  	hostGateway hostGateway
    23  }
    24  
    25  func (d *Driver) Bootstrap(ctx context.Context, l progress.Logger) error {
    26  	return nil
    27  }
    28  
    29  func (d *Driver) Info(ctx context.Context) (*driver.Info, error) {
    30  	_, err := d.DockerAPI.ServerVersion(ctx)
    31  	if err != nil {
    32  		return nil, errors.Wrapf(driver.ErrNotConnecting, err.Error())
    33  	}
    34  	return &driver.Info{
    35  		Status: driver.Running,
    36  	}, nil
    37  }
    38  
    39  func (d *Driver) Version(ctx context.Context) (string, error) {
    40  	v, err := d.DockerAPI.ServerVersion(ctx)
    41  	if err != nil {
    42  		return "", errors.Wrapf(driver.ErrNotConnecting, err.Error())
    43  	}
    44  	if bkversion, _ := resolveBuildKitVersion(v.Version); bkversion != "" {
    45  		return bkversion, nil
    46  	}
    47  	// https://github.com/moby/moby/blob/efc7a2abc3ab6dfa7d8d5d8c1c3b99138989b0f1/builder/builder-next/worker/worker.go#L176
    48  	return strings.TrimSuffix(v.Version, "-moby"), nil
    49  }
    50  
    51  func (d *Driver) Stop(ctx context.Context, force bool) error {
    52  	return nil
    53  }
    54  
    55  func (d *Driver) Rm(ctx context.Context, force, rmVolume, rmDaemon bool) error {
    56  	return nil
    57  }
    58  
    59  func (d *Driver) Dial(ctx context.Context) (net.Conn, error) {
    60  	return d.DockerAPI.DialHijack(ctx, "/grpc", "h2c", d.DialMeta)
    61  }
    62  
    63  func (d *Driver) Client(ctx context.Context, opts ...client.ClientOpt) (*client.Client, error) {
    64  	opts = append([]client.ClientOpt{
    65  		client.WithContextDialer(func(context.Context, string) (net.Conn, error) {
    66  			return d.Dial(ctx)
    67  		}), client.WithSessionDialer(func(ctx context.Context, proto string, meta map[string][]string) (net.Conn, error) {
    68  			return d.DockerAPI.DialHijack(ctx, "/session", proto, meta)
    69  		}),
    70  	}, opts...)
    71  	return client.New(ctx, "", opts...)
    72  }
    73  
    74  type features struct {
    75  	once sync.Once
    76  	list map[driver.Feature]bool
    77  }
    78  
    79  func (d *Driver) Features(ctx context.Context) map[driver.Feature]bool {
    80  	d.features.once.Do(func() {
    81  		var useContainerdSnapshotter bool
    82  		if c, err := d.Client(ctx); err == nil {
    83  			workers, _ := c.ListWorkers(ctx)
    84  			for _, w := range workers {
    85  				if _, ok := w.Labels["org.mobyproject.buildkit.worker.snapshotter"]; ok {
    86  					useContainerdSnapshotter = true
    87  				}
    88  			}
    89  			c.Close()
    90  		}
    91  		d.features.list = map[driver.Feature]bool{
    92  			driver.OCIExporter:    useContainerdSnapshotter,
    93  			driver.DockerExporter: useContainerdSnapshotter,
    94  			driver.CacheExport:    useContainerdSnapshotter,
    95  			driver.MultiPlatform:  useContainerdSnapshotter,
    96  			driver.DefaultLoad:    true,
    97  		}
    98  	})
    99  	return d.features.list
   100  }
   101  
   102  type hostGateway struct {
   103  	once sync.Once
   104  	ip   net.IP
   105  	err  error
   106  }
   107  
   108  func (d *Driver) HostGatewayIP(ctx context.Context) (net.IP, error) {
   109  	d.hostGateway.once.Do(func() {
   110  		c, err := d.Client(ctx)
   111  		if err != nil {
   112  			d.hostGateway.err = err
   113  			return
   114  		}
   115  		defer c.Close()
   116  		workers, err := c.ListWorkers(ctx)
   117  		if err != nil {
   118  			d.hostGateway.err = errors.Wrap(err, "listing workers")
   119  			return
   120  		}
   121  		for _, w := range workers {
   122  			// should match github.com/docker/docker/builder/builder-next/worker/label.HostGatewayIP const
   123  			if v, ok := w.Labels["org.mobyproject.buildkit.worker.moby.host-gateway-ip"]; ok && v != "" {
   124  				ip := net.ParseIP(v)
   125  				if ip == nil {
   126  					d.hostGateway.err = errors.Errorf("failed to parse host-gateway IP: %s", v)
   127  					return
   128  				}
   129  				d.hostGateway.ip = ip
   130  				return
   131  			}
   132  		}
   133  		d.hostGateway.err = errors.New("host-gateway IP not found")
   134  	})
   135  	return d.hostGateway.ip, d.hostGateway.err
   136  }
   137  
   138  func (d *Driver) Factory() driver.Factory {
   139  	return d.factory
   140  }
   141  
   142  func (d *Driver) IsMobyDriver() bool {
   143  	return true
   144  }
   145  
   146  func (d *Driver) Config() driver.InitConfig {
   147  	return d.InitConfig
   148  }