github.com/pdmccormick/importable-docker-buildx@v0.0.0-20240426161518-e47091289030/driver/remote/driver.go (about) 1 package remote 2 3 import ( 4 "context" 5 "crypto/tls" 6 "crypto/x509" 7 "net" 8 "os" 9 "strings" 10 "time" 11 12 "github.com/docker/buildx/driver" 13 util "github.com/docker/buildx/driver/remote/util" 14 "github.com/docker/buildx/util/progress" 15 "github.com/moby/buildkit/client" 16 "github.com/moby/buildkit/client/connhelper" 17 "github.com/pkg/errors" 18 ) 19 20 type Driver struct { 21 factory driver.Factory 22 driver.InitConfig 23 24 // if you add fields, remember to update docs: 25 // https://github.com/docker/docs/blob/main/content/build/drivers/remote.md 26 *tlsOpts 27 defaultLoad bool 28 } 29 30 type tlsOpts struct { 31 serverName string 32 caCert string 33 cert string 34 key string 35 } 36 37 func (d *Driver) Bootstrap(ctx context.Context, l progress.Logger) error { 38 c, err := d.Client(ctx) 39 if err != nil { 40 return err 41 } 42 return progress.Wrap("[internal] waiting for connection", l, func(_ progress.SubLogger) error { 43 ctx, cancel := context.WithTimeout(ctx, 20*time.Second) 44 defer cancel() 45 return c.Wait(ctx) 46 }) 47 } 48 49 func (d *Driver) Info(ctx context.Context) (*driver.Info, error) { 50 c, err := d.Client(ctx) 51 if err != nil { 52 return &driver.Info{ 53 Status: driver.Inactive, 54 }, nil 55 } 56 57 if _, err := c.ListWorkers(ctx); err != nil { 58 return &driver.Info{ 59 Status: driver.Inactive, 60 }, nil 61 } 62 63 return &driver.Info{ 64 Status: driver.Running, 65 }, nil 66 } 67 68 func (d *Driver) Version(ctx context.Context) (string, error) { 69 return "", nil 70 } 71 72 func (d *Driver) Stop(ctx context.Context, force bool) error { 73 return nil 74 } 75 76 func (d *Driver) Rm(ctx context.Context, force, rmVolume, rmDaemon bool) error { 77 return nil 78 } 79 80 func (d *Driver) Client(ctx context.Context, opts ...client.ClientOpt) (*client.Client, error) { 81 opts = append([]client.ClientOpt{ 82 client.WithContextDialer(func(ctx context.Context, _ string) (net.Conn, error) { 83 return d.Dial(ctx) 84 }), 85 }, opts...) 86 return client.New(ctx, "", opts...) 87 } 88 89 func (d *Driver) Dial(ctx context.Context) (net.Conn, error) { 90 addr := d.InitConfig.EndpointAddr 91 ch, err := connhelper.GetConnectionHelper(addr) 92 if err != nil { 93 return nil, err 94 } 95 if ch != nil { 96 return ch.ContextDialer(ctx, addr) 97 } 98 99 network, addr, ok := strings.Cut(addr, "://") 100 if !ok { 101 return nil, errors.Errorf("invalid endpoint address: %s", d.InitConfig.EndpointAddr) 102 } 103 104 conn, err := util.DialContext(ctx, network, addr) 105 106 if err != nil { 107 return nil, errors.WithStack(err) 108 } 109 110 if d.tlsOpts != nil { 111 cfg, err := loadTLS(d.tlsOpts) 112 if err != nil { 113 return nil, errors.Wrap(err, "error loading tls config") 114 } 115 conn = tls.Client(conn, cfg) 116 } 117 return conn, nil 118 } 119 120 func loadTLS(opts *tlsOpts) (*tls.Config, error) { 121 cfg := &tls.Config{ 122 ServerName: opts.serverName, 123 RootCAs: x509.NewCertPool(), 124 } 125 126 if opts.caCert != "" { 127 ca, err := os.ReadFile(opts.caCert) 128 if err != nil { 129 return nil, errors.Wrap(err, "could not read ca certificate") 130 } 131 if ok := cfg.RootCAs.AppendCertsFromPEM(ca); !ok { 132 return nil, errors.New("failed to append ca certs") 133 } 134 } 135 136 if opts.cert != "" || opts.key != "" { 137 cert, err := tls.LoadX509KeyPair(opts.cert, opts.key) 138 if err != nil { 139 return nil, errors.Wrap(err, "could not read certificate/key") 140 } 141 cfg.Certificates = append(cfg.Certificates, cert) 142 } 143 144 return cfg, nil 145 } 146 147 func (d *Driver) Features(ctx context.Context) map[driver.Feature]bool { 148 return map[driver.Feature]bool{ 149 driver.OCIExporter: true, 150 driver.DockerExporter: true, 151 driver.CacheExport: true, 152 driver.MultiPlatform: true, 153 driver.DefaultLoad: d.defaultLoad, 154 } 155 } 156 157 func (d *Driver) HostGatewayIP(ctx context.Context) (net.IP, error) { 158 return nil, errors.New("host-gateway is not supported by the remote driver") 159 } 160 161 func (d *Driver) Factory() driver.Factory { 162 return d.factory 163 } 164 165 func (d *Driver) IsMobyDriver() bool { 166 return false 167 } 168 169 func (d *Driver) Config() driver.InitConfig { 170 return d.InitConfig 171 }