consul/command/connect/envoy/exec_windows.go

113 lines
3.1 KiB
Go
Raw Normal View History

[COMPLIANCE] License changes (#18443) * Adding explicit MPL license for sub-package This directory and its subdirectories (packages) contain files licensed with the MPLv2 `LICENSE` file in this directory and are intentionally licensed separately from the BSL `LICENSE` file at the root of this repository. * Adding explicit MPL license for sub-package This directory and its subdirectories (packages) contain files licensed with the MPLv2 `LICENSE` file in this directory and are intentionally licensed separately from the BSL `LICENSE` file at the root of this repository. * Updating the license from MPL to Business Source License Going forward, this project will be licensed under the Business Source License v1.1. Please see our blog post for more details at <Blog URL>, FAQ at www.hashicorp.com/licensing-faq, and details of the license at www.hashicorp.com/bsl. * add missing license headers * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 --------- Co-authored-by: hashicorp-copywrite[bot] <110428419+hashicorp-copywrite[bot]@users.noreply.github.com>
2023-08-11 13:12:13 +00:00
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
//go:build windows && !fips
// +build windows,!fips
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
}