The current executor is only tested on Linux, so let's be honest about
that. Stubbing this correctly helps avoid incorrectly trying to call
into Linux-only code in e.g. libnetwork.
Signed-off-by: Bjorn Neergaard <bjorn.neergaard@docker.com>
| 1 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,163 @@ |
| 0 |
+package buildkit |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "context" |
|
| 4 |
+ "os" |
|
| 5 |
+ "path/filepath" |
|
| 6 |
+ "strconv" |
|
| 7 |
+ "sync" |
|
| 8 |
+ |
|
| 9 |
+ "github.com/containerd/containerd/log" |
|
| 10 |
+ "github.com/docker/docker/daemon/config" |
|
| 11 |
+ "github.com/docker/docker/libnetwork" |
|
| 12 |
+ "github.com/docker/docker/pkg/idtools" |
|
| 13 |
+ "github.com/docker/docker/pkg/stringid" |
|
| 14 |
+ "github.com/moby/buildkit/executor" |
|
| 15 |
+ "github.com/moby/buildkit/executor/oci" |
|
| 16 |
+ "github.com/moby/buildkit/executor/runcexecutor" |
|
| 17 |
+ "github.com/moby/buildkit/identity" |
|
| 18 |
+ "github.com/moby/buildkit/solver/pb" |
|
| 19 |
+ "github.com/moby/buildkit/util/network" |
|
| 20 |
+ specs "github.com/opencontainers/runtime-spec/specs-go" |
|
| 21 |
+) |
|
| 22 |
+ |
|
| 23 |
+const networkName = "bridge" |
|
| 24 |
+ |
|
| 25 |
+func newExecutor(root, cgroupParent string, net *libnetwork.Controller, dnsConfig *oci.DNSConfig, rootless bool, idmap idtools.IdentityMapping, apparmorProfile string) (executor.Executor, error) {
|
|
| 26 |
+ netRoot := filepath.Join(root, "net") |
|
| 27 |
+ networkProviders := map[pb.NetMode]network.Provider{
|
|
| 28 |
+ pb.NetMode_UNSET: &bridgeProvider{Controller: net, Root: netRoot},
|
|
| 29 |
+ pb.NetMode_HOST: network.NewHostProvider(), |
|
| 30 |
+ pb.NetMode_NONE: network.NewNoneProvider(), |
|
| 31 |
+ } |
|
| 32 |
+ |
|
| 33 |
+ // make sure net state directory is cleared from previous state |
|
| 34 |
+ fis, err := os.ReadDir(netRoot) |
|
| 35 |
+ if err == nil {
|
|
| 36 |
+ for _, fi := range fis {
|
|
| 37 |
+ fp := filepath.Join(netRoot, fi.Name()) |
|
| 38 |
+ if err := os.RemoveAll(fp); err != nil {
|
|
| 39 |
+ log.G(context.TODO()).WithError(err).Errorf("failed to delete old network state: %v", fp)
|
|
| 40 |
+ } |
|
| 41 |
+ } |
|
| 42 |
+ } |
|
| 43 |
+ |
|
| 44 |
+ // Returning a non-nil but empty *IdentityMapping breaks BuildKit: |
|
| 45 |
+ // https://github.com/moby/moby/pull/39444 |
|
| 46 |
+ pidmap := &idmap |
|
| 47 |
+ if idmap.Empty() {
|
|
| 48 |
+ pidmap = nil |
|
| 49 |
+ } |
|
| 50 |
+ |
|
| 51 |
+ return runcexecutor.New(runcexecutor.Opt{
|
|
| 52 |
+ Root: filepath.Join(root, "executor"), |
|
| 53 |
+ CommandCandidates: []string{"runc"},
|
|
| 54 |
+ DefaultCgroupParent: cgroupParent, |
|
| 55 |
+ Rootless: rootless, |
|
| 56 |
+ NoPivot: os.Getenv("DOCKER_RAMDISK") != "",
|
|
| 57 |
+ IdentityMapping: pidmap, |
|
| 58 |
+ DNS: dnsConfig, |
|
| 59 |
+ ApparmorProfile: apparmorProfile, |
|
| 60 |
+ }, networkProviders) |
|
| 61 |
+} |
|
| 62 |
+ |
|
| 63 |
+type bridgeProvider struct {
|
|
| 64 |
+ *libnetwork.Controller |
|
| 65 |
+ Root string |
|
| 66 |
+} |
|
| 67 |
+ |
|
| 68 |
+func (p *bridgeProvider) New(ctx context.Context, hostname string) (network.Namespace, error) {
|
|
| 69 |
+ n, err := p.NetworkByName(networkName) |
|
| 70 |
+ if err != nil {
|
|
| 71 |
+ return nil, err |
|
| 72 |
+ } |
|
| 73 |
+ |
|
| 74 |
+ iface := &lnInterface{ready: make(chan struct{}), provider: p}
|
|
| 75 |
+ iface.Once.Do(func() {
|
|
| 76 |
+ go iface.init(p.Controller, n) |
|
| 77 |
+ }) |
|
| 78 |
+ |
|
| 79 |
+ return iface, nil |
|
| 80 |
+} |
|
| 81 |
+ |
|
| 82 |
+func (p *bridgeProvider) Close() error {
|
|
| 83 |
+ return nil |
|
| 84 |
+} |
|
| 85 |
+ |
|
| 86 |
+type lnInterface struct {
|
|
| 87 |
+ ep *libnetwork.Endpoint |
|
| 88 |
+ sbx *libnetwork.Sandbox |
|
| 89 |
+ sync.Once |
|
| 90 |
+ err error |
|
| 91 |
+ ready chan struct{}
|
|
| 92 |
+ provider *bridgeProvider |
|
| 93 |
+} |
|
| 94 |
+ |
|
| 95 |
+func (iface *lnInterface) init(c *libnetwork.Controller, n *libnetwork.Network) {
|
|
| 96 |
+ defer close(iface.ready) |
|
| 97 |
+ id := identity.NewID() |
|
| 98 |
+ |
|
| 99 |
+ ep, err := n.CreateEndpoint(id, libnetwork.CreateOptionDisableResolution()) |
|
| 100 |
+ if err != nil {
|
|
| 101 |
+ iface.err = err |
|
| 102 |
+ return |
|
| 103 |
+ } |
|
| 104 |
+ |
|
| 105 |
+ sbx, err := c.NewSandbox(id, libnetwork.OptionUseExternalKey(), libnetwork.OptionHostsPath(filepath.Join(iface.provider.Root, id, "hosts")), |
|
| 106 |
+ libnetwork.OptionResolvConfPath(filepath.Join(iface.provider.Root, id, "resolv.conf"))) |
|
| 107 |
+ if err != nil {
|
|
| 108 |
+ iface.err = err |
|
| 109 |
+ return |
|
| 110 |
+ } |
|
| 111 |
+ |
|
| 112 |
+ if err := ep.Join(sbx); err != nil {
|
|
| 113 |
+ iface.err = err |
|
| 114 |
+ return |
|
| 115 |
+ } |
|
| 116 |
+ |
|
| 117 |
+ iface.sbx = sbx |
|
| 118 |
+ iface.ep = ep |
|
| 119 |
+} |
|
| 120 |
+ |
|
| 121 |
+func (iface *lnInterface) Set(s *specs.Spec) error {
|
|
| 122 |
+ <-iface.ready |
|
| 123 |
+ if iface.err != nil {
|
|
| 124 |
+ log.G(context.TODO()).WithError(iface.err).Error("failed to set networking spec")
|
|
| 125 |
+ return iface.err |
|
| 126 |
+ } |
|
| 127 |
+ shortNetCtlrID := stringid.TruncateID(iface.provider.Controller.ID()) |
|
| 128 |
+ // attach netns to bridge within the container namespace, using reexec in a prestart hook |
|
| 129 |
+ s.Hooks = &specs.Hooks{
|
|
| 130 |
+ Prestart: []specs.Hook{{
|
|
| 131 |
+ Path: filepath.Join("/proc", strconv.Itoa(os.Getpid()), "exe"),
|
|
| 132 |
+ Args: []string{"libnetwork-setkey", "-exec-root=" + iface.provider.Config().ExecRoot, iface.sbx.ContainerID(), shortNetCtlrID},
|
|
| 133 |
+ }}, |
|
| 134 |
+ } |
|
| 135 |
+ return nil |
|
| 136 |
+} |
|
| 137 |
+ |
|
| 138 |
+func (iface *lnInterface) Close() error {
|
|
| 139 |
+ <-iface.ready |
|
| 140 |
+ if iface.sbx != nil {
|
|
| 141 |
+ go func() {
|
|
| 142 |
+ if err := iface.sbx.Delete(); err != nil {
|
|
| 143 |
+ log.G(context.TODO()).WithError(err).Errorf("failed to delete builder network sandbox")
|
|
| 144 |
+ } |
|
| 145 |
+ if err := os.RemoveAll(filepath.Join(iface.provider.Root, iface.sbx.ContainerID())); err != nil {
|
|
| 146 |
+ log.G(context.TODO()).WithError(err).Errorf("failed to delete builder sandbox directory")
|
|
| 147 |
+ } |
|
| 148 |
+ }() |
|
| 149 |
+ } |
|
| 150 |
+ return iface.err |
|
| 151 |
+} |
|
| 152 |
+ |
|
| 153 |
+func getDNSConfig(cfg config.DNSConfig) *oci.DNSConfig {
|
|
| 154 |
+ if cfg.DNS != nil || cfg.DNSSearch != nil || cfg.DNSOptions != nil {
|
|
| 155 |
+ return &oci.DNSConfig{
|
|
| 156 |
+ Nameservers: cfg.DNS, |
|
| 157 |
+ SearchDomains: cfg.DNSSearch, |
|
| 158 |
+ Options: cfg.DNSOptions, |
|
| 159 |
+ } |
|
| 160 |
+ } |
|
| 161 |
+ return nil |
|
| 162 |
+} |
| 0 | 163 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,33 @@ |
| 0 |
+//go:build !linux |
|
| 1 |
+ |
|
| 2 |
+package buildkit |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "context" |
|
| 6 |
+ "errors" |
|
| 7 |
+ "runtime" |
|
| 8 |
+ |
|
| 9 |
+ "github.com/docker/docker/daemon/config" |
|
| 10 |
+ "github.com/docker/docker/libnetwork" |
|
| 11 |
+ "github.com/docker/docker/pkg/idtools" |
|
| 12 |
+ "github.com/moby/buildkit/executor" |
|
| 13 |
+ "github.com/moby/buildkit/executor/oci" |
|
| 14 |
+) |
|
| 15 |
+ |
|
| 16 |
+func newExecutor(_, _ string, _ *libnetwork.Controller, _ *oci.DNSConfig, _ bool, _ idtools.IdentityMapping, _ string) (executor.Executor, error) {
|
|
| 17 |
+ return &stubExecutor{}, nil
|
|
| 18 |
+} |
|
| 19 |
+ |
|
| 20 |
+type stubExecutor struct{}
|
|
| 21 |
+ |
|
| 22 |
+func (w *stubExecutor) Run(ctx context.Context, id string, root executor.Mount, mounts []executor.Mount, process executor.ProcessInfo, started chan<- struct{}) (err error) {
|
|
| 23 |
+ return errors.New("buildkit executor not implemented for "+runtime.GOOS)
|
|
| 24 |
+} |
|
| 25 |
+ |
|
| 26 |
+func (w *stubExecutor) Exec(ctx context.Context, id string, process executor.ProcessInfo) error {
|
|
| 27 |
+ return errors.New("buildkit executor not implemented for "+runtime.GOOS)
|
|
| 28 |
+} |
|
| 29 |
+ |
|
| 30 |
+func getDNSConfig(config.DNSConfig) *oci.DNSConfig {
|
|
| 31 |
+ return nil |
|
| 32 |
+} |
| 0 | 33 |
deleted file mode 100644 |
| ... | ... |
@@ -1,165 +0,0 @@ |
| 1 |
-//go:build !windows |
|
| 2 |
- |
|
| 3 |
-package buildkit |
|
| 4 |
- |
|
| 5 |
-import ( |
|
| 6 |
- "context" |
|
| 7 |
- "os" |
|
| 8 |
- "path/filepath" |
|
| 9 |
- "strconv" |
|
| 10 |
- "sync" |
|
| 11 |
- |
|
| 12 |
- "github.com/containerd/containerd/log" |
|
| 13 |
- "github.com/docker/docker/daemon/config" |
|
| 14 |
- "github.com/docker/docker/libnetwork" |
|
| 15 |
- "github.com/docker/docker/pkg/idtools" |
|
| 16 |
- "github.com/docker/docker/pkg/stringid" |
|
| 17 |
- "github.com/moby/buildkit/executor" |
|
| 18 |
- "github.com/moby/buildkit/executor/oci" |
|
| 19 |
- "github.com/moby/buildkit/executor/runcexecutor" |
|
| 20 |
- "github.com/moby/buildkit/identity" |
|
| 21 |
- "github.com/moby/buildkit/solver/pb" |
|
| 22 |
- "github.com/moby/buildkit/util/network" |
|
| 23 |
- specs "github.com/opencontainers/runtime-spec/specs-go" |
|
| 24 |
-) |
|
| 25 |
- |
|
| 26 |
-const networkName = "bridge" |
|
| 27 |
- |
|
| 28 |
-func newExecutor(root, cgroupParent string, net *libnetwork.Controller, dnsConfig *oci.DNSConfig, rootless bool, idmap idtools.IdentityMapping, apparmorProfile string) (executor.Executor, error) {
|
|
| 29 |
- netRoot := filepath.Join(root, "net") |
|
| 30 |
- networkProviders := map[pb.NetMode]network.Provider{
|
|
| 31 |
- pb.NetMode_UNSET: &bridgeProvider{Controller: net, Root: netRoot},
|
|
| 32 |
- pb.NetMode_HOST: network.NewHostProvider(), |
|
| 33 |
- pb.NetMode_NONE: network.NewNoneProvider(), |
|
| 34 |
- } |
|
| 35 |
- |
|
| 36 |
- // make sure net state directory is cleared from previous state |
|
| 37 |
- fis, err := os.ReadDir(netRoot) |
|
| 38 |
- if err == nil {
|
|
| 39 |
- for _, fi := range fis {
|
|
| 40 |
- fp := filepath.Join(netRoot, fi.Name()) |
|
| 41 |
- if err := os.RemoveAll(fp); err != nil {
|
|
| 42 |
- log.G(context.TODO()).WithError(err).Errorf("failed to delete old network state: %v", fp)
|
|
| 43 |
- } |
|
| 44 |
- } |
|
| 45 |
- } |
|
| 46 |
- |
|
| 47 |
- // Returning a non-nil but empty *IdentityMapping breaks BuildKit: |
|
| 48 |
- // https://github.com/moby/moby/pull/39444 |
|
| 49 |
- pidmap := &idmap |
|
| 50 |
- if idmap.Empty() {
|
|
| 51 |
- pidmap = nil |
|
| 52 |
- } |
|
| 53 |
- |
|
| 54 |
- return runcexecutor.New(runcexecutor.Opt{
|
|
| 55 |
- Root: filepath.Join(root, "executor"), |
|
| 56 |
- CommandCandidates: []string{"runc"},
|
|
| 57 |
- DefaultCgroupParent: cgroupParent, |
|
| 58 |
- Rootless: rootless, |
|
| 59 |
- NoPivot: os.Getenv("DOCKER_RAMDISK") != "",
|
|
| 60 |
- IdentityMapping: pidmap, |
|
| 61 |
- DNS: dnsConfig, |
|
| 62 |
- ApparmorProfile: apparmorProfile, |
|
| 63 |
- }, networkProviders) |
|
| 64 |
-} |
|
| 65 |
- |
|
| 66 |
-type bridgeProvider struct {
|
|
| 67 |
- *libnetwork.Controller |
|
| 68 |
- Root string |
|
| 69 |
-} |
|
| 70 |
- |
|
| 71 |
-func (p *bridgeProvider) New(ctx context.Context, hostname string) (network.Namespace, error) {
|
|
| 72 |
- n, err := p.NetworkByName(networkName) |
|
| 73 |
- if err != nil {
|
|
| 74 |
- return nil, err |
|
| 75 |
- } |
|
| 76 |
- |
|
| 77 |
- iface := &lnInterface{ready: make(chan struct{}), provider: p}
|
|
| 78 |
- iface.Once.Do(func() {
|
|
| 79 |
- go iface.init(p.Controller, n) |
|
| 80 |
- }) |
|
| 81 |
- |
|
| 82 |
- return iface, nil |
|
| 83 |
-} |
|
| 84 |
- |
|
| 85 |
-func (p *bridgeProvider) Close() error {
|
|
| 86 |
- return nil |
|
| 87 |
-} |
|
| 88 |
- |
|
| 89 |
-type lnInterface struct {
|
|
| 90 |
- ep *libnetwork.Endpoint |
|
| 91 |
- sbx *libnetwork.Sandbox |
|
| 92 |
- sync.Once |
|
| 93 |
- err error |
|
| 94 |
- ready chan struct{}
|
|
| 95 |
- provider *bridgeProvider |
|
| 96 |
-} |
|
| 97 |
- |
|
| 98 |
-func (iface *lnInterface) init(c *libnetwork.Controller, n *libnetwork.Network) {
|
|
| 99 |
- defer close(iface.ready) |
|
| 100 |
- id := identity.NewID() |
|
| 101 |
- |
|
| 102 |
- ep, err := n.CreateEndpoint(id, libnetwork.CreateOptionDisableResolution()) |
|
| 103 |
- if err != nil {
|
|
| 104 |
- iface.err = err |
|
| 105 |
- return |
|
| 106 |
- } |
|
| 107 |
- |
|
| 108 |
- sbx, err := c.NewSandbox(id, libnetwork.OptionUseExternalKey(), libnetwork.OptionHostsPath(filepath.Join(iface.provider.Root, id, "hosts")), |
|
| 109 |
- libnetwork.OptionResolvConfPath(filepath.Join(iface.provider.Root, id, "resolv.conf"))) |
|
| 110 |
- if err != nil {
|
|
| 111 |
- iface.err = err |
|
| 112 |
- return |
|
| 113 |
- } |
|
| 114 |
- |
|
| 115 |
- if err := ep.Join(sbx); err != nil {
|
|
| 116 |
- iface.err = err |
|
| 117 |
- return |
|
| 118 |
- } |
|
| 119 |
- |
|
| 120 |
- iface.sbx = sbx |
|
| 121 |
- iface.ep = ep |
|
| 122 |
-} |
|
| 123 |
- |
|
| 124 |
-func (iface *lnInterface) Set(s *specs.Spec) error {
|
|
| 125 |
- <-iface.ready |
|
| 126 |
- if iface.err != nil {
|
|
| 127 |
- log.G(context.TODO()).WithError(iface.err).Error("failed to set networking spec")
|
|
| 128 |
- return iface.err |
|
| 129 |
- } |
|
| 130 |
- shortNetCtlrID := stringid.TruncateID(iface.provider.Controller.ID()) |
|
| 131 |
- // attach netns to bridge within the container namespace, using reexec in a prestart hook |
|
| 132 |
- s.Hooks = &specs.Hooks{
|
|
| 133 |
- Prestart: []specs.Hook{{
|
|
| 134 |
- Path: filepath.Join("/proc", strconv.Itoa(os.Getpid()), "exe"),
|
|
| 135 |
- Args: []string{"libnetwork-setkey", "-exec-root=" + iface.provider.Config().ExecRoot, iface.sbx.ContainerID(), shortNetCtlrID},
|
|
| 136 |
- }}, |
|
| 137 |
- } |
|
| 138 |
- return nil |
|
| 139 |
-} |
|
| 140 |
- |
|
| 141 |
-func (iface *lnInterface) Close() error {
|
|
| 142 |
- <-iface.ready |
|
| 143 |
- if iface.sbx != nil {
|
|
| 144 |
- go func() {
|
|
| 145 |
- if err := iface.sbx.Delete(); err != nil {
|
|
| 146 |
- log.G(context.TODO()).WithError(err).Errorf("failed to delete builder network sandbox")
|
|
| 147 |
- } |
|
| 148 |
- if err := os.RemoveAll(filepath.Join(iface.provider.Root, iface.sbx.ContainerID())); err != nil {
|
|
| 149 |
- log.G(context.TODO()).WithError(err).Errorf("failed to delete builder sandbox directory")
|
|
| 150 |
- } |
|
| 151 |
- }() |
|
| 152 |
- } |
|
| 153 |
- return iface.err |
|
| 154 |
-} |
|
| 155 |
- |
|
| 156 |
-func getDNSConfig(cfg config.DNSConfig) *oci.DNSConfig {
|
|
| 157 |
- if cfg.DNS != nil || cfg.DNSSearch != nil || cfg.DNSOptions != nil {
|
|
| 158 |
- return &oci.DNSConfig{
|
|
| 159 |
- Nameservers: cfg.DNS, |
|
| 160 |
- SearchDomains: cfg.DNSSearch, |
|
| 161 |
- Options: cfg.DNSOptions, |
|
| 162 |
- } |
|
| 163 |
- } |
|
| 164 |
- return nil |
|
| 165 |
-} |
| 166 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,30 +0,0 @@ |
| 1 |
-package buildkit |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "context" |
|
| 5 |
- "errors" |
|
| 6 |
- |
|
| 7 |
- "github.com/docker/docker/daemon/config" |
|
| 8 |
- "github.com/docker/docker/libnetwork" |
|
| 9 |
- "github.com/docker/docker/pkg/idtools" |
|
| 10 |
- "github.com/moby/buildkit/executor" |
|
| 11 |
- "github.com/moby/buildkit/executor/oci" |
|
| 12 |
-) |
|
| 13 |
- |
|
| 14 |
-func newExecutor(_, _ string, _ *libnetwork.Controller, _ *oci.DNSConfig, _ bool, _ idtools.IdentityMapping, _ string) (executor.Executor, error) {
|
|
| 15 |
- return &winExecutor{}, nil
|
|
| 16 |
-} |
|
| 17 |
- |
|
| 18 |
-type winExecutor struct{}
|
|
| 19 |
- |
|
| 20 |
-func (w *winExecutor) Run(ctx context.Context, id string, root executor.Mount, mounts []executor.Mount, process executor.ProcessInfo, started chan<- struct{}) (err error) {
|
|
| 21 |
- return errors.New("buildkit executor not implemented for windows")
|
|
| 22 |
-} |
|
| 23 |
- |
|
| 24 |
-func (w *winExecutor) Exec(ctx context.Context, id string, process executor.ProcessInfo) error {
|
|
| 25 |
- return errors.New("buildkit executor not implemented for windows")
|
|
| 26 |
-} |
|
| 27 |
- |
|
| 28 |
-func getDNSConfig(config.DNSConfig) *oci.DNSConfig {
|
|
| 29 |
- return nil |
|
| 30 |
-} |