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  }