Skip to content

Commit a3e72b5

Browse files
weltekialexellis
authored andcommitted
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) <[email protected]>
1 parent 2f9258b commit a3e72b5

File tree

2 files changed

+42
-8
lines changed

2 files changed

+42
-8
lines changed

commands/faas.go

+31-8
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
package commands
55

66
import (
7+
"errors"
78
"fmt"
89
"log"
910
"os"
11+
"os/exec"
1012
"path"
1113
"runtime"
1214
"strings"
@@ -88,21 +90,42 @@ func Execute(customArgs []string) {
8890
}
8991

9092
if cmd1 != nil && len(args1) > 0 {
91-
9293
found := ""
9394
for _, plugin := range plugins {
94-
if path.Base(plugin) == args1[0] {
95+
pluginName := args1[0]
96+
if runtime.GOOS == "windows" {
97+
pluginName = fmt.Sprintf("%s.exe", args1[0])
98+
}
99+
100+
if path.Base(plugin) == pluginName {
95101
found = plugin
96102
}
97103
}
98104
if len(found) > 0 {
99-
100-
// if we have found the plugin then sysexec it by replacing current process.
101-
if err := syscall.Exec(found, append([]string{found}, os.Args[2:]...), os.Environ()); err != nil {
102-
fmt.Fprintf(os.Stderr, "Error from plugin: %v", err)
103-
os.Exit(127)
105+
// If we have found the plugin then sysexec it by replacing the current process.
106+
// On Windows we use the os/exec package to run the plugins since replacing the current
107+
// process with syscall.exec is not supported.
108+
if runtime.GOOS == "windows" {
109+
cmd := exec.Command(found, os.Args[2:]...)
110+
cmd.Stdout = os.Stdout
111+
cmd.Stderr = os.Stderr
112+
if err := cmd.Run(); err != nil {
113+
var exitErr *exec.ExitError
114+
if errors.As(err, &exitErr) {
115+
os.Exit(exitErr.ExitCode())
116+
} else {
117+
fmt.Println("Error from plugin", err)
118+
os.Exit(127)
119+
}
120+
}
121+
return
122+
} else {
123+
if err := syscall.Exec(found, append([]string{found}, os.Args[2:]...), os.Environ()); err != nil {
124+
fmt.Fprintf(os.Stderr, "Error from plugin: %v", err)
125+
os.Exit(127)
126+
}
127+
return
104128
}
105-
return
106129
}
107130
}
108131

commands/plugin_get.go

+11
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,17 @@ func runPluginGetCmd(cmd *cobra.Command, args []string) error {
132132
if err := archive.Untar(tarFile, pluginDir, gzipped, true); err != nil {
133133
return fmt.Errorf("failed to untar %s: %w", tmpTar, err)
134134
}
135+
136+
// Add the .exe filename extension to the plugin executable on windows.
137+
// If the .exe extension is missing the plugin will not execute.
138+
if runtime.GOOS == "windows" {
139+
pluginPath := path.Join(pluginDir, pluginName)
140+
err := os.Rename(pluginPath, fmt.Sprintf("%s.exe", pluginPath))
141+
if err != nil {
142+
return fmt.Errorf("failed to move plugin %w", err)
143+
}
144+
}
145+
135146
fmt.Printf("Downloaded in (%ds)\n\nUsage:\n faas-cli %s\n", int(time.Since(st).Seconds()), pluginName)
136147
return nil
137148
}

0 commit comments

Comments
 (0)