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