-
Notifications
You must be signed in to change notification settings - Fork 4.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support Consul Connect Envoy Command on Windows (#17694)
### Description Add support for consul connect envoy command on windows. This PR fixes the comments of PR - #15114 ### Testing * Built consul.exe from this branch on windows and hosted here - [AWS S3](https://asheshvidyut-bucket.s3.ap-southeast-2.amazonaws.com/consul.zip) * Updated the [tutorial](https://developer.hashicorp.com/consul/tutorials/developer-mesh/consul-windows-workloads) and changed the `consul_url.default` value to [AWS S3](https://asheshvidyut-bucket.s3.ap-southeast-2.amazonaws.com/consul.zip) * Followed the steps in the tutorial and verified that everything is working as described. ### PR Checklist * [x] updated test coverage * [ ] external facing docs updated * [x] appropriate backport labels added * [x] not a security concern --------- Co-authored-by: Franco Bruno Lavayen <[email protected]> Co-authored-by: Jose Ignacio Lorenzo <[email protected]> Co-authored-by: Jose Ignacio Lorenzo <[email protected]> Co-authored-by: Dhia Ayachi <[email protected]>
- Loading branch information
1 parent
bcc6a9d
commit f7c5ba5
Showing
8 changed files
with
177 additions
and
54 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
```release-note:feature | ||
Windows: support consul connect envoy command on Windows | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
//go:build linux || darwin || windows | ||
// +build linux darwin windows | ||
|
||
package envoy | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"strings" | ||
) | ||
|
||
func isHotRestartOption(s string) bool { | ||
restartOpts := []string{ | ||
"--restart-epoch", | ||
"--hot-restart-version", | ||
"--drain-time-s", | ||
"--parent-shutdown-time-s", | ||
} | ||
for _, opt := range restartOpts { | ||
if s == opt { | ||
return true | ||
} | ||
if strings.HasPrefix(s, opt+"=") { | ||
return true | ||
} | ||
} | ||
return false | ||
} | ||
|
||
func hasHotRestartOption(argSets ...[]string) bool { | ||
for _, args := range argSets { | ||
for _, opt := range args { | ||
if isHotRestartOption(opt) { | ||
return true | ||
} | ||
} | ||
} | ||
return false | ||
} | ||
|
||
// execArgs returns the command and args used to execute a binary. By default it | ||
// will return a command of os.Executable with the args unmodified. This is a shim | ||
// for testing, and can be overridden to execute using 'go run' instead. | ||
var execArgs = func(args ...string) (string, []string, error) { | ||
execPath, err := os.Executable() | ||
if err != nil { | ||
return "", nil, err | ||
} | ||
|
||
if strings.HasSuffix(execPath, "/envoy.test") { | ||
return "", nil, fmt.Errorf("set execArgs to use 'go run' instead of doing a self-exec") | ||
} | ||
|
||
return execPath, args, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
//go:build windows | ||
// +build windows | ||
|
||
package envoy | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"github.com/natefinch/npipe" | ||
"os" | ||
"os/exec" | ||
"path/filepath" | ||
"time" | ||
) | ||
|
||
func makeBootstrapPipe(bootstrapJSON []byte) (string, error) { | ||
pipeFile := filepath.Join(os.TempDir(), | ||
fmt.Sprintf("envoy-%x-bootstrap.json", time.Now().UnixNano()+int64(os.Getpid()))) | ||
|
||
binary, args, err := execArgs("connect", "envoy", "pipe-bootstrap", pipeFile) | ||
if err != nil { | ||
return pipeFile, err | ||
} | ||
|
||
// Dial the named pipe | ||
pipeConn, err := npipe.Dial(pipeFile) | ||
if err != nil { | ||
return pipeFile, err | ||
} | ||
defer pipeConn.Close() | ||
|
||
// Start the command to connect to the named pipe | ||
cmd := exec.Command(binary, args...) | ||
cmd.Stdout = os.Stdout | ||
cmd.Stderr = os.Stderr | ||
cmd.Stdin = pipeConn | ||
|
||
// Start the command | ||
err = cmd.Start() | ||
if err != nil { | ||
return pipeFile, err | ||
} | ||
|
||
// Write the config | ||
n, err := pipeConn.Write(bootstrapJSON) | ||
if err != nil { | ||
return pipeFile, err | ||
} | ||
|
||
if n < len(bootstrapJSON) { | ||
return pipeFile, fmt.Errorf("failed writing boostrap to child STDIN: %s", err) | ||
} | ||
|
||
// We can't wait for the process since we need to exec into Envoy before it | ||
// will be able to complete so it will be remain as a zombie until Envoy is | ||
// killed then will be reaped by the init process (pid 0). This is all a bit | ||
// gross but the cleanest workaround I can think of for Envoy 1.10 not | ||
// supporting /dev/fd/<fd> config paths any more. So we are done and leaving | ||
// the child to run it's course without reaping it. | ||
return pipeFile, nil | ||
} | ||
|
||
func startProc(binary string, args []string) (p *os.Process, err error) { | ||
if binary, err = exec.LookPath(binary); err == nil { | ||
var procAttr os.ProcAttr | ||
procAttr.Files = []*os.File{os.Stdin, | ||
os.Stdout, os.Stderr} | ||
p, err := os.StartProcess(binary, args, &procAttr) | ||
if err == nil { | ||
return p, nil | ||
} | ||
} | ||
return nil, err | ||
} | ||
|
||
func execEnvoy(binary string, prefixArgs, suffixArgs []string, bootstrapJSON []byte) error { | ||
tempFile, err := makeBootstrapPipe(bootstrapJSON) | ||
if err != nil { | ||
os.RemoveAll(tempFile) | ||
return err | ||
} | ||
// We don't defer a cleanup since we are about to Exec into Envoy which means | ||
// defer will never fire. The child process cleans up for us in the happy | ||
// path. | ||
|
||
// We default to disabling hot restart because it makes it easier to run | ||
// multiple envoys locally for testing without them trying to share memory and | ||
// unix sockets and complain about being different IDs. But if user is | ||
// actually configuring hot-restart explicitly with the --restart-epoch option | ||
// then don't disable it! | ||
disableHotRestart := !hasHotRestartOption(prefixArgs, suffixArgs) | ||
|
||
// First argument needs to be the executable name. | ||
envoyArgs := []string{} | ||
envoyArgs = append(envoyArgs, prefixArgs...) | ||
if disableHotRestart { | ||
envoyArgs = append(envoyArgs, "--disable-hot-restart") | ||
} | ||
envoyArgs = append(envoyArgs, suffixArgs...) | ||
envoyArgs = append(envoyArgs, "--config-path", tempFile) | ||
|
||
// Exec | ||
if proc, err := startProc(binary, envoyArgs); err == nil { | ||
proc.Wait() | ||
} else if err != nil { | ||
return errors.New("Failed to exec envoy: " + err.Error()) | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters