From 64f4631d8b8568285ed0de948a702154f218d711 Mon Sep 17 00:00:00 2001 From: Marat Radchenko Date: Thu, 29 Aug 2024 18:01:51 +0300 Subject: [PATCH] Add stub implementations to make buildkitd build for Darwin Signed-off-by: Marat Radchenko --- cmd/buildkitd/main_containerd_worker.go | 3 - executor/oci/spec_darwin.go | 64 +++++++++++ snapshot/localmounter_darwin.go | 67 ++++++++++++ source/git/source_darwin.go | 7 ++ source/git/source_freebsd.go | 100 +----------------- source/git/source_unix_nolinux.go | 99 +++++++++++++++++ util/network/netproviders/network_nobridge.go | 4 +- 7 files changed, 243 insertions(+), 101 deletions(-) create mode 100644 executor/oci/spec_darwin.go create mode 100644 snapshot/localmounter_darwin.go create mode 100644 source/git/source_darwin.go create mode 100644 source/git/source_unix_nolinux.go diff --git a/cmd/buildkitd/main_containerd_worker.go b/cmd/buildkitd/main_containerd_worker.go index aae5f98db158..be9e0a575c39 100644 --- a/cmd/buildkitd/main_containerd_worker.go +++ b/cmd/buildkitd/main_containerd_worker.go @@ -1,6 +1,3 @@ -//go:build linux || windows || freebsd -// +build linux windows freebsd - package main import ( diff --git a/executor/oci/spec_darwin.go b/executor/oci/spec_darwin.go new file mode 100644 index 000000000000..fbcaff191204 --- /dev/null +++ b/executor/oci/spec_darwin.go @@ -0,0 +1,64 @@ +package oci + +import ( + "github.com/containerd/containerd/mount" + "github.com/containerd/containerd/oci" + "github.com/containerd/continuity/fs" + "github.com/docker/docker/pkg/idtools" + "github.com/moby/buildkit/solver/pb" + "github.com/opencontainers/runtime-spec/specs-go" + "github.com/pkg/errors" +) + +func withProcessArgs(args ...string) oci.SpecOpts { + return oci.WithProcessArgs(args...) +} + +func generateMountOpts(_, _ string) []oci.SpecOpts { + return nil +} + +func generateSecurityOpts(mode pb.SecurityMode, _ string, _ bool) ([]oci.SpecOpts, error) { + return nil, nil +} + +func generateProcessModeOpts(mode ProcessMode) ([]oci.SpecOpts, error) { + return nil, nil +} + +func generateIDmapOpts(idmap *idtools.IdentityMapping) ([]oci.SpecOpts, error) { + if idmap == nil { + return nil, nil + } + return nil, errors.New("no support for IdentityMapping on Darwin") +} + +func generateRlimitOpts(ulimits []*pb.Ulimit) ([]oci.SpecOpts, error) { + if len(ulimits) == 0 { + return nil, nil + } + return nil, errors.New("no support for POSIXRlimit on Darwin") +} + +// tracing is not implemented on Darwin +func getTracingSocketMount(_ string) *specs.Mount { + return nil +} + +// tracing is not implemented on Darwin +func getTracingSocket() string { + return "" +} + +func cgroupV2NamespaceSupported() bool { + return false +} + +func sub(m mount.Mount, subPath string) (mount.Mount, func() error, error) { + src, err := fs.RootPath(m.Source, subPath) + if err != nil { + return mount.Mount{}, nil, err + } + m.Source = src + return m, func() error { return nil }, nil +} diff --git a/snapshot/localmounter_darwin.go b/snapshot/localmounter_darwin.go new file mode 100644 index 000000000000..1b20e931d71c --- /dev/null +++ b/snapshot/localmounter_darwin.go @@ -0,0 +1,67 @@ +package snapshot + +import ( + "os" + + "github.com/containerd/containerd/mount" + "github.com/pkg/errors" + "golang.org/x/sys/unix" +) + +func (lm *localMounter) Mount() (string, error) { + lm.mu.Lock() + defer lm.mu.Unlock() + + if lm.mounts == nil && lm.mountable != nil { + mounts, release, err := lm.mountable.Mount() + if err != nil { + return "", err + } + lm.mounts = mounts + lm.release = release + } + + if len(lm.mounts) == 1 && lm.mounts[0].Type == "bind" { + ro := false + for _, opt := range lm.mounts[0].Options { + if opt == "ro" { + ro = true + break + } + } + if !ro { + return lm.mounts[0].Source, nil + } + } + + dir, err := os.MkdirTemp("", "buildkit-mount") + if err != nil { + return "", errors.Wrap(err, "failed to create temp dir") + } + + if err := mount.All(lm.mounts, dir); err != nil { + os.RemoveAll(dir) + return "", errors.Wrapf(err, "failed to mount %s: %+v", dir, lm.mounts) + } + lm.target = dir + return dir, nil +} + +func (lm *localMounter) Unmount() error { + lm.mu.Lock() + defer lm.mu.Unlock() + + if lm.target != "" { + if err := mount.UnmountRecursive(lm.target, unix.MNT_FORCE); err != nil { + return err + } + os.RemoveAll(lm.target) + lm.target = "" + } + + if lm.release != nil { + return lm.release() + } + + return nil +} diff --git a/source/git/source_darwin.go b/source/git/source_darwin.go new file mode 100644 index 000000000000..7b3e3053ec49 --- /dev/null +++ b/source/git/source_darwin.go @@ -0,0 +1,7 @@ +package git + +import "golang.org/x/sys/unix" + +var reexecSysProcAttr = unix.SysProcAttr{ + Setpgid: true, +} diff --git a/source/git/source_freebsd.go b/source/git/source_freebsd.go index 963946d5a306..7164820b46fb 100644 --- a/source/git/source_freebsd.go +++ b/source/git/source_freebsd.go @@ -1,100 +1,8 @@ package git -import ( - "context" - "os" - "os/exec" - "os/signal" - "syscall" - "time" +import "golang.org/x/sys/unix" - "github.com/docker/docker/pkg/reexec" - "golang.org/x/sys/unix" -) - -const ( - gitCmd = "umask-git" -) - -func init() { - reexec.Register(gitCmd, gitMain) -} - -func gitMain() { - // Need standard user umask for git process. - unix.Umask(0022) - - // Reexec git command - cmd := exec.Command(os.Args[1], os.Args[2:]...) //nolint:gosec // reexec - cmd.SysProcAttr = &unix.SysProcAttr{ - Setpgid: true, - Pdeathsig: unix.SIGTERM, - } - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - cmd.Stdin = os.Stdin - - // Forward all signals - sigc := make(chan os.Signal, 1) - done := make(chan struct{}) - signal.Notify(sigc) - go func() { - for { - select { - case sig := <-sigc: - if cmd.Process == nil { - continue - } - switch sig { - case unix.SIGINT, unix.SIGTERM, unix.SIGKILL: - _ = unix.Kill(-cmd.Process.Pid, sig.(unix.Signal)) - default: - _ = cmd.Process.Signal(sig) - } - case <-done: - return - } - } - }() - - err := cmd.Run() - close(done) - if err != nil { - if exiterr, ok := err.(*exec.ExitError); ok { - switch status := exiterr.Sys().(type) { - case unix.WaitStatus: - os.Exit(status.ExitStatus()) - case syscall.WaitStatus: - os.Exit(status.ExitStatus()) - } - } - os.Exit(1) - } - os.Exit(0) -} - -func runWithStandardUmask(ctx context.Context, cmd *exec.Cmd) error { - cmd.Path = reexec.Self() - cmd.Args = append([]string{gitCmd}, cmd.Args...) - if err := cmd.Start(); err != nil { - return err - } - waitDone := make(chan struct{}) - go func() { - select { - case <-ctx.Done(): - _ = unix.Kill(-cmd.Process.Pid, unix.SIGTERM) - go func() { - select { - case <-waitDone: - case <-time.After(10 * time.Second): - _ = unix.Kill(-cmd.Process.Pid, unix.SIGKILL) - } - }() - case <-waitDone: - } - }() - err := cmd.Wait() - close(waitDone) - return err +var reexecSysProcAttr = unix.SysProcAttr{ + Setpgid: true, + Pdeathsig: unix.SIGTERM, } diff --git a/source/git/source_unix_nolinux.go b/source/git/source_unix_nolinux.go new file mode 100644 index 000000000000..3995c10f124c --- /dev/null +++ b/source/git/source_unix_nolinux.go @@ -0,0 +1,99 @@ +//go:build unix && !linux + +package git + +import ( + "context" + "os" + "os/exec" + "os/signal" + "syscall" + "time" + + "github.com/docker/docker/pkg/reexec" + "golang.org/x/sys/unix" +) + +const ( + gitCmd = "umask-git" +) + +func init() { + reexec.Register(gitCmd, gitMain) +} + +func gitMain() { + // Need standard user umask for git process. + unix.Umask(0022) + + // Reexec git command + cmd := exec.Command(os.Args[1], os.Args[2:]...) //nolint:gosec // reexec + cmd.SysProcAttr = &reexecSysProcAttr + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.Stdin = os.Stdin + + // Forward all signals + sigc := make(chan os.Signal, 1) + done := make(chan struct{}) + signal.Notify(sigc) + go func() { + for { + select { + case sig := <-sigc: + if cmd.Process == nil { + continue + } + switch sig { + case unix.SIGINT, unix.SIGTERM, unix.SIGKILL: + _ = unix.Kill(-cmd.Process.Pid, sig.(unix.Signal)) + default: + _ = cmd.Process.Signal(sig) + } + case <-done: + return + } + } + }() + + err := cmd.Run() + close(done) + if err != nil { + if exiterr, ok := err.(*exec.ExitError); ok { + switch status := exiterr.Sys().(type) { + case unix.WaitStatus: + os.Exit(status.ExitStatus()) + case syscall.WaitStatus: + os.Exit(status.ExitStatus()) + } + } + os.Exit(1) + } + os.Exit(0) +} + +func runWithStandardUmask(ctx context.Context, cmd *exec.Cmd) error { + cmd.Path = reexec.Self() + cmd.Args = append([]string{gitCmd}, cmd.Args...) + if err := cmd.Start(); err != nil { + return err + } + waitDone := make(chan struct{}) + go func() { + select { + case <-ctx.Done(): + _ = unix.Kill(-cmd.Process.Pid, unix.SIGTERM) + go func() { + select { + case <-waitDone: + case <-time.After(10 * time.Second): + _ = unix.Kill(-cmd.Process.Pid, unix.SIGKILL) + } + }() + case <-waitDone: + } + }() + err := cmd.Wait() + close(waitDone) + return err +} diff --git a/util/network/netproviders/network_nobridge.go b/util/network/netproviders/network_nobridge.go index 1edde9b38d90..748545ccd1d6 100644 --- a/util/network/netproviders/network_nobridge.go +++ b/util/network/netproviders/network_nobridge.go @@ -1,5 +1,5 @@ -//go:build freebsd || windows -// +build freebsd windows +//go:build !linux +// +build !linux package netproviders