From 8b4b33ff1fd7e6ab3f3d16ede596c4cbdc2ed61b Mon Sep 17 00:00:00 2001 From: "Han Verstraete (OpenFaaS Ltd)" Date: Fri, 26 Jan 2024 12:36:18 +0100 Subject: [PATCH] Fix execution of plugins on Windows - syscall.Exec is not supported on Windows systems. Use the os/exec package instead. - On windows the plugin executables should have the .exe filename extension in order to execute them. Signed-off-by: Han Verstraete (OpenFaaS Ltd) --- commands/faas.go | 39 +++++++++++++++++++++++++++++++-------- commands/plugin_get.go | 11 +++++++++++ 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/commands/faas.go b/commands/faas.go index 259d8589..709a811b 100644 --- a/commands/faas.go +++ b/commands/faas.go @@ -4,9 +4,11 @@ package commands import ( + "errors" "fmt" "log" "os" + "os/exec" "path" "runtime" "strings" @@ -88,21 +90,42 @@ func Execute(customArgs []string) { } if cmd1 != nil && len(args1) > 0 { - found := "" for _, plugin := range plugins { - if path.Base(plugin) == args1[0] { + pluginName := args1[0] + if runtime.GOOS == "windows" { + pluginName = fmt.Sprintf("%s.exe", args1[0]) + } + + if path.Base(plugin) == pluginName { found = plugin } } if len(found) > 0 { - - // if we have found the plugin then sysexec it by replacing current process. - if err := syscall.Exec(found, append([]string{found}, os.Args[2:]...), os.Environ()); err != nil { - fmt.Fprintf(os.Stderr, "Error from plugin: %v", err) - os.Exit(127) + // If we have found the plugin then sysexec it by replacing the current process. + // On Windows we use the os/exec package to run the plugins since replacing the current + // process with syscall.exec is not supported. + if runtime.GOOS == "windows" { + cmd := exec.Command(found, os.Args[2:]...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + if err := cmd.Run(); err != nil { + var exitErr *exec.ExitError + if errors.As(err, &exitErr) { + os.Exit(exitErr.ExitCode()) + } else { + fmt.Println("Error from plugin", err) + os.Exit(127) + } + } + return + } else { + if err := syscall.Exec(found, append([]string{found}, os.Args[2:]...), os.Environ()); err != nil { + fmt.Fprintf(os.Stderr, "Error from plugin: %v", err) + os.Exit(127) + } + return } - return } } diff --git a/commands/plugin_get.go b/commands/plugin_get.go index 6dc6158d..6cdbf2cb 100644 --- a/commands/plugin_get.go +++ b/commands/plugin_get.go @@ -132,6 +132,17 @@ func runPluginGetCmd(cmd *cobra.Command, args []string) error { if err := archive.Untar(tarFile, pluginDir, gzipped, true); err != nil { return fmt.Errorf("failed to untar %s: %w", tmpTar, err) } + + // Add the .exe filename extension to the plugin executable on windows. + // If the .exe extension is missing the plugin will not execute. + if runtime.GOOS == "windows" { + pluginPath := path.Join(pluginDir, pluginName) + err := os.Rename(pluginPath, fmt.Sprintf("%s.exe", pluginPath)) + if err != nil { + return fmt.Errorf("failed to move plugin %w", err) + } + } + fmt.Printf("Downloaded in (%ds)\n\nUsage:\n faas-cli %s\n", int(time.Since(st).Seconds()), pluginName) return nil }