Merge branch 'fix-executable-locator' into 'main'

Fix location of executables in PATH

See merge request nvidia/container-toolkit/container-toolkit!148
This commit is contained in:
Evan Lezar 2022-05-12 05:26:22 +00:00
commit 1eb0e3c8b3
4 changed files with 84 additions and 38 deletions

View File

@ -6,21 +6,20 @@ import (
"log" "log"
"os" "os"
"os/exec" "os/exec"
"path"
"path/filepath" "path/filepath"
"runtime" "runtime"
"runtime/debug" "runtime/debug"
"strconv" "strconv"
"strings" "strings"
"syscall" "syscall"
"github.com/NVIDIA/nvidia-container-toolkit/internal/lookup"
) )
var ( var (
debugflag = flag.Bool("debug", false, "enable debug output") debugflag = flag.Bool("debug", false, "enable debug output")
forceflag = flag.Bool("force", false, "force execution of prestart hook in experimental mode") forceflag = flag.Bool("force", false, "force execution of prestart hook in experimental mode")
configflag = flag.String("config", "", "configuration file") configflag = flag.String("config", "", "configuration file")
defaultPATH = []string{"/usr/local/sbin", "/usr/local/bin", "/usr/sbin", "/usr/bin", "/sbin", "/bin"}
) )
func exit() { func exit() {
@ -36,28 +35,16 @@ func exit() {
os.Exit(0) os.Exit(0)
} }
func getPATH(config CLIConfig) string {
dirs := filepath.SplitList(os.Getenv("PATH"))
// directories from the hook environment have higher precedence
dirs = append(dirs, defaultPATH...)
if config.Root != nil {
rootDirs := []string{}
for _, dir := range dirs {
rootDirs = append(rootDirs, path.Join(*config.Root, dir))
}
// directories with the root prefix have higher precedence
dirs = append(rootDirs, dirs...)
}
return strings.Join(dirs, ":")
}
func getCLIPath(config CLIConfig) string { func getCLIPath(config CLIConfig) string {
if config.Path != nil { if config.Path != nil {
return *config.Path return *config.Path
} }
if err := os.Setenv("PATH", getPATH(config)); err != nil { var root string
if config.Root != nil {
root = *config.Root
}
if err := os.Setenv("PATH", lookup.GetPath(root)); err != nil {
log.Panicln("couldn't set PATH variable:", err) log.Panicln("couldn't set PATH variable:", err)
} }

View File

@ -25,24 +25,13 @@ import (
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )
const (
envPath = "PATH"
)
var defaultPaths = []string{"/usr/local/sbin", "/usr/local/bin", "/usr/sbin", "/usr/bin", "/sbin", "/bin"}
type executable struct { type executable struct {
file file
} }
// NewExecutableLocator creates a locator to fine executable files in the path. A logger can also be specified. // NewExecutableLocator creates a locator to fine executable files in the path. A logger can also be specified.
func NewExecutableLocator(logger *log.Logger, root string) Locator { func NewExecutableLocator(logger *log.Logger, root string) Locator {
pathEnv := os.Getenv(envPath) paths := GetPaths(root)
paths := filepath.SplitList(pathEnv)
if root != "" {
paths = append(paths, defaultPaths...)
}
var prefixes []string var prefixes []string
for _, dir := range paths { for _, dir := range paths {

69
internal/lookup/path.go Normal file
View File

@ -0,0 +1,69 @@
/**
# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
**/
package lookup
import (
"os"
"path"
"path/filepath"
"strings"
)
const (
envPath = "PATH"
)
var (
defaultPATH = []string{"/usr/local/sbin", "/usr/local/bin", "/usr/sbin", "/usr/bin", "/sbin", "/bin"}
)
// GetPaths returns a list of paths for a specified root. These are constructed from the
// PATH environment variable, a default path list, and the supplied root.
func GetPaths(root string) []string {
dirs := filepath.SplitList(os.Getenv(envPath))
inDirs := make(map[string]bool)
for _, d := range dirs {
inDirs[d] = true
}
// directories from the environment have higher precedence
for _, d := range defaultPATH {
if inDirs[d] {
// We don't add paths that are already included
continue
}
dirs = append(dirs, d)
}
if root != "" && root != "/" {
rootDirs := []string{}
for _, dir := range dirs {
rootDirs = append(rootDirs, path.Join(root, dir))
}
// directories with the root prefix have higher precedence
dirs = append(rootDirs, dirs...)
}
return dirs
}
// GetPath returns a colon-separated path value that can be used to set the PATH
// environment variable
func GetPath(root string) string {
return strings.Join(GetPaths(root), ":")
}

View File

@ -18,8 +18,8 @@ package oci
import ( import (
"fmt" "fmt"
"os/exec"
"github.com/NVIDIA/nvidia-container-toolkit/internal/lookup"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )
@ -43,14 +43,15 @@ func findRuntime(logger *log.Logger, candidates []string) (string, error) {
return "", fmt.Errorf("at least one runtime candidate must be specified") return "", fmt.Errorf("at least one runtime candidate must be specified")
} }
locator := lookup.NewExecutableLocator(logger, "/")
for _, candidate := range candidates { for _, candidate := range candidates {
logger.Debugf("Looking for runtime binary '%v'", candidate) logger.Debugf("Looking for runtime binary '%v'", candidate)
runcPath, err := exec.LookPath(candidate) targets, err := locator.Locate(candidate)
if err == nil { if err == nil && len(targets) > 0 {
logger.Debugf("Found runtime binary '%v'", runcPath) logger.Debugf("Found runtime binary '%v'", targets)
return runcPath, nil return targets[0], nil
} }
logger.Debugf("Runtime binary '%v' not found: %v", candidate, err) logger.Debugf("Runtime binary '%v' not found: %v (targets=%v)", candidate, err, targets)
} }
return "", fmt.Errorf("no runtime binary found from candidate list: %v", candidates) return "", fmt.Errorf("no runtime binary found from candidate list: %v", candidates)