diff --git a/pkg/invoke/find.go b/pkg/invoke/find.go index 3b037907..e815404c 100644 --- a/pkg/invoke/find.go +++ b/pkg/invoke/find.go @@ -30,18 +30,14 @@ func FindInPath(plugin string, paths []string) (string, error) { return "", fmt.Errorf("no paths provided") } - var fullpath string for _, path := range paths { - full := filepath.Join(path, plugin) - if fi, err := os.Stat(full); err == nil && fi.Mode().IsRegular() { - fullpath = full - break + for _, fe := range ExecutableFileExtensions { + fullpath := filepath.Join(path, plugin) + fe + if fi, err := os.Stat(fullpath); err == nil && fi.Mode().IsRegular() { + return fullpath, nil + } } } - if fullpath == "" { - return "", fmt.Errorf("failed to find plugin %q in path %s", plugin, paths) - } - - return fullpath, nil + return "", fmt.Errorf("failed to find plugin %q in path %s", plugin, paths) } diff --git a/pkg/invoke/find_test.go b/pkg/invoke/find_test.go index be4cc2dd..58543131 100644 --- a/pkg/invoke/find_test.go +++ b/pkg/invoke/find_test.go @@ -17,7 +17,9 @@ package invoke_test import ( "fmt" "io/ioutil" + "os" "path/filepath" + "strings" "github.com/containernetworking/cni/pkg/invoke" . "github.com/onsi/ginkgo" @@ -26,10 +28,12 @@ import ( var _ = Describe("FindInPath", func() { var ( - multiplePaths []string - pluginName string - pluginDir string - anotherTempDir string + multiplePaths []string + pluginName string + plugin2NameWithExt string + plugin2NameWithoutExt string + pluginDir string + anotherTempDir string ) BeforeEach(func() { @@ -37,11 +41,24 @@ var _ = Describe("FindInPath", func() { Expect(err).NotTo(HaveOccurred()) plugin, err := ioutil.TempFile(tempDir, "a-cni-plugin") + Expect(err).NotTo(HaveOccurred()) + + plugin2Name := "a-plugin-with-extension" + invoke.ExecutableFileExtensions[0] + plugin2, err := os.Create(filepath.Join(tempDir, plugin2Name)) + Expect(err).NotTo(HaveOccurred()) anotherTempDir, err = ioutil.TempDir("", "nothing-here") + Expect(err).NotTo(HaveOccurred()) multiplePaths = []string{anotherTempDir, tempDir} pluginDir, pluginName = filepath.Split(plugin.Name()) + _, plugin2NameWithExt = filepath.Split(plugin2.Name()) + plugin2NameWithoutExt = strings.Split(plugin2NameWithExt, ".")[0] + }) + + AfterEach(func() { + os.RemoveAll(pluginDir) + os.RemoveAll(anotherTempDir) }) Context("when multiple paths are provided", func() { @@ -52,6 +69,14 @@ var _ = Describe("FindInPath", func() { }) }) + Context("when a plugin name without its file name extension is provided", func() { + It("returns the path to the plugin, including its extension", func() { + pluginPath, err := invoke.FindInPath(plugin2NameWithoutExt, multiplePaths) + Expect(err).NotTo(HaveOccurred()) + Expect(pluginPath).To(Equal(filepath.Join(pluginDir, plugin2NameWithExt))) + }) + }) + Context("when an error occurs", func() { Context("when no paths are provided", func() { It("returns an error noting no paths were provided", func() { diff --git a/pkg/invoke/os_unix.go b/pkg/invoke/os_unix.go new file mode 100644 index 00000000..bab5737a --- /dev/null +++ b/pkg/invoke/os_unix.go @@ -0,0 +1,20 @@ +// Copyright 2016 CNI 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. + +// +build darwin dragonfly freebsd linux netbsd opensbd solaris + +package invoke + +// Valid file extensions for plugin executables. +var ExecutableFileExtensions = []string{""} diff --git a/pkg/invoke/os_windows.go b/pkg/invoke/os_windows.go new file mode 100644 index 00000000..7665125b --- /dev/null +++ b/pkg/invoke/os_windows.go @@ -0,0 +1,18 @@ +// Copyright 2016 CNI 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 invoke + +// Valid file extensions for plugin executables. +var ExecutableFileExtensions = []string{".exe", ""}