diff --git a/client/driver/exec.go b/client/driver/exec.go index 8ee6b9269..5273f1d7f 100644 --- a/client/driver/exec.go +++ b/client/driver/exec.go @@ -12,7 +12,7 @@ import ( "github.com/hashicorp/go-plugin" "github.com/hashicorp/nomad/client/allocdir" "github.com/hashicorp/nomad/client/config" - "github.com/hashicorp/nomad/client/driver/plugins" + "github.com/hashicorp/nomad/client/driver/executor" cstructs "github.com/hashicorp/nomad/client/driver/structs" "github.com/hashicorp/nomad/client/getter" "github.com/hashicorp/nomad/helper/discover" @@ -36,7 +36,7 @@ type ExecDriverConfig struct { // execHandle is returned from Start/Open as a handle to the PID type execHandle struct { pluginClient *plugin.Client - executor plugins.Executor + executor executor.Executor userPid int killTimeout time.Duration logger *log.Logger @@ -107,11 +107,11 @@ func (d *ExecDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, Cmd: exec.Command(bin, "executor"), } - executor, pluginClient, err := createExecutor(pluginConfig, d.config.LogOutput) + exec, pluginClient, err := createExecutor(pluginConfig, d.config.LogOutput) if err != nil { return nil, err } - executorCtx := &plugins.ExecutorContext{ + executorCtx := &executor.ExecutorContext{ TaskEnv: d.taskEnv, AllocDir: ctx.AllocDir, TaskName: task.Name, @@ -120,7 +120,7 @@ func (d *ExecDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, FSIsolation: true, UnprivilegedUser: false, } - ps, err := executor.LaunchCmd(&plugins.ExecCommand{Cmd: command, Args: driverConfig.Args}, executorCtx) + ps, err := exec.LaunchCmd(&executor.ExecCommand{Cmd: command, Args: driverConfig.Args}, executorCtx) if err != nil { pluginClient.Kill() return nil, fmt.Errorf("error starting process via the plugin: %v", err) @@ -131,7 +131,7 @@ func (d *ExecDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, h := &execHandle{ pluginClient: pluginClient, userPid: ps.Pid, - executor: executor, + executor: exec, killTimeout: d.DriverContext.KillTimeout(task), logger: d.logger, doneCh: make(chan struct{}), @@ -144,7 +144,7 @@ func (d *ExecDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, type execId struct { KillTimeout time.Duration UserPid int - PluginConfig *plugins.ExecutorReattachConfig + PluginConfig *ExecutorReattachConfig } func (d *ExecDriver) Open(ctx *ExecContext, handleID string) (DriverHandle, error) { @@ -183,7 +183,7 @@ func (d *ExecDriver) Open(ctx *ExecContext, handleID string) (DriverHandle, erro func (h *execHandle) ID() string { id := execId{ KillTimeout: h.killTimeout, - PluginConfig: plugins.NewExecutorReattachConfig(h.pluginClient.ReattachConfig()), + PluginConfig: NewExecutorReattachConfig(h.pluginClient.ReattachConfig()), UserPid: h.userPid, } diff --git a/client/driver/plugins/executor.go b/client/driver/executor/executor.go similarity index 99% rename from client/driver/plugins/executor.go rename to client/driver/executor/executor.go index 89ca1397e..60c18e17e 100644 --- a/client/driver/plugins/executor.go +++ b/client/driver/executor/executor.go @@ -1,4 +1,4 @@ -package plugins +package executor import ( "fmt" diff --git a/client/driver/plugins/executor_basic.go b/client/driver/executor/executor_basic.go similarity index 96% rename from client/driver/plugins/executor_basic.go rename to client/driver/executor/executor_basic.go index 464cb3b3f..88acf1105 100644 --- a/client/driver/plugins/executor_basic.go +++ b/client/driver/executor/executor_basic.go @@ -1,6 +1,6 @@ // +build !linux -package plugins +package executor func (e *UniversalExecutor) configureChroot() error { return nil diff --git a/client/driver/plugins/executor_linux.go b/client/driver/executor/executor_linux.go similarity index 99% rename from client/driver/plugins/executor_linux.go rename to client/driver/executor/executor_linux.go index efdd4e410..4c946d429 100644 --- a/client/driver/plugins/executor_linux.go +++ b/client/driver/executor/executor_linux.go @@ -1,4 +1,4 @@ -package plugins +package executor import ( "fmt" diff --git a/client/driver/plugins/executor_test.go b/client/driver/executor/executor_test.go similarity index 99% rename from client/driver/plugins/executor_test.go rename to client/driver/executor/executor_test.go index 98fd89f11..2b7e281ac 100644 --- a/client/driver/plugins/executor_test.go +++ b/client/driver/executor/executor_test.go @@ -1,4 +1,4 @@ -package plugins +package executor import ( "io/ioutil" diff --git a/client/driver/plugins/executor_plugin.go b/client/driver/executor_plugin.go similarity index 70% rename from client/driver/plugins/executor_plugin.go rename to client/driver/executor_plugin.go index 8dbdbe58a..c07ad3f79 100644 --- a/client/driver/plugins/executor_plugin.go +++ b/client/driver/executor_plugin.go @@ -1,4 +1,4 @@ -package plugins +package driver import ( "log" @@ -7,6 +7,7 @@ import ( "os" "github.com/hashicorp/go-plugin" + "github.com/hashicorp/nomad/client/driver/executor" ) var HandshakeConfig = plugin.HandshakeConfig{ @@ -45,39 +46,39 @@ type ExecutorRPC struct { } type LaunchCmdArgs struct { - Cmd *ExecCommand - Ctx *ExecutorContext + Cmd *executor.ExecCommand + Ctx *executor.ExecutorContext } -func (e *ExecutorRPC) LaunchCmd(cmd *ExecCommand, ctx *ExecutorContext) (*ProcessState, error) { - var ps *ProcessState +func (e *ExecutorRPC) LaunchCmd(cmd *executor.ExecCommand, ctx *executor.ExecutorContext) (*executor.ProcessState, error) { + var ps *executor.ProcessState err := e.client.Call("Plugin.LaunchCmd", LaunchCmdArgs{Cmd: cmd, Ctx: ctx}, &ps) return ps, err } -func (e *ExecutorRPC) Wait() (*ProcessState, error) { - var ps ProcessState +func (e *ExecutorRPC) Wait() (*executor.ProcessState, error) { + var ps executor.ProcessState err := e.client.Call("Plugin.Wait", new(interface{}), &ps) return &ps, err } func (e *ExecutorRPC) ShutDown() error { - var ps ProcessState + var ps executor.ProcessState err := e.client.Call("Plugin.ShutDown", new(interface{}), &ps) return err } func (e *ExecutorRPC) Exit() error { - var ps ProcessState + var ps executor.ProcessState err := e.client.Call("Plugin.Exit", new(interface{}), &ps) return err } type ExecutorRPCServer struct { - Impl Executor + Impl executor.Executor } -func (e *ExecutorRPCServer) LaunchCmd(args LaunchCmdArgs, ps *ProcessState) error { +func (e *ExecutorRPCServer) LaunchCmd(args LaunchCmdArgs, ps *executor.ProcessState) error { state, err := e.Impl.LaunchCmd(args.Cmd, args.Ctx) if state != nil { *ps = *state @@ -85,7 +86,7 @@ func (e *ExecutorRPCServer) LaunchCmd(args LaunchCmdArgs, ps *ProcessState) erro return err } -func (e *ExecutorRPCServer) Wait(args interface{}, ps *ProcessState) error { +func (e *ExecutorRPCServer) Wait(args interface{}, ps *executor.ProcessState) error { state, err := e.Impl.Wait() if state != nil { *ps = *state @@ -93,13 +94,13 @@ func (e *ExecutorRPCServer) Wait(args interface{}, ps *ProcessState) error { return err } -func (e *ExecutorRPCServer) ShutDown(args interface{}, ps *ProcessState) error { +func (e *ExecutorRPCServer) ShutDown(args interface{}, ps *executor.ProcessState) error { var err error err = e.Impl.ShutDown() return err } -func (e *ExecutorRPCServer) Exit(args interface{}, ps *ProcessState) error { +func (e *ExecutorRPCServer) Exit(args interface{}, ps *executor.ProcessState) error { var err error err = e.Impl.Exit() return err @@ -111,7 +112,7 @@ type ExecutorPlugin struct { func (p *ExecutorPlugin) Server(*plugin.MuxBroker) (interface{}, error) { p.logger = log.New(os.Stdout, "executor-plugin-server:", log.LstdFlags) - return &ExecutorRPCServer{Impl: NewExecutor(p.logger)}, nil + return &ExecutorRPCServer{Impl: executor.NewExecutor(p.logger)}, nil } func (p *ExecutorPlugin) Client(b *plugin.MuxBroker, c *rpc.Client) (interface{}, error) { diff --git a/client/driver/java.go b/client/driver/java.go index d1600a0db..74f295cf8 100644 --- a/client/driver/java.go +++ b/client/driver/java.go @@ -17,7 +17,7 @@ import ( "github.com/hashicorp/nomad/client/allocdir" "github.com/hashicorp/nomad/client/config" - "github.com/hashicorp/nomad/client/driver/plugins" + "github.com/hashicorp/nomad/client/driver/executor" cstructs "github.com/hashicorp/nomad/client/driver/structs" "github.com/hashicorp/nomad/client/fingerprint" "github.com/hashicorp/nomad/client/getter" @@ -43,7 +43,7 @@ type JavaDriverConfig struct { type javaHandle struct { pluginClient *plugin.Client userPid int - executor plugins.Executor + executor executor.Executor killTimeout time.Duration logger *log.Logger @@ -152,17 +152,17 @@ func (d *JavaDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, Cmd: exec.Command(bin, "executor"), } - executor, pluginClient, err := createExecutor(pluginConfig, d.config.LogOutput) + exec, pluginClient, err := createExecutor(pluginConfig, d.config.LogOutput) if err != nil { return nil, err } - executorCtx := &plugins.ExecutorContext{ + executorCtx := &executor.ExecutorContext{ TaskEnv: d.taskEnv, AllocDir: ctx.AllocDir, TaskName: task.Name, TaskResources: task.Resources, } - ps, err := executor.LaunchCmd(&plugins.ExecCommand{Cmd: "java", Args: args}, executorCtx) + ps, err := exec.LaunchCmd(&executor.ExecCommand{Cmd: "java", Args: args}, executorCtx) if err != nil { pluginClient.Kill() return nil, fmt.Errorf("error starting process via the plugin: %v", err) @@ -172,7 +172,7 @@ func (d *JavaDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, // Return a driver handle h := &javaHandle{ pluginClient: pluginClient, - executor: executor, + executor: exec, userPid: ps.Pid, killTimeout: d.DriverContext.KillTimeout(task), logger: d.logger, @@ -186,7 +186,7 @@ func (d *JavaDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, type javaId struct { KillTimeout time.Duration - PluginConfig *plugins.ExecutorReattachConfig + PluginConfig *ExecutorReattachConfig UserPid int } @@ -227,7 +227,7 @@ func (d *JavaDriver) Open(ctx *ExecContext, handleID string) (DriverHandle, erro func (h *javaHandle) ID() string { id := javaId{ KillTimeout: h.killTimeout, - PluginConfig: plugins.NewExecutorReattachConfig(h.pluginClient.ReattachConfig()), + PluginConfig: NewExecutorReattachConfig(h.pluginClient.ReattachConfig()), UserPid: h.userPid, } diff --git a/client/driver/qemu.go b/client/driver/qemu.go index 69a1ed178..e7753fcc9 100644 --- a/client/driver/qemu.go +++ b/client/driver/qemu.go @@ -14,7 +14,7 @@ import ( "github.com/hashicorp/go-plugin" "github.com/hashicorp/nomad/client/allocdir" "github.com/hashicorp/nomad/client/config" - "github.com/hashicorp/nomad/client/driver/plugins" + "github.com/hashicorp/nomad/client/driver/executor" cstructs "github.com/hashicorp/nomad/client/driver/structs" "github.com/hashicorp/nomad/client/fingerprint" "github.com/hashicorp/nomad/client/getter" @@ -46,7 +46,7 @@ type QemuDriverConfig struct { type qemuHandle struct { pluginClient *plugin.Client userPid int - executor plugins.Executor + executor executor.Executor killTimeout time.Duration logger *log.Logger waitCh chan *cstructs.WaitResult @@ -196,17 +196,17 @@ func (d *QemuDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, Cmd: exec.Command(bin, "executor"), } - executor, pluginClient, err := createExecutor(pluginConfig, d.config.LogOutput) + exec, pluginClient, err := createExecutor(pluginConfig, d.config.LogOutput) if err != nil { return nil, err } - executorCtx := &plugins.ExecutorContext{ + executorCtx := &executor.ExecutorContext{ TaskEnv: d.taskEnv, AllocDir: ctx.AllocDir, TaskName: task.Name, TaskResources: task.Resources, } - ps, err := executor.LaunchCmd(&plugins.ExecCommand{Cmd: args[0], Args: args[1:]}, executorCtx) + ps, err := exec.LaunchCmd(&executor.ExecCommand{Cmd: args[0], Args: args[1:]}, executorCtx) if err != nil { pluginClient.Kill() return nil, fmt.Errorf("error starting process via the plugin: %v", err) @@ -217,7 +217,7 @@ func (d *QemuDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, // Create and Return Handle h := &qemuHandle{ pluginClient: pluginClient, - executor: executor, + executor: exec, userPid: ps.Pid, killTimeout: d.DriverContext.KillTimeout(task), logger: d.logger, @@ -232,7 +232,7 @@ func (d *QemuDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, type qemuId struct { KillTimeout time.Duration UserPid int - PluginConfig *plugins.ExecutorReattachConfig + PluginConfig *ExecutorReattachConfig } func (d *QemuDriver) Open(ctx *ExecContext, handleID string) (DriverHandle, error) { @@ -272,7 +272,7 @@ func (d *QemuDriver) Open(ctx *ExecContext, handleID string) (DriverHandle, erro func (h *qemuHandle) ID() string { id := qemuId{ KillTimeout: h.killTimeout, - PluginConfig: plugins.NewExecutorReattachConfig(h.pluginClient.ReattachConfig()), + PluginConfig: NewExecutorReattachConfig(h.pluginClient.ReattachConfig()), UserPid: h.userPid, } diff --git a/client/driver/raw_exec.go b/client/driver/raw_exec.go index f3f670d25..5b92e6d85 100644 --- a/client/driver/raw_exec.go +++ b/client/driver/raw_exec.go @@ -11,7 +11,7 @@ import ( "github.com/hashicorp/go-plugin" "github.com/hashicorp/nomad/client/allocdir" "github.com/hashicorp/nomad/client/config" - "github.com/hashicorp/nomad/client/driver/plugins" + "github.com/hashicorp/nomad/client/driver/executor" cstructs "github.com/hashicorp/nomad/client/driver/structs" "github.com/hashicorp/nomad/client/fingerprint" "github.com/hashicorp/nomad/client/getter" @@ -37,7 +37,7 @@ type RawExecDriver struct { type rawExecHandle struct { pluginClient *plugin.Client userPid int - executor plugins.Executor + executor executor.Executor killTimeout time.Duration logger *log.Logger waitCh chan *cstructs.WaitResult @@ -103,17 +103,17 @@ func (d *RawExecDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandl Cmd: exec.Command(bin, "executor"), } - executor, pluginClient, err := createExecutor(pluginConfig, d.config.LogOutput) + exec, pluginClient, err := createExecutor(pluginConfig, d.config.LogOutput) if err != nil { return nil, err } - executorCtx := &plugins.ExecutorContext{ + executorCtx := &executor.ExecutorContext{ TaskEnv: d.taskEnv, AllocDir: ctx.AllocDir, TaskName: task.Name, TaskResources: task.Resources, } - ps, err := executor.LaunchCmd(&plugins.ExecCommand{Cmd: command, Args: driverConfig.Args}, executorCtx) + ps, err := exec.LaunchCmd(&executor.ExecCommand{Cmd: command, Args: driverConfig.Args}, executorCtx) if err != nil { pluginClient.Kill() return nil, fmt.Errorf("error starting process via the plugin: %v", err) @@ -123,7 +123,7 @@ func (d *RawExecDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandl // Return a driver handle h := &rawExecHandle{ pluginClient: pluginClient, - executor: executor, + executor: exec, userPid: ps.Pid, killTimeout: d.DriverContext.KillTimeout(task), logger: d.logger, @@ -137,7 +137,7 @@ func (d *RawExecDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandl type rawExecId struct { KillTimeout time.Duration UserPid int - PluginConfig *plugins.ExecutorReattachConfig + PluginConfig *ExecutorReattachConfig } func (d *RawExecDriver) Open(ctx *ExecContext, handleID string) (DriverHandle, error) { @@ -175,7 +175,7 @@ func (d *RawExecDriver) Open(ctx *ExecContext, handleID string) (DriverHandle, e func (h *rawExecHandle) ID() string { id := rawExecId{ KillTimeout: h.killTimeout, - PluginConfig: plugins.NewExecutorReattachConfig(h.pluginClient.ReattachConfig()), + PluginConfig: NewExecutorReattachConfig(h.pluginClient.ReattachConfig()), UserPid: h.userPid, } diff --git a/client/driver/utils.go b/client/driver/utils.go index d39996718..972876eeb 100644 --- a/client/driver/utils.go +++ b/client/driver/utils.go @@ -7,12 +7,12 @@ import ( "github.com/hashicorp/go-multierror" "github.com/hashicorp/go-plugin" - "github.com/hashicorp/nomad/client/driver/plugins" + "github.com/hashicorp/nomad/client/driver/executor" ) -func createExecutor(config *plugin.ClientConfig, w io.Writer) (plugins.Executor, *plugin.Client, error) { - config.HandshakeConfig = plugins.HandshakeConfig - config.Plugins = plugins.PluginMap +func createExecutor(config *plugin.ClientConfig, w io.Writer) (executor.Executor, *plugin.Client, error) { + config.HandshakeConfig = HandshakeConfig + config.Plugins = PluginMap config.SyncStdout = w config.SyncStderr = w executorClient := plugin.NewClient(config) @@ -25,7 +25,7 @@ func createExecutor(config *plugin.ClientConfig, w io.Writer) (plugins.Executor, if err != nil { return nil, nil, fmt.Errorf("unable to dispense the executor plugin: %v", err) } - executorPlugin := raw.(plugins.Executor) + executorPlugin := raw.(executor.Executor) return executorPlugin, executorClient, nil } diff --git a/command/executor_plugin.go b/command/executor_plugin.go index 44f86836a..15a84db84 100644 --- a/command/executor_plugin.go +++ b/command/executor_plugin.go @@ -5,7 +5,7 @@ import ( "github.com/hashicorp/go-plugin" - "github.com/hashicorp/nomad/client/driver/plugins" + "github.com/hashicorp/nomad/client/driver" ) type ExecutorPluginCommand struct { @@ -25,8 +25,8 @@ func (e *ExecutorPluginCommand) Synopsis() string { func (e *ExecutorPluginCommand) Run(args []string) int { plugin.Serve(&plugin.ServeConfig{ - HandshakeConfig: plugins.HandshakeConfig, - Plugins: plugins.PluginMap, + HandshakeConfig: driver.HandshakeConfig, + Plugins: driver.PluginMap, }) return 0 } diff --git a/command/spawn_daemon.go b/command/spawn_daemon.go deleted file mode 100644 index 52ffd8e6c..000000000 --- a/command/spawn_daemon.go +++ /dev/null @@ -1,234 +0,0 @@ -package command - -import ( - "encoding/json" - "fmt" - "io" - "os" - "os/exec" - "strconv" - "strings" - "syscall" -) - -type SpawnDaemonCommand struct { - Meta - config *DaemonConfig - exitFile io.WriteCloser -} - -func (c *SpawnDaemonCommand) Help() string { - helpText := ` -Usage: nomad spawn-daemon [options] - - INTERNAL ONLY - - Spawns a daemon process by double forking. The required daemon_config is a - json encoding of the DaemonConfig struct containing the isolation - configuration and command to run. SpawnStartStatus is json serialized to - stdout upon running the user command or if any error prevents its execution. - If there is no error, the process waits on the users command. Once the user - command exits, the exit code is written to a file specified in the - daemon_config and this process exits with the same exit status as the user - command. - ` - - return strings.TrimSpace(helpText) -} - -func (c *SpawnDaemonCommand) Synopsis() string { - return "Spawn a daemon command with configurable isolation." -} - -// Status of executing the user's command. -type SpawnStartStatus struct { - // The PID of the user's command. - UserPID int - - // ErrorMsg will be empty if the user command was started successfully. - // Otherwise it will have an error message. - ErrorMsg string -} - -// Exit status of the user's command. -type SpawnExitStatus struct { - // The exit code of the user's command. - ExitCode int -} - -// Configuration for the command to start as a daemon. -type DaemonConfig struct { - exec.Cmd - - // The filepath to write the exit status to. - ExitStatusFile string - - // The paths, if not /dev/null, must be either in the tasks root directory - // or in the shared alloc directory. - StdoutFile string - StdinFile string - StderrFile string - - // An optional path specifying the directory to chroot the process in. - Chroot string -} - -// Whether to start the user command or abort. -type TaskStart bool - -// parseConfig reads the DaemonConfig from the passed arguments. If not -// successful, an error is returned. -func (c *SpawnDaemonCommand) parseConfig(args []string) (*DaemonConfig, error) { - flags := c.Meta.FlagSet("spawn-daemon", FlagSetClient) - flags.Usage = func() { c.Ui.Output(c.Help()) } - if err := flags.Parse(args); err != nil { - return nil, fmt.Errorf("failed to parse args: %v", err) - } - - // Check that we got json input. - args = flags.Args() - if len(args) != 1 { - return nil, fmt.Errorf("incorrect number of args; got %v; want 1", len(args)) - } - jsonInput, err := strconv.Unquote(args[0]) - if err != nil { - return nil, fmt.Errorf("Failed to unquote json input: %v", err) - } - - // De-serialize the passed command. - var config DaemonConfig - dec := json.NewDecoder(strings.NewReader(jsonInput)) - if err := dec.Decode(&config); err != nil { - return nil, err - } - - return &config, nil -} - -// configureLogs creates the log files and redirects the process -// stdin/stderr/stdout to them. If unsuccessful, an error is returned. -func (c *SpawnDaemonCommand) configureLogs() error { - if len(c.config.StdoutFile) != 0 { - stdo, err := os.OpenFile(c.config.StdoutFile, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0666) - if err != nil { - return fmt.Errorf("Error opening file to redirect stdout: %v", err) - } - - c.config.Cmd.Stdout = stdo - } - - if len(c.config.StderrFile) != 0 { - stde, err := os.OpenFile(c.config.StderrFile, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0666) - if err != nil { - return fmt.Errorf("Error opening file to redirect stderr: %v", err) - } - c.config.Cmd.Stderr = stde - } - - if len(c.config.StdinFile) != 0 { - stdi, err := os.OpenFile(c.config.StdinFile, os.O_CREATE|os.O_RDONLY, 0666) - if err != nil { - return fmt.Errorf("Error opening file to redirect stdin: %v", err) - } - c.config.Cmd.Stdin = stdi - } - - return nil -} - -func (c *SpawnDaemonCommand) Run(args []string) int { - var err error - c.config, err = c.parseConfig(args) - if err != nil { - return c.outputStartStatus(err, 1) - } - - // Open the file we will be using to write exit codes to. We do this early - // to ensure that we don't start the user process when we can't capture its - // exit status. - c.exitFile, err = os.OpenFile(c.config.ExitStatusFile, os.O_WRONLY, 0666) - if err != nil { - return c.outputStartStatus(fmt.Errorf("Error opening file to store exit status: %v", err), 1) - } - - // Isolate the user process. - if err := c.isolateCmd(); err != nil { - return c.outputStartStatus(err, 1) - } - - // Redirect logs. - if err := c.configureLogs(); err != nil { - return c.outputStartStatus(err, 1) - } - - // Chroot jail the process and set its working directory. - c.configureChroot() - - // Wait to get the start command. - var start TaskStart - dec := json.NewDecoder(os.Stdin) - if err := dec.Decode(&start); err != nil { - return c.outputStartStatus(err, 1) - } - - // Aborted by Nomad process. - if !start { - return 0 - } - - // Spawn the user process. - if err := c.config.Cmd.Start(); err != nil { - return c.outputStartStatus(fmt.Errorf("Error starting user command: %v", err), 1) - } - - // Indicate that the command was started successfully. - c.outputStartStatus(nil, 0) - - // Wait and then output the exit status. - return c.writeExitStatus(c.config.Cmd.Wait()) -} - -// outputStartStatus is a helper function that outputs a SpawnStartStatus to -// Stdout with the passed error, which may be nil to indicate no error. It -// returns the passed status. -func (c *SpawnDaemonCommand) outputStartStatus(err error, status int) int { - startStatus := &SpawnStartStatus{} - enc := json.NewEncoder(os.Stdout) - - if err != nil { - startStatus.ErrorMsg = err.Error() - } - - if c.config != nil && c.config.Cmd.Process != nil { - startStatus.UserPID = c.config.Process.Pid - } - - enc.Encode(startStatus) - return status -} - -// writeExitStatus takes in the error result from calling wait and writes out -// the exit status to a file. It returns the same exit status as the user -// command. -func (c *SpawnDaemonCommand) writeExitStatus(exit error) int { - // Parse the exit code. - exitStatus := &SpawnExitStatus{} - if exit != nil { - // Default to exit code 1 if we can not get the actual exit code. - exitStatus.ExitCode = 1 - - if exiterr, ok := exit.(*exec.ExitError); ok { - if status, ok := exiterr.Sys().(syscall.WaitStatus); ok { - exitStatus.ExitCode = status.ExitStatus() - } - } - } - - if c.exitFile != nil { - enc := json.NewEncoder(c.exitFile) - enc.Encode(exitStatus) - c.exitFile.Close() - } - - return exitStatus.ExitCode -} diff --git a/command/spawn_daemon_darwin.go b/command/spawn_daemon_darwin.go deleted file mode 100644 index f3fe8484a..000000000 --- a/command/spawn_daemon_darwin.go +++ /dev/null @@ -1,4 +0,0 @@ -package command - -// No chroot on darwin. -func (c *SpawnDaemonCommand) configureChroot() {} diff --git a/command/spawn_daemon_linux.go b/command/spawn_daemon_linux.go deleted file mode 100644 index 512ec645f..000000000 --- a/command/spawn_daemon_linux.go +++ /dev/null @@ -1,16 +0,0 @@ -package command - -import "syscall" - -// configureChroot enters the user command into a chroot if specified in the -// config and on an OS that supports Chroots. -func (c *SpawnDaemonCommand) configureChroot() { - if len(c.config.Chroot) != 0 { - if c.config.Cmd.SysProcAttr == nil { - c.config.Cmd.SysProcAttr = &syscall.SysProcAttr{} - } - - c.config.Cmd.SysProcAttr.Chroot = c.config.Chroot - c.config.Cmd.Dir = "/" - } -} diff --git a/command/spawn_daemon_test.go b/command/spawn_daemon_test.go deleted file mode 100644 index 5bfd6ad5a..000000000 --- a/command/spawn_daemon_test.go +++ /dev/null @@ -1,48 +0,0 @@ -package command - -import ( - "bytes" - "encoding/json" - "fmt" - "io" - "os/exec" - "testing" -) - -type nopCloser struct { - io.ReadWriter -} - -func (n *nopCloser) Close() error { - return nil -} - -func TestSpawnDaemon_WriteExitStatus(t *testing.T) { - // Check if there is python. - path, err := exec.LookPath("python") - if err != nil { - t.Skip("python not detected") - } - - var b bytes.Buffer - daemon := &SpawnDaemonCommand{exitFile: &nopCloser{&b}} - - code := 3 - cmd := exec.Command(path, "./test-resources/exiter.py", fmt.Sprintf("%d", code)) - err = cmd.Run() - actual := daemon.writeExitStatus(err) - if actual != code { - t.Fatalf("writeExitStatus(%v) returned %v; want %v", err, actual, code) - } - - // De-serialize the passed command. - var exitStatus SpawnExitStatus - dec := json.NewDecoder(&b) - if err := dec.Decode(&exitStatus); err != nil { - t.Fatalf("failed to decode exit status: %v", err) - } - - if exitStatus.ExitCode != code { - t.Fatalf("writeExitStatus(%v) wrote exit status %v; want %v", err, exitStatus.ExitCode, code) - } -} diff --git a/command/spawn_daemon_unix.go b/command/spawn_daemon_unix.go deleted file mode 100644 index 981e52596..000000000 --- a/command/spawn_daemon_unix.go +++ /dev/null @@ -1,16 +0,0 @@ -// +build !windows - -package command - -import "syscall" - -// isolateCmd sets the session id for the process and the umask. -func (c *SpawnDaemonCommand) isolateCmd() error { - if c.config.Cmd.SysProcAttr == nil { - c.config.Cmd.SysProcAttr = &syscall.SysProcAttr{} - } - - c.config.Cmd.SysProcAttr.Setsid = true - syscall.Umask(0) - return nil -} diff --git a/command/spawn_daemon_windows.go b/command/spawn_daemon_windows.go deleted file mode 100644 index bb2d63ed8..000000000 --- a/command/spawn_daemon_windows.go +++ /dev/null @@ -1,7 +0,0 @@ -// build !linux !darwin - -package command - -// No isolation on Windows. -func (c *SpawnDaemonCommand) isolateCmd() error { return nil } -func (c *SpawnDaemonCommand) configureChroot() {} diff --git a/commands.go b/commands.go index 9f5fedb12..99294858d 100644 --- a/commands.go +++ b/commands.go @@ -118,13 +118,6 @@ func Commands(metaPtr *command.Meta) map[string]cli.CommandFactory { Meta: meta, }, nil }, - - "spawn-daemon": func() (cli.Command, error) { - return &command.SpawnDaemonCommand{ - Meta: meta, - }, nil - }, - "status": func() (cli.Command, error) { return &command.StatusCommand{ Meta: meta,