| // +build !windows |
| |
| package buildkit |
| |
| import ( |
| "fmt" |
| "path/filepath" |
| "sync" |
| |
| "github.com/docker/libnetwork" |
| "github.com/moby/buildkit/executor" |
| "github.com/moby/buildkit/executor/runcexecutor" |
| "github.com/moby/buildkit/identity" |
| "github.com/moby/buildkit/util/network" |
| "github.com/pkg/errors" |
| "github.com/sirupsen/logrus" |
| ) |
| |
| const networkName = "bridge" |
| |
| func init() { |
| // FIXME: https://github.com/moby/moby/issues/37676 |
| runcexecutor.DisableSubReaper() |
| } |
| |
| func newExecutor(root string, net libnetwork.NetworkController) (executor.Executor, error) { |
| return runcexecutor.New(runcexecutor.Opt{ |
| Root: filepath.Join(root, "executor"), |
| CommandCandidates: []string{"docker-runc", "runc"}, |
| }, &bridgeProvider{NetworkController: net}) |
| } |
| |
| type bridgeProvider struct { |
| libnetwork.NetworkController |
| } |
| |
| func (p *bridgeProvider) NewInterface() (network.Interface, error) { |
| n, err := p.NetworkByName(networkName) |
| if err != nil { |
| return nil, err |
| } |
| |
| iface := &lnInterface{ready: make(chan struct{})} |
| iface.Once.Do(func() { |
| go iface.init(p.NetworkController, n) |
| }) |
| |
| return iface, nil |
| } |
| |
| func (p *bridgeProvider) Release(iface network.Interface) error { |
| go func() { |
| if err := p.release(iface); err != nil { |
| logrus.Errorf("%s", err) |
| } |
| }() |
| return nil |
| } |
| |
| func (p *bridgeProvider) release(iface network.Interface) error { |
| li, ok := iface.(*lnInterface) |
| if !ok { |
| return errors.Errorf("invalid interface %T", iface) |
| } |
| err := li.sbx.Delete() |
| if err1 := li.ep.Delete(true); err1 != nil && err == nil { |
| err = err1 |
| } |
| return err |
| } |
| |
| type lnInterface struct { |
| ep libnetwork.Endpoint |
| sbx libnetwork.Sandbox |
| sync.Once |
| err error |
| ready chan struct{} |
| } |
| |
| func (iface *lnInterface) init(c libnetwork.NetworkController, n libnetwork.Network) { |
| defer close(iface.ready) |
| id := identity.NewID() |
| |
| ep, err := n.CreateEndpoint(id) |
| if err != nil { |
| iface.err = err |
| return |
| } |
| |
| sbx, err := c.NewSandbox(id) |
| if err != nil { |
| iface.err = err |
| return |
| } |
| |
| if err := ep.Join(sbx); err != nil { |
| iface.err = err |
| return |
| } |
| |
| iface.sbx = sbx |
| iface.ep = ep |
| } |
| |
| func (iface *lnInterface) Set(pid int) error { |
| <-iface.ready |
| if iface.err != nil { |
| return iface.err |
| } |
| return iface.sbx.SetKey(fmt.Sprintf("/proc/%d/ns/net", pid)) |
| } |
| |
| func (iface *lnInterface) Remove(pid int) error { |
| return nil |
| } |