blob: 8ca1f85de055f6eb9e036279ebdfa18bacc69e57 [file] [log] [blame]
// +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
}