diff --git a/pkg/cmd/cmd.go b/pkg/cmd/cmd.go index 9dba3ce1..5cdfcb66 100644 --- a/pkg/cmd/cmd.go +++ b/pkg/cmd/cmd.go @@ -21,6 +21,7 @@ import ( "net/http" "os" "os/exec" + "path/filepath" "runtime" "strings" "syscall" @@ -173,21 +174,37 @@ func NewDefaultPluginHandler(validPrefixes []string) *DefaultPluginHandler { func (h *DefaultPluginHandler) Lookup(filename string) (string, bool) { for _, prefix := range h.ValidPrefixes { path, err := exec.LookPath(fmt.Sprintf("%s-%s", prefix, filename)) - if err != nil || len(path) == 0 { + if shouldSkipOnLookPathErr(err) || len(path) == 0 { continue } return path, true } - return "", false } +func Command(name string, arg ...string) *exec.Cmd { + cmd := &exec.Cmd{ + Path: name, + Args: append([]string{name}, arg...), + } + if filepath.Base(name) == name { + lp, err := exec.LookPath(name) + if lp != "" && !shouldSkipOnLookPathErr(err) { + // Update cmd.Path even if err is non-nil. + // If err is ErrDot (especially on Windows), lp may include a resolved + // extension (like .exe or .bat) that should be preserved. + cmd.Path = lp + } + } + return cmd +} + // Execute implements PluginHandler func (h *DefaultPluginHandler) Execute(executablePath string, cmdArgs, environment []string) error { // Windows does not support exec syscall. if runtime.GOOS == "windows" { - cmd := exec.Command(executablePath, cmdArgs...) + cmd := Command(executablePath, cmdArgs...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr cmd.Stdin = os.Stdin diff --git a/pkg/cmd/skiplookerr_go118.go b/pkg/cmd/skiplookerr_go118.go new file mode 100644 index 00000000..acde1312 --- /dev/null +++ b/pkg/cmd/skiplookerr_go118.go @@ -0,0 +1,24 @@ +//go:build !go1.19 +// +build !go1.19 + +/* +Copyright 2022 The Kubernetes Authors. + +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 cmd + +func shouldSkipOnLookPathErr(err error) bool { + return err != nil +} diff --git a/pkg/cmd/skiplookerr_go119.go b/pkg/cmd/skiplookerr_go119.go new file mode 100644 index 00000000..f24c5646 --- /dev/null +++ b/pkg/cmd/skiplookerr_go119.go @@ -0,0 +1,29 @@ +//go:build go1.19 +// +build go1.19 + +/* +Copyright 2022 The Kubernetes Authors. + +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 cmd + +import ( + "errors" + "os/exec" +) + +func shouldSkipOnLookPathErr(err error) bool { + return err != nil && !errors.Is(err, exec.ErrDot) +}