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