76 lines
1.7 KiB
Go
76 lines
1.7 KiB
Go
//go:build windows
|
|
|
|
package bootstrap
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"strings"
|
|
)
|
|
|
|
// ExitCode maps err to a process exit status, preserving the status of a
|
|
// finished child process.
|
|
func ExitCode(err error) int {
|
|
if err == nil {
|
|
return 0
|
|
}
|
|
|
|
var exitError *exec.ExitError
|
|
if errors.As(err, &exitError) {
|
|
return exitError.ExitCode()
|
|
}
|
|
|
|
return 1
|
|
}
|
|
|
|
// ExitOnError logs err and terminates the process with a matching exit
|
|
// status. A nil error is ignored.
|
|
func ExitOnError(err error) {
|
|
if err == nil {
|
|
return
|
|
}
|
|
|
|
LogError("**** %v", err)
|
|
os.Exit(ExitCode(err))
|
|
}
|
|
|
|
// Command decides what the container should execute: no arguments start the
|
|
// service binary, arguments beginning with a dash are treated as its flags,
|
|
// anything else is a user-supplied command.
|
|
func Command(args []string, binary string) []string {
|
|
if len(args) == 0 {
|
|
return []string{binary}
|
|
}
|
|
if strings.HasPrefix(args[0], "-") {
|
|
return append([]string{binary}, args...)
|
|
}
|
|
return args
|
|
}
|
|
|
|
// Execute hands control over to args with the given environment.
|
|
func Execute(args []string, env Environment) error {
|
|
if err := Exec(args, env); err != nil {
|
|
return fmt.Errorf("execute %s: %w", args[0], err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// RunService implements the common entrypoint flow: when the container is
|
|
// about to start the service binary (the image default), prepare is called
|
|
// first; custom user commands are executed untouched.
|
|
func RunService(binary string, prepare func(Environment) error) error {
|
|
env := NewEnvironment(os.Environ())
|
|
args := Command(os.Args[1:], binary)
|
|
|
|
if args[0] == binary {
|
|
if err := prepare(env); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return Execute(args, env)
|
|
}
|