@ -49,6 +49,22 @@ func hasHotRestartOption(argSets ...[]string) bool {
return false
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
}
func makeBootstrapPipe ( bootstrapJSON [ ] byte ) ( string , error ) {
func makeBootstrapPipe ( bootstrapJSON [ ] byte ) ( string , error ) {
pipeFile := filepath . Join ( os . TempDir ( ) ,
pipeFile := filepath . Join ( os . TempDir ( ) ,
fmt . Sprintf ( "envoy-%x-bootstrap.json" , time . Now ( ) . UnixNano ( ) + int64 ( os . Getpid ( ) ) ) )
fmt . Sprintf ( "envoy-%x-bootstrap.json" , time . Now ( ) . UnixNano ( ) + int64 ( os . Getpid ( ) ) ) )
@ -58,33 +74,30 @@ func makeBootstrapPipe(bootstrapJSON []byte) (string, error) {
return pipeFile , err
return pipeFile , err
}
}
// Get our own executable path.
binary , args , err := execArgs ( "connect" , "envoy" , "pipe-bootstrap" , pipeFile )
execPath , err := os . Executable ( )
if err != nil {
if err != nil {
return pipeFile , err
return pipeFile , err
}
}
if testSelfExecOverride != "" {
execPath = testSelfExecOverride
} else if strings . HasSuffix ( execPath , "/envoy.test" ) {
return pipeFile , fmt . Errorf ( "I seem to be running in a test binary without " +
"overriding the self-executable. Not doing that - it will make you sad. " +
"See testSelfExecOverride." )
}
// Exec the pipe-bootstrap internal sub-command which will write the bootstrap
// Exec the pipe-bootstrap internal sub-command which will write the bootstrap
// from STDIN to the named pipe (once Envoy opens it) and then clean up the
// from STDIN to the named pipe (once Envoy opens it) and then clean up the
// file for us.
// file for us.
cmd := exec . Command ( execPath , "connect" , "envoy" , "pipe-bootstrap" , pipeFile )
cmd := exec . Command ( binary , args ... )
cmd . Stdout = os . Stdout
cmd . Stderr = os . Stderr
stdin , err := cmd . StdinPipe ( )
stdin , err := cmd . StdinPipe ( )
if err != nil {
if err != nil {
return pipeFile , err
return pipeFile , err
}
}
err = cmd . Start ( )
if err != nil {
return pipeFile , err
}
// Write the config
// Write the config
n , err := stdin . Write ( bootstrapJSON )
n , err := stdin . Write ( bootstrapJSON )
// Close STDIN whether it was successful or not
// Close STDIN whether it was successful or not
stdin. Close ( )
_ = stdin. Close ( )
if err != nil {
if err != nil {
return pipeFile , err
return pipeFile , err
}
}
@ -92,11 +105,6 @@ func makeBootstrapPipe(bootstrapJSON []byte) (string, error) {
return pipeFile , fmt . Errorf ( "failed writing boostrap to child STDIN: %s" , err )
return pipeFile , fmt . Errorf ( "failed writing boostrap to child STDIN: %s" , err )
}
}
err = cmd . Start ( )
if err != nil {
return pipeFile , err
}
// We can't wait for the process since we need to exec into Envoy before it
// 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
// 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
// killed then will be reaped by the init process (pid 0). This is all a bit