Browse code

daemon/internal/builder-next: add executorOpts struct

The newExecutor and newExecutorGD constructors started to gain
a long list of arguments, some of which were platform-specific
and not used on other platforms.

Add a basic struct to pass options, which also allows documenting
platform-specific fields through comments, and makes it easier to
maintain platform-specific stubs.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>

Sebastiaan van Stijn authored on 2026/02/10 19:40:48
Showing 6 changed files
... ...
@@ -154,19 +154,19 @@ func newSnapshotterController(ctx context.Context, rt http.RoundTripper, opt Opt
154 154
 	wo.RegistryHosts = opt.RegistryHosts
155 155
 	wo.Labels = getLabels(opt, wo.Labels)
156 156
 
157
-	exec, err := newExecutor(
158
-		opt.Root,
159
-		opt.DefaultCgroupParent,
160
-		opt.NetworkController,
161
-		dnsConfig,
162
-		opt.Rootless,
163
-		opt.IdentityMapping,
164
-		opt.ApparmorProfile,
165
-		cdiManager,
166
-		opt.ContainerdAddress,
167
-		opt.ContainerdNamespace,
168
-		opt.HyperVIsolation,
169
-	)
157
+	exec, err := newExecutor(executorOpts{
158
+		root:                opt.Root,
159
+		networkController:   opt.NetworkController,
160
+		dnsConfig:           dnsConfig,
161
+		cdiManager:          cdiManager,
162
+		cgroupParent:        opt.DefaultCgroupParent,
163
+		apparmorProfile:     opt.ApparmorProfile,
164
+		rootless:            opt.Rootless,
165
+		identityMapping:     opt.IdentityMapping,
166
+		containerdAddr:      opt.ContainerdAddress,
167
+		containerdNamespace: opt.ContainerdNamespace,
168
+		hypervIsolation:     opt.HyperVIsolation,
169
+	})
170 170
 	if err != nil {
171 171
 		return nil, err
172 172
 	}
... ...
@@ -354,25 +354,26 @@ func newGraphDriverController(ctx context.Context, rt http.RoundTripper, opt Opt
354 354
 		return nil, err
355 355
 	}
356 356
 
357
-	dns := getDNSConfig(opt.DNSConfig)
358
-
359 357
 	cdiManager, err := getCDIManager(opt)
360 358
 	if err != nil {
361 359
 		return nil, err
362 360
 	}
363 361
 
364
-	exec, err := newExecutorGD(
365
-		root,
366
-		opt.DefaultCgroupParent,
367
-		opt.NetworkController,
368
-		dns,
369
-		opt.Rootless,
370
-		opt.IdentityMapping,
371
-		opt.ApparmorProfile,
372
-		cdiManager,
373
-		opt.ContainerdAddress,
374
-		opt.ContainerdNamespace,
375
-	)
362
+	exec, err := newExecutorGD(executorOpts{
363
+		root:              root,
364
+		networkController: opt.NetworkController,
365
+		dnsConfig:         getDNSConfig(opt.DNSConfig),
366
+		cdiManager:        cdiManager,
367
+		cgroupParent:      opt.DefaultCgroupParent,
368
+		apparmorProfile:   opt.ApparmorProfile,
369
+		rootless:          opt.Rootless,
370
+		identityMapping:   opt.IdentityMapping,
371
+
372
+		// Windows-only fields (currently not used, as newExecutorGD is not implemented on Windows)
373
+		containerdAddr:      opt.ContainerdAddress,
374
+		containerdNamespace: opt.ContainerdNamespace,
375
+		hypervIsolation:     opt.HyperVIsolation,
376
+	})
376 377
 	if err != nil {
377 378
 		return nil, err
378 379
 	}
... ...
@@ -8,24 +8,20 @@ import (
8 8
 
9 9
 	"github.com/containerd/log"
10 10
 	"github.com/moby/buildkit/executor"
11
-	"github.com/moby/buildkit/executor/oci"
12 11
 	"github.com/moby/buildkit/executor/resources"
13 12
 	"github.com/moby/buildkit/executor/runcexecutor"
14
-	"github.com/moby/buildkit/solver/llbsolver/cdidevices"
15 13
 	"github.com/moby/buildkit/solver/pb"
16 14
 	"github.com/moby/buildkit/util/network"
17 15
 	"github.com/moby/moby/v2/daemon/internal/stringid"
18
-	"github.com/moby/moby/v2/daemon/libnetwork"
19
-	"github.com/moby/sys/user"
20 16
 	"github.com/opencontainers/runtime-spec/specs-go"
21 17
 )
22 18
 
23 19
 const networkName = "bridge"
24 20
 
25
-func newExecutor(root, cgroupParent string, net *libnetwork.Controller, dnsConfig *oci.DNSConfig, rootless bool, idmap user.IdentityMapping, apparmorProfile string, cdiManager *cdidevices.Manager, _, _ string, _ bool) (executor.Executor, error) {
26
-	netRoot := filepath.Join(root, "net")
21
+func newExecutor(opts executorOpts) (executor.Executor, error) {
22
+	netRoot := filepath.Join(opts.root, "net")
27 23
 	networkProviders := map[pb.NetMode]network.Provider{
28
-		pb.NetMode_UNSET: &bridgeProvider{Controller: net, Root: netRoot},
24
+		pb.NetMode_UNSET: &bridgeProvider{Controller: opts.networkController, Root: netRoot},
29 25
 		pb.NetMode_HOST:  network.NewHostProvider(),
30 26
 		pb.NetMode_NONE:  network.NewNoneProvider(),
31 27
 	}
... ...
@@ -43,9 +39,9 @@ func newExecutor(root, cgroupParent string, net *libnetwork.Controller, dnsConfi
43 43
 
44 44
 	// Returning a non-nil but empty *IdentityMapping breaks BuildKit:
45 45
 	// https://github.com/moby/moby/pull/39444
46
-	pidmap := &idmap
47
-	if idmap.Empty() {
48
-		pidmap = nil
46
+	idmap := &opts.identityMapping
47
+	if opts.identityMapping.Empty() {
48
+		idmap = nil
49 49
 	}
50 50
 
51 51
 	rm, err := resources.NewMonitor()
... ...
@@ -53,43 +49,30 @@ func newExecutor(root, cgroupParent string, net *libnetwork.Controller, dnsConfi
53 53
 		return nil, err
54 54
 	}
55 55
 
56
-	runcCmds := []string{"runc"}
57
-
58 56
 	// TODO: FIXME: testing env var, replace with something better or remove in a major version or two
57
+	runcCmds := []string{"runc"}
59 58
 	if runcOverride := os.Getenv("DOCKER_BUILDKIT_RUNC_COMMAND"); runcOverride != "" {
60 59
 		runcCmds = []string{runcOverride}
61 60
 	}
62 61
 
63 62
 	return runcexecutor.New(runcexecutor.Opt{
64
-		Root:                filepath.Join(root, "executor"),
63
+		Root:                filepath.Join(opts.root, "executor"),
65 64
 		CommandCandidates:   runcCmds,
66
-		DefaultCgroupParent: cgroupParent,
67
-		Rootless:            rootless,
65
+		DefaultCgroupParent: opts.cgroupParent,
66
+		Rootless:            opts.rootless,
68 67
 		NoPivot:             os.Getenv("DOCKER_RAMDISK") != "",
69
-		IdentityMapping:     pidmap,
70
-		DNS:                 dnsConfig,
71
-		ApparmorProfile:     apparmorProfile,
68
+		IdentityMapping:     idmap,
69
+		DNS:                 opts.dnsConfig,
70
+		ApparmorProfile:     opts.apparmorProfile,
72 71
 		ResourceMonitor:     rm,
73
-		CDIManager:          cdiManager,
72
+		CDIManager:          opts.cdiManager,
74 73
 	}, networkProviders)
75 74
 }
76 75
 
77
-// newExecutorGD calls newExecutor() on Linux.
78
-// Created for symmetry with the non-linux platforms, esp. Windows.
79
-func newExecutorGD(root, cgroupParent string, net *libnetwork.Controller, dnsConfig *oci.DNSConfig, rootless bool, idmap user.IdentityMapping, apparmorProfile string, cdiManager *cdidevices.Manager, _, _ string) (executor.Executor, error) {
80
-	return newExecutor(
81
-		root,
82
-		cgroupParent,
83
-		net,
84
-		dnsConfig,
85
-		rootless,
86
-		idmap,
87
-		apparmorProfile,
88
-		cdiManager,
89
-		"",
90
-		"",
91
-		false,
92
-	)
76
+// newExecutorGD calls newExecutor() on Linux. It returns a stubExecutor on
77
+// other platforms.
78
+func newExecutorGD(opts executorOpts) (executor.Executor, error) {
79
+	return newExecutor(opts)
93 80
 }
94 81
 
95 82
 func (iface *lnInterface) Set(s *specs.Spec) error {
... ...
@@ -8,11 +8,7 @@ import (
8 8
 	"runtime"
9 9
 
10 10
 	"github.com/moby/buildkit/executor"
11
-	"github.com/moby/buildkit/executor/oci"
12 11
 	resourcetypes "github.com/moby/buildkit/executor/resources/types"
13
-	"github.com/moby/buildkit/solver/llbsolver/cdidevices"
14
-	"github.com/moby/moby/v2/daemon/libnetwork"
15
-	"github.com/moby/sys/user"
16 12
 )
17 13
 
18 14
 type stubExecutor struct{}
... ...
@@ -26,6 +22,6 @@ func (w *stubExecutor) Exec(ctx context.Context, id string, process executor.Pro
26 26
 }
27 27
 
28 28
 // function stub created for GraphDriver
29
-func newExecutorGD(_, _ string, _ *libnetwork.Controller, _ *oci.DNSConfig, _ bool, _ user.IdentityMapping, _ string, _ *cdidevices.Manager, _, _ string) (executor.Executor, error) {
29
+func newExecutorGD(executorOpts) (executor.Executor, error) {
30 30
 	return &stubExecutor{}, nil
31 31
 }
32 32
new file mode 100644
... ...
@@ -0,0 +1,29 @@
0
+package buildkit
1
+
2
+import (
3
+	"github.com/moby/buildkit/executor/oci"
4
+	"github.com/moby/buildkit/solver/llbsolver/cdidevices"
5
+	"github.com/moby/moby/v2/daemon/libnetwork"
6
+	"github.com/moby/sys/user"
7
+)
8
+
9
+// executorOpts holds options for constructing an executor. It contains fields
10
+// used on Linux, Windows, or both.
11
+type executorOpts struct {
12
+	// common fields
13
+	root              string
14
+	networkController *libnetwork.Controller
15
+	dnsConfig         *oci.DNSConfig
16
+	cdiManager        *cdidevices.Manager
17
+
18
+	// linux-only fields
19
+	cgroupParent    string
20
+	apparmorProfile string
21
+	rootless        bool
22
+	identityMapping user.IdentityMapping
23
+
24
+	// windows-only fields
25
+	containerdAddr      string
26
+	containerdNamespace string
27
+	hypervIsolation     bool
28
+}
... ...
@@ -4,12 +4,8 @@ package buildkit
4 4
 
5 5
 import (
6 6
 	"github.com/moby/buildkit/executor"
7
-	"github.com/moby/buildkit/executor/oci"
8
-	"github.com/moby/buildkit/solver/llbsolver/cdidevices"
9
-	"github.com/moby/moby/v2/daemon/libnetwork"
10
-	"github.com/moby/sys/user"
11 7
 )
12 8
 
13
-func newExecutor(_, _ string, _ *libnetwork.Controller, _ *oci.DNSConfig, _ bool, _ user.IdentityMapping, _ string, _ *cdidevices.Manager, _, _ string, _ bool) (executor.Executor, error) {
9
+func newExecutor(executorOpts) (executor.Executor, error) {
14 10
 	return &stubExecutor{}, nil
15 11
 }
... ...
@@ -9,51 +9,34 @@ import (
9 9
 	"github.com/containerd/log"
10 10
 	"github.com/moby/buildkit/executor"
11 11
 	"github.com/moby/buildkit/executor/containerdexecutor"
12
-	"github.com/moby/buildkit/executor/oci"
13
-	"github.com/moby/buildkit/solver/llbsolver/cdidevices"
14 12
 	"github.com/moby/buildkit/solver/pb"
15 13
 	"github.com/moby/buildkit/util/network"
16
-	"github.com/moby/moby/v2/daemon/libnetwork"
17
-	"github.com/moby/sys/user"
18 14
 	"github.com/opencontainers/runtime-spec/specs-go"
19 15
 )
20 16
 
21 17
 const networkName = "nat"
22 18
 
23
-func newExecutor(
24
-	root string,
25
-	_ string,
26
-	net *libnetwork.Controller,
27
-	dns *oci.DNSConfig,
28
-	_ bool,
29
-	_ user.IdentityMapping,
30
-	_ string,
31
-	cdiManager *cdidevices.Manager,
32
-	containerdAddr string,
33
-	containerdNamespace string,
34
-	hypervIsolation bool,
35
-) (executor.Executor, error) {
36
-	netRoot := filepath.Join(root, "net")
19
+func newExecutor(opts executorOpts) (executor.Executor, error) {
20
+	netRoot := filepath.Join(opts.root, "net")
37 21
 	np := map[pb.NetMode]network.Provider{
38
-		pb.NetMode_UNSET: &bridgeProvider{Controller: net, Root: netRoot},
22
+		pb.NetMode_UNSET: &bridgeProvider{Controller: opts.networkController, Root: netRoot},
39 23
 		pb.NetMode_NONE:  network.NewNoneProvider(),
40 24
 	}
41 25
 
42
-	opt := ctd.WithDefaultNamespace(containerdNamespace)
43
-	client, err := ctd.New(containerdAddr, opt)
26
+	opt := ctd.WithDefaultNamespace(opts.containerdNamespace)
27
+	client, err := ctd.New(opts.containerdAddr, opt)
44 28
 	if err != nil {
45 29
 		return nil, err
46 30
 	}
47 31
 
48
-	executorOpts := containerdexecutor.ExecutorOptions{
32
+	return containerdexecutor.New(containerdexecutor.ExecutorOptions{
49 33
 		Client:           client,
50
-		Root:             root,
51
-		DNSConfig:        dns,
52
-		CDIManager:       cdiManager,
34
+		Root:             opts.root,
35
+		DNSConfig:        opts.dnsConfig,
36
+		CDIManager:       opts.cdiManager,
53 37
 		NetworkProviders: np,
54
-		HyperVIsolation:  hypervIsolation,
55
-	}
56
-	return containerdexecutor.New(executorOpts), nil
38
+		HyperVIsolation:  opts.hypervIsolation,
39
+	}), nil
57 40
 }
58 41
 
59 42
 func (iface *lnInterface) Set(s *specs.Spec) error {