From ecf070a027d7130c89b8a3ef939199775df8a75b Mon Sep 17 00:00:00 2001 From: Tonis Tiigi Date: Fri, 23 Oct 2020 11:17:41 -0700 Subject: [PATCH] exec: use platform specific default path Signed-off-by: Tonis Tiigi --- client/llb/exec.go | 8 +++++++- examples/buildkit0/buildkit.go | 2 +- examples/buildkit1/buildkit.go | 2 +- examples/buildkit2/buildkit.go | 2 +- examples/buildkit3/buildkit.go | 2 +- examples/nested-llb/main.go | 2 +- exporter/containerimage/writer.go | 2 +- frontend/dockerfile/dockerfile2llb/convert.go | 6 +++++- frontend/dockerfile/dockerfile2llb/image.go | 2 +- frontend/gateway/container.go | 2 +- solver/llbsolver/ops/exec.go | 6 +++++- util/system/path.go | 18 ++++++++++++++++++ util/system/path_unix.go | 5 ----- util/system/path_windows.go | 4 ---- 14 files changed, 43 insertions(+), 20 deletions(-) create mode 100644 util/system/path.go diff --git a/client/llb/exec.go b/client/llb/exec.go index c1c82aa756da..decc0d7407f7 100644 --- a/client/llb/exec.go +++ b/client/llb/exec.go @@ -153,7 +153,13 @@ func (e *ExecOp) Marshal(ctx context.Context, c *Constraints) (digest.Digest, [] } if c.Caps != nil { if err := c.Caps.Supports(pb.CapExecMetaSetsDefaultPath); err != nil { - env = env.SetDefault("PATH", system.DefaultPathEnv) + os := "linux" + if c.Platform != nil { + os = c.Platform.OS + } else if e.constraints.Platform != nil { + os = e.constraints.Platform.OS + } + env = env.SetDefault("PATH", system.DefaultPathEnv(os)) } else { addCap(&e.constraints, pb.CapExecMetaSetsDefaultPath) } diff --git a/examples/buildkit0/buildkit.go b/examples/buildkit0/buildkit.go index 66fb750a5a97..dd094d15ec59 100644 --- a/examples/buildkit0/buildkit.go +++ b/examples/buildkit0/buildkit.go @@ -35,7 +35,7 @@ func main() { func goBuildBase() llb.State { goAlpine := llb.Image("docker.io/library/golang:1.13-alpine") return goAlpine. - AddEnv("PATH", "/usr/local/go/bin:"+system.DefaultPathEnv). + AddEnv("PATH", "/usr/local/go/bin:"+system.DefaultPathEnvUnix). AddEnv("GOPATH", "/go"). Run(llb.Shlex("apk add --no-cache g++ linux-headers")). Run(llb.Shlex("apk add --no-cache git libseccomp-dev make")).Root() diff --git a/examples/buildkit1/buildkit.go b/examples/buildkit1/buildkit.go index c6dad534816c..ea3e558e1809 100644 --- a/examples/buildkit1/buildkit.go +++ b/examples/buildkit1/buildkit.go @@ -35,7 +35,7 @@ func main() { func goBuildBase() llb.State { goAlpine := llb.Image("docker.io/library/golang:1.13-alpine") return goAlpine. - AddEnv("PATH", "/usr/local/go/bin:"+system.DefaultPathEnv). + AddEnv("PATH", "/usr/local/go/bin:"+system.DefaultPathEnvUnix). AddEnv("GOPATH", "/go"). Run(llb.Shlex("apk add --no-cache g++ linux-headers")). Run(llb.Shlex("apk add --no-cache git libseccomp-dev make")).Root() diff --git a/examples/buildkit2/buildkit.go b/examples/buildkit2/buildkit.go index 4bd55bef93a1..9e82d3adee0a 100644 --- a/examples/buildkit2/buildkit.go +++ b/examples/buildkit2/buildkit.go @@ -35,7 +35,7 @@ func main() { func goBuildBase() llb.State { goAlpine := llb.Image("docker.io/library/golang:1.13-alpine") return goAlpine. - AddEnv("PATH", "/usr/local/go/bin:"+system.DefaultPathEnv). + AddEnv("PATH", "/usr/local/go/bin:"+system.DefaultPathEnvUnix). AddEnv("GOPATH", "/go"). Run(llb.Shlex("apk add --no-cache g++ linux-headers libseccomp-dev make")).Root() } diff --git a/examples/buildkit3/buildkit.go b/examples/buildkit3/buildkit.go index 4ddcf59ef829..633891483d19 100644 --- a/examples/buildkit3/buildkit.go +++ b/examples/buildkit3/buildkit.go @@ -36,7 +36,7 @@ func main() { func goBuildBase() llb.State { goAlpine := llb.Image("docker.io/library/golang:1.13-alpine") return goAlpine. - AddEnv("PATH", "/usr/local/go/bin:"+system.DefaultPathEnv). + AddEnv("PATH", "/usr/local/go/bin:"+system.DefaultPathEnvUnix). AddEnv("GOPATH", "/go"). Run(llb.Shlex("apk add --no-cache g++ linux-headers libseccomp-dev make")).Root() } diff --git a/examples/nested-llb/main.go b/examples/nested-llb/main.go index 1c15934091eb..d53aa57cb43f 100644 --- a/examples/nested-llb/main.go +++ b/examples/nested-llb/main.go @@ -34,7 +34,7 @@ func main() { func goBuildBase() llb.State { goAlpine := llb.Image("docker.io/library/golang:1.13-alpine") return goAlpine. - AddEnv("PATH", "/usr/local/go/bin:"+system.DefaultPathEnv). + AddEnv("PATH", "/usr/local/go/bin:"+system.DefaultPathEnvUnix). AddEnv("GOPATH", "/go"). Run(llb.Shlex("apk add --no-cache g++ linux-headers make")).Root() } diff --git a/exporter/containerimage/writer.go b/exporter/containerimage/writer.go index a0858801c1b2..bfee4d15801a 100644 --- a/exporter/containerimage/writer.go +++ b/exporter/containerimage/writer.go @@ -315,7 +315,7 @@ func emptyImageConfig() ([]byte, error) { } img.RootFS.Type = "layers" img.Config.WorkingDir = "/" - img.Config.Env = []string{"PATH=" + system.DefaultPathEnv} + img.Config.Env = []string{"PATH=" + system.DefaultPathEnv(pl.OS)} dt, err := json.Marshal(img) return dt, errors.Wrap(err, "failed to create empty image config") } diff --git a/frontend/dockerfile/dockerfile2llb/convert.go b/frontend/dockerfile/dockerfile2llb/convert.go index ca5d9c5b49bc..213c671eaff1 100644 --- a/frontend/dockerfile/dockerfile2llb/convert.go +++ b/frontend/dockerfile/dockerfile2llb/convert.go @@ -317,7 +317,11 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State, // make sure that PATH is always set if _, ok := shell.BuildEnvs(d.image.Config.Env)["PATH"]; !ok { - d.image.Config.Env = append(d.image.Config.Env, "PATH="+system.DefaultPathEnv) + var os string + if d.platform != nil { + os = d.platform.OS + } + d.image.Config.Env = append(d.image.Config.Env, "PATH="+system.DefaultPathEnv(os)) } // initialize base metadata from image conf diff --git a/frontend/dockerfile/dockerfile2llb/image.go b/frontend/dockerfile/dockerfile2llb/image.go index 55e9add23363..6eb4cf6e7ae0 100644 --- a/frontend/dockerfile/dockerfile2llb/image.go +++ b/frontend/dockerfile/dockerfile2llb/image.go @@ -74,6 +74,6 @@ func emptyImage(platform specs.Platform) Image { } img.RootFS.Type = "layers" img.Config.WorkingDir = "/" - img.Config.Env = []string{"PATH=" + system.DefaultPathEnv} + img.Config.Env = []string{"PATH=" + system.DefaultPathEnv(platform.OS)} return img } diff --git a/frontend/gateway/container.go b/frontend/gateway/container.go index 9981124c40f4..99a3640ddd53 100644 --- a/frontend/gateway/container.go +++ b/frontend/gateway/container.go @@ -227,7 +227,7 @@ func (gwCtr *gatewayContainer) Start(ctx context.Context, req client.StartReques if procInfo.Meta.Cwd == "" { procInfo.Meta.Cwd = "/" } - procInfo.Meta.Env = addDefaultEnvvar(procInfo.Meta.Env, "PATH", utilsystem.DefaultPathEnv) + procInfo.Meta.Env = addDefaultEnvvar(procInfo.Meta.Env, "PATH", utilsystem.DefaultPathEnvUnix) // support windows? if req.Tty { procInfo.Meta.Env = addDefaultEnvvar(procInfo.Meta.Env, "TERM", "xterm") } diff --git a/solver/llbsolver/ops/exec.go b/solver/llbsolver/ops/exec.go index e5aeeea12b8f..5516376fd8ae 100644 --- a/solver/llbsolver/ops/exec.go +++ b/solver/llbsolver/ops/exec.go @@ -380,7 +380,11 @@ func (e *execOp) Exec(ctx context.Context, g session.Group, inputs []solver.Resu if e.op.Meta.ProxyEnv != nil { meta.Env = append(meta.Env, proxyEnvList(e.op.Meta.ProxyEnv)...) } - meta.Env = addDefaultEnvvar(meta.Env, "PATH", utilsystem.DefaultPathEnv) + var currentOS string + if e.platform != nil { + currentOS = e.platform.OS + } + meta.Env = addDefaultEnvvar(meta.Env, "PATH", utilsystem.DefaultPathEnv(currentOS)) stdout, stderr := logs.NewLogStreams(ctx, os.Getenv("BUILDKIT_DEBUG_EXEC_OUTPUT") == "1") defer stdout.Close() diff --git a/util/system/path.go b/util/system/path.go new file mode 100644 index 000000000000..f6dc70dc8dd5 --- /dev/null +++ b/util/system/path.go @@ -0,0 +1,18 @@ +package system + +// DefaultPathEnvUnix is unix style list of directories to search for +// executables. Each directory is separated from the next by a colon +// ':' character . +const DefaultPathEnvUnix = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + +// DefaultPathEnvWindows is windows style list of directories to search for +// executables. Each directory is separated from the next by a colon +// ';' character . +const DefaultPathEnvWindows = "c:\\Windows\\System32;c:\\Windows" + +func DefaultPathEnv(os string) string { + if os == "windows" { + return DefaultPathEnvWindows + } + return DefaultPathEnvUnix +} diff --git a/util/system/path_unix.go b/util/system/path_unix.go index c607c4db09f2..f3762e69d36a 100644 --- a/util/system/path_unix.go +++ b/util/system/path_unix.go @@ -2,11 +2,6 @@ package system -// DefaultPathEnv is unix style list of directories to search for -// executables. Each directory is separated from the next by a colon -// ':' character . -const DefaultPathEnv = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" - // CheckSystemDriveAndRemoveDriveLetter verifies that a path, if it includes a drive letter, // is the system drive. This is a no-op on Linux. func CheckSystemDriveAndRemoveDriveLetter(path string) (string, error) { diff --git a/util/system/path_windows.go b/util/system/path_windows.go index cbfe2c1576ce..3fc47449484e 100644 --- a/util/system/path_windows.go +++ b/util/system/path_windows.go @@ -8,10 +8,6 @@ import ( "strings" ) -// DefaultPathEnv is deliberately empty on Windows as the default path will be set by -// the container. Docker has no context of what the default path should be. -const DefaultPathEnv = "" - // CheckSystemDriveAndRemoveDriveLetter verifies and manipulates a Windows path. // This is used, for example, when validating a user provided path in docker cp. // If a drive letter is supplied, it must be the system drive. The drive letter