2018-05-15 18:21:08 -04:00
|
|
|
// +build !windows
|
|
|
|
|
|
|
|
package buildkit
|
|
|
|
|
|
|
|
import (
|
2018-08-21 22:37:32 -04:00
|
|
|
"os"
|
2018-05-15 18:21:08 -04:00
|
|
|
"path/filepath"
|
2018-08-21 22:37:32 -04:00
|
|
|
"strconv"
|
2018-08-02 17:24:34 -04:00
|
|
|
"sync"
|
2018-05-15 18:21:08 -04:00
|
|
|
|
2018-08-02 17:24:34 -04:00
|
|
|
"github.com/docker/libnetwork"
|
2018-05-15 18:21:08 -04:00
|
|
|
"github.com/moby/buildkit/executor"
|
|
|
|
"github.com/moby/buildkit/executor/runcexecutor"
|
2018-08-02 17:24:34 -04:00
|
|
|
"github.com/moby/buildkit/identity"
|
2018-08-21 22:37:32 -04:00
|
|
|
"github.com/moby/buildkit/solver/pb"
|
2018-08-02 17:24:34 -04:00
|
|
|
"github.com/moby/buildkit/util/network"
|
2018-08-21 22:37:32 -04:00
|
|
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
2018-11-29 01:55:39 -05:00
|
|
|
"github.com/sirupsen/logrus"
|
2018-05-15 18:21:08 -04:00
|
|
|
)
|
|
|
|
|
2018-08-02 17:24:34 -04:00
|
|
|
const networkName = "bridge"
|
|
|
|
|
2019-02-28 03:12:55 -05:00
|
|
|
func newExecutor(root, cgroupParent string, net libnetwork.NetworkController, rootless bool) (executor.Executor, error) {
|
2018-08-21 22:37:32 -04:00
|
|
|
networkProviders := map[pb.NetMode]network.Provider{
|
2019-02-28 03:12:55 -05:00
|
|
|
pb.NetMode_UNSET: &bridgeProvider{NetworkController: net, Root: filepath.Join(root, "net")},
|
2018-08-21 22:37:32 -04:00
|
|
|
pb.NetMode_HOST: network.NewHostProvider(),
|
|
|
|
pb.NetMode_NONE: network.NewNoneProvider(),
|
|
|
|
}
|
2018-05-15 18:21:08 -04:00
|
|
|
return runcexecutor.New(runcexecutor.Opt{
|
2018-08-14 21:40:28 -04:00
|
|
|
Root: filepath.Join(root, "executor"),
|
2018-09-21 18:58:34 -04:00
|
|
|
CommandCandidates: []string{"runc"},
|
2018-08-14 21:40:28 -04:00
|
|
|
DefaultCgroupParent: cgroupParent,
|
2019-02-28 03:12:55 -05:00
|
|
|
Rootless: rootless,
|
2018-08-21 22:37:32 -04:00
|
|
|
}, networkProviders)
|
2018-08-02 17:24:34 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
type bridgeProvider struct {
|
|
|
|
libnetwork.NetworkController
|
2019-02-28 03:12:55 -05:00
|
|
|
Root string
|
2018-08-02 17:24:34 -04:00
|
|
|
}
|
|
|
|
|
2018-08-21 22:37:32 -04:00
|
|
|
func (p *bridgeProvider) New() (network.Namespace, error) {
|
2018-08-02 17:24:34 -04:00
|
|
|
n, err := p.NetworkByName(networkName)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2018-08-21 22:37:32 -04:00
|
|
|
iface := &lnInterface{ready: make(chan struct{}), provider: p}
|
2018-08-02 17:24:34 -04:00
|
|
|
iface.Once.Do(func() {
|
|
|
|
go iface.init(p.NetworkController, n)
|
2018-05-15 18:21:08 -04:00
|
|
|
})
|
2018-08-02 17:24:34 -04:00
|
|
|
|
|
|
|
return iface, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type lnInterface struct {
|
|
|
|
ep libnetwork.Endpoint
|
|
|
|
sbx libnetwork.Sandbox
|
|
|
|
sync.Once
|
2018-08-21 22:37:32 -04:00
|
|
|
err error
|
|
|
|
ready chan struct{}
|
|
|
|
provider *bridgeProvider
|
2018-08-02 17:24:34 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func (iface *lnInterface) init(c libnetwork.NetworkController, n libnetwork.Network) {
|
|
|
|
defer close(iface.ready)
|
|
|
|
id := identity.NewID()
|
|
|
|
|
2018-11-29 00:28:16 -05:00
|
|
|
ep, err := n.CreateEndpoint(id, libnetwork.CreateOptionDisableResolution())
|
2018-08-02 17:24:34 -04:00
|
|
|
if err != nil {
|
|
|
|
iface.err = err
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-02-28 03:12:55 -05:00
|
|
|
sbx, err := c.NewSandbox(id, libnetwork.OptionUseExternalKey(), libnetwork.OptionHostsPath(filepath.Join(iface.provider.Root, id, "hosts")),
|
|
|
|
libnetwork.OptionResolvConfPath(filepath.Join(iface.provider.Root, id, "resolv.conf")))
|
2018-08-02 17:24:34 -04:00
|
|
|
if err != nil {
|
|
|
|
iface.err = err
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := ep.Join(sbx); err != nil {
|
|
|
|
iface.err = err
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
iface.sbx = sbx
|
|
|
|
iface.ep = ep
|
|
|
|
}
|
|
|
|
|
2018-08-21 22:37:32 -04:00
|
|
|
func (iface *lnInterface) Set(s *specs.Spec) {
|
2018-08-02 17:24:34 -04:00
|
|
|
<-iface.ready
|
|
|
|
if iface.err != nil {
|
2019-02-28 03:12:55 -05:00
|
|
|
logrus.WithError(iface.err).Error("failed to set networking spec")
|
2018-08-21 22:37:32 -04:00
|
|
|
return
|
|
|
|
}
|
|
|
|
// attach netns to bridge within the container namespace, using reexec in a prestart hook
|
|
|
|
s.Hooks = &specs.Hooks{
|
|
|
|
Prestart: []specs.Hook{{
|
|
|
|
Path: filepath.Join("/proc", strconv.Itoa(os.Getpid()), "exe"),
|
2019-02-28 03:12:55 -05:00
|
|
|
Args: []string{"libnetwork-setkey", "-exec-root=" + iface.provider.Config().Daemon.ExecRoot, iface.sbx.ContainerID(), iface.provider.NetworkController.ID()},
|
2018-08-21 22:37:32 -04:00
|
|
|
}},
|
2018-08-02 17:24:34 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-21 22:37:32 -04:00
|
|
|
func (iface *lnInterface) Close() error {
|
|
|
|
<-iface.ready
|
2019-02-28 03:12:55 -05:00
|
|
|
if iface.sbx != nil {
|
|
|
|
go func() {
|
|
|
|
if err := iface.sbx.Delete(); err != nil {
|
|
|
|
logrus.Errorf("failed to delete builder network sandbox: %v", err)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
2018-11-29 01:55:39 -05:00
|
|
|
return iface.err
|
2018-05-15 18:21:08 -04:00
|
|
|
}
|