File: driver.go

package info (click to toggle)
docker-buildx 0.13.1%2Bds1-3
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 2,356 kB
  • sloc: sh: 299; makefile: 87
file content (156 lines) | stat: -rw-r--r-- 4,080 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package docker

import (
	"context"
	"net"
	"strings"
	"sync"

	"github.com/docker/buildx/driver"
	"github.com/docker/buildx/util/progress"
	"github.com/moby/buildkit/client"
	"github.com/moby/buildkit/util/tracing/detect"
	"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/docker.md
	features    features
	hostGateway hostGateway
}

func (d *Driver) Bootstrap(ctx context.Context, l progress.Logger) error {
	return nil
}

func (d *Driver) Info(ctx context.Context) (*driver.Info, error) {
	_, err := d.DockerAPI.ServerVersion(ctx)
	if err != nil {
		return nil, errors.Wrapf(driver.ErrNotConnecting, err.Error())
	}
	return &driver.Info{
		Status: driver.Running,
	}, nil
}

func (d *Driver) Version(ctx context.Context) (string, error) {
	v, err := d.DockerAPI.ServerVersion(ctx)
	if err != nil {
		return "", errors.Wrapf(driver.ErrNotConnecting, err.Error())
	}
	if bkversion, _ := resolveBuildKitVersion(v.Version); bkversion != "" {
		return bkversion, nil
	}
	// https://github.com/moby/moby/blob/efc7a2abc3ab6dfa7d8d5d8c1c3b99138989b0f1/builder/builder-next/worker/worker.go#L176
	return strings.TrimSuffix(v.Version, "-moby"), 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) Dial(ctx context.Context) (net.Conn, error) {
	return d.DockerAPI.DialHijack(ctx, "/grpc", "h2c", d.DialMeta)
}

func (d *Driver) Client(ctx context.Context) (*client.Client, error) {
	opts := []client.ClientOpt{
		client.WithContextDialer(func(context.Context, string) (net.Conn, error) {
			return d.Dial(ctx)
		}), client.WithSessionDialer(func(ctx context.Context, proto string, meta map[string][]string) (net.Conn, error) {
			return d.DockerAPI.DialHijack(ctx, "/session", proto, meta)
		}),
	}

	exp, _, err := detect.Exporter()
	if err != nil {
		return nil, err
	}
	if td, ok := exp.(client.TracerDelegate); ok {
		opts = append(opts, client.WithTracerDelegate(td))
	}
	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 {
	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 {
			// 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
			}
		}
		d.hostGateway.err = errors.New("host-gateway IP not found")
	})
	return d.hostGateway.ip, d.hostGateway.err
}

func (d *Driver) Factory() driver.Factory {
	return d.factory
}

func (d *Driver) IsMobyDriver() bool {
	return true
}

func (d *Driver) Config() driver.InitConfig {
	return d.InitConfig
}