mirror of
				https://gitea.com/Lydanne/buildx.git
				synced 2025-11-04 18:13:42 +08:00 
			
		
		
		
	Because remote driver implements Info() by calling Client() internally, two instances on Client are created backed by separate TCP connection. This hack avoids it and improves performance. Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
		
			
				
	
	
		
			185 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			185 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package remote
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"crypto/tls"
 | 
						|
	"crypto/x509"
 | 
						|
	"net"
 | 
						|
	"os"
 | 
						|
	"strings"
 | 
						|
	"sync"
 | 
						|
	"time"
 | 
						|
 | 
						|
	"github.com/docker/buildx/driver"
 | 
						|
	util "github.com/docker/buildx/driver/remote/util"
 | 
						|
	"github.com/docker/buildx/util/progress"
 | 
						|
	"github.com/moby/buildkit/client"
 | 
						|
	"github.com/moby/buildkit/client/connhelper"
 | 
						|
	"github.com/moby/buildkit/util/tracing/delegated"
 | 
						|
	"github.com/pkg/errors"
 | 
						|
)
 | 
						|
 | 
						|
type Driver struct {
 | 
						|
	factory driver.Factory
 | 
						|
	driver.InitConfig
 | 
						|
 | 
						|
	// if you add fields, remember to update docs:
 | 
						|
	// https://github.com/docker/docs/blob/main/content/build/drivers/remote.md
 | 
						|
	*tlsOpts
 | 
						|
	defaultLoad bool
 | 
						|
 | 
						|
	// remote driver caches the client because its Bootstap/Info methods reuse it internally
 | 
						|
	clientOnce sync.Once
 | 
						|
	client     *client.Client
 | 
						|
	err        error
 | 
						|
}
 | 
						|
 | 
						|
type tlsOpts struct {
 | 
						|
	serverName string
 | 
						|
	caCert     string
 | 
						|
	cert       string
 | 
						|
	key        string
 | 
						|
}
 | 
						|
 | 
						|
func (d *Driver) Bootstrap(ctx context.Context, l progress.Logger) error {
 | 
						|
	c, err := d.Client(ctx)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	return progress.Wrap("[internal] waiting for connection", l, func(_ progress.SubLogger) error {
 | 
						|
		ctx, cancel := context.WithTimeout(ctx, 20*time.Second)
 | 
						|
		defer cancel()
 | 
						|
		return c.Wait(ctx)
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
func (d *Driver) Info(ctx context.Context) (*driver.Info, error) {
 | 
						|
	c, err := d.Client(ctx)
 | 
						|
	if err != nil {
 | 
						|
		return &driver.Info{
 | 
						|
			Status: driver.Inactive,
 | 
						|
		}, nil
 | 
						|
	}
 | 
						|
 | 
						|
	if _, err := c.ListWorkers(ctx); err != nil {
 | 
						|
		return &driver.Info{
 | 
						|
			Status: driver.Inactive,
 | 
						|
		}, nil
 | 
						|
	}
 | 
						|
 | 
						|
	return &driver.Info{
 | 
						|
		Status: driver.Running,
 | 
						|
	}, nil
 | 
						|
}
 | 
						|
 | 
						|
func (d *Driver) Version(ctx context.Context) (string, error) {
 | 
						|
	return "", nil
 | 
						|
}
 | 
						|
 | 
						|
func (d *Driver) Stop(ctx context.Context, force bool) error {
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (d *Driver) Rm(ctx context.Context, force, rmVolume, rmDaemon bool) error {
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (d *Driver) Client(ctx context.Context, opts ...client.ClientOpt) (*client.Client, error) {
 | 
						|
	d.clientOnce.Do(func() {
 | 
						|
		opts = append([]client.ClientOpt{
 | 
						|
			client.WithContextDialer(func(ctx context.Context, _ string) (net.Conn, error) {
 | 
						|
				return d.Dial(ctx)
 | 
						|
			}),
 | 
						|
			client.WithTracerDelegate(delegated.DefaultExporter),
 | 
						|
		}, opts...)
 | 
						|
		c, err := client.New(ctx, "", opts...)
 | 
						|
		d.client = c
 | 
						|
		d.err = err
 | 
						|
	})
 | 
						|
	return d.client, d.err
 | 
						|
}
 | 
						|
 | 
						|
func (d *Driver) Dial(ctx context.Context) (net.Conn, error) {
 | 
						|
	addr := d.InitConfig.EndpointAddr
 | 
						|
	ch, err := connhelper.GetConnectionHelper(addr)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	if ch != nil {
 | 
						|
		return ch.ContextDialer(ctx, addr)
 | 
						|
	}
 | 
						|
 | 
						|
	network, addr, ok := strings.Cut(addr, "://")
 | 
						|
	if !ok {
 | 
						|
		return nil, errors.Errorf("invalid endpoint address: %s", d.InitConfig.EndpointAddr)
 | 
						|
	}
 | 
						|
 | 
						|
	conn, err := util.DialContext(ctx, network, addr)
 | 
						|
 | 
						|
	if err != nil {
 | 
						|
		return nil, errors.WithStack(err)
 | 
						|
	}
 | 
						|
 | 
						|
	if d.tlsOpts != nil {
 | 
						|
		cfg, err := loadTLS(d.tlsOpts)
 | 
						|
		if err != nil {
 | 
						|
			return nil, errors.Wrap(err, "error loading tls config")
 | 
						|
		}
 | 
						|
		conn = tls.Client(conn, cfg)
 | 
						|
	}
 | 
						|
	return conn, nil
 | 
						|
}
 | 
						|
 | 
						|
func loadTLS(opts *tlsOpts) (*tls.Config, error) {
 | 
						|
	cfg := &tls.Config{
 | 
						|
		ServerName: opts.serverName,
 | 
						|
		RootCAs:    x509.NewCertPool(),
 | 
						|
	}
 | 
						|
 | 
						|
	if opts.caCert != "" {
 | 
						|
		ca, err := os.ReadFile(opts.caCert)
 | 
						|
		if err != nil {
 | 
						|
			return nil, errors.Wrap(err, "could not read ca certificate")
 | 
						|
		}
 | 
						|
		if ok := cfg.RootCAs.AppendCertsFromPEM(ca); !ok {
 | 
						|
			return nil, errors.New("failed to append ca certs")
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if opts.cert != "" || opts.key != "" {
 | 
						|
		cert, err := tls.LoadX509KeyPair(opts.cert, opts.key)
 | 
						|
		if err != nil {
 | 
						|
			return nil, errors.Wrap(err, "could not read certificate/key")
 | 
						|
		}
 | 
						|
		cfg.Certificates = append(cfg.Certificates, cert)
 | 
						|
	}
 | 
						|
 | 
						|
	return cfg, nil
 | 
						|
}
 | 
						|
 | 
						|
func (d *Driver) Features(ctx context.Context) map[driver.Feature]bool {
 | 
						|
	return map[driver.Feature]bool{
 | 
						|
		driver.OCIExporter:    true,
 | 
						|
		driver.DockerExporter: true,
 | 
						|
		driver.CacheExport:    true,
 | 
						|
		driver.MultiPlatform:  true,
 | 
						|
		driver.DefaultLoad:    d.defaultLoad,
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
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
 | 
						|
}
 | 
						|
 | 
						|
func (d *Driver) IsMobyDriver() bool {
 | 
						|
	return false
 | 
						|
}
 | 
						|
 | 
						|
func (d *Driver) Config() driver.InitConfig {
 | 
						|
	return d.InitConfig
 | 
						|
}
 |