From ecdc1c92b6bc96ac02be423a11e3da1776c720d3 Mon Sep 17 00:00:00 2001 From: Alex Dadgar Date: Wed, 28 Oct 2015 17:22:04 -0700 Subject: [PATCH] Exec driver only applies on linux as root --- client/driver/exec.go | 13 ++-- client/driver/exec_test.go | 17 +---- client/executor/exec_universal.go | 109 +++------------------------ client/testutil/driver_compatible.go | 4 +- 4 files changed, 23 insertions(+), 120 deletions(-) diff --git a/client/driver/exec.go b/client/driver/exec.go index 0324cad68..cbcb85a0a 100644 --- a/client/driver/exec.go +++ b/client/driver/exec.go @@ -35,8 +35,11 @@ func NewExecDriver(ctx *DriverContext) Driver { } func (d *ExecDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool, error) { - // Only enable if we are root when running on non-windows systems. - if runtime.GOOS != "windows" && syscall.Geteuid() != 0 { + // Only enable if we are root on linux. + if runtime.GOOS != "linux" { + d.logger.Printf("[DEBUG] driver.exec: only available on linux, disabling") + return false, nil + } else if syscall.Geteuid() != 0 { d.logger.Printf("[DEBUG] driver.exec: must run as root user, disabling") return false, nil } @@ -73,10 +76,8 @@ func (d *ExecDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, } // Add execution permissions to the newly downloaded artifact - if runtime.GOOS != "windows" { - if err := syscall.Chmod(artifactFile, 0755); err != nil { - log.Printf("[ERR] driver.Exec: Error making artifact executable: %s", err) - } + if err := syscall.Chmod(artifactFile, 0755); err != nil { + log.Printf("[ERR] driver.exec: Error making artifact executable: %s", err) } } diff --git a/client/driver/exec_test.go b/client/driver/exec_test.go index ba8745176..488847c5c 100644 --- a/client/driver/exec_test.go +++ b/client/driver/exec_test.go @@ -5,7 +5,6 @@ import ( "io/ioutil" "path/filepath" "reflect" - "runtime" "testing" "time" @@ -123,13 +122,7 @@ func TestExecDriver_Start_Wait(t *testing.T) { func TestExecDriver_Start_Artifact_basic(t *testing.T) { ctestutils.ExecCompatible(t) - var file string - switch runtime.GOOS { - case "darwin": - file = "hi_darwin_amd64" - default: - file = "hi_linux_amd64" - } + file := "hi_linux_amd64" task := &structs.Task{ Name: "sleep", @@ -172,13 +165,7 @@ func TestExecDriver_Start_Artifact_basic(t *testing.T) { func TestExecDriver_Start_Artifact_expanded(t *testing.T) { ctestutils.ExecCompatible(t) - var file string - switch runtime.GOOS { - case "darwin": - file = "hi_darwin_amd64" - default: - file = "hi_linux_amd64" - } + file := "hi_linux_amd64" task := &structs.Task{ Name: "sleep", diff --git a/client/executor/exec_universal.go b/client/executor/exec_universal.go index 6b1977d10..4979ae3b7 100644 --- a/client/executor/exec_universal.go +++ b/client/executor/exec_universal.go @@ -3,105 +3,20 @@ package executor import ( - "fmt" - "os" - "strconv" - "strings" - "github.com/hashicorp/nomad/client/allocdir" - "github.com/hashicorp/nomad/client/driver/args" - "github.com/hashicorp/nomad/client/driver/environment" "github.com/hashicorp/nomad/nomad/structs" ) -func NewExecutor() Executor { - return &UniversalExecutor{} -} +// UniversalExecutor exists to make the exec driver compile on all operating systems. +type UniversalExecutor struct{} -// UniversalExecutor should work everywhere, and as a result does not include -// any resource restrictions or runas capabilities. -type UniversalExecutor struct { - cmd -} - -func (e *UniversalExecutor) Limit(resources *structs.Resources) error { - if resources == nil { - return errNoResources - } - return nil -} - -func (e *UniversalExecutor) ConfigureTaskDir(taskName string, alloc *allocdir.AllocDir) error { - taskDir, ok := alloc.TaskDirs[taskName] - if !ok { - return fmt.Errorf("Error finding task dir for (%s)", taskName) - } - e.Dir = taskDir - return nil -} - -func (e *UniversalExecutor) Start() error { - // Parse the commands arguments and replace instances of Nomad environment - // variables. - envVars, err := environment.ParseFromList(e.cmd.Env) - if err != nil { - return err - } - - parsedPath, err := args.ParseAndReplace(e.cmd.Path, envVars.Map()) - if err != nil { - return err - } else if len(parsedPath) != 1 { - return fmt.Errorf("couldn't properly parse command path: %v", e.cmd.Path) - } - - e.cmd.Path = parsedPath[0] - combined := strings.Join(e.cmd.Args, " ") - parsed, err := args.ParseAndReplace(combined, envVars.Map()) - if err != nil { - return err - } - e.Cmd.Args = parsed - - // We don't want to call ourself. We want to call Start on our embedded Cmd - return e.cmd.Start() -} - -func (e *UniversalExecutor) Open(pid string) error { - pidNum, err := strconv.Atoi(pid) - if err != nil { - return fmt.Errorf("Failed to parse pid %v: %v", pid, err) - } - - process, err := os.FindProcess(pidNum) - if err != nil { - return fmt.Errorf("Failed to reopen pid %d: %v", pidNum, err) - } - e.Process = process - return nil -} - -func (e *UniversalExecutor) Wait() error { - // We don't want to call ourself. We want to call Start on our embedded Cmd - return e.cmd.Wait() -} - -func (e *UniversalExecutor) ID() (string, error) { - if e.cmd.Process != nil { - return strconv.Itoa(e.cmd.Process.Pid), nil - } else { - return "", fmt.Errorf("Process has finished or was never started") - } -} - -func (e *UniversalExecutor) Shutdown() error { - return e.ForceStop() -} - -func (e *UniversalExecutor) ForceStop() error { - return e.Process.Kill() -} - -func (e *UniversalExecutor) Command() *cmd { - return &e.cmd -} +func NewExecutor() Executor { return &UniversalExecutor{} } +func (e *UniversalExecutor) Limit(resources *structs.Resources) error { return nil } +func (e *UniversalExecutor) ConfigureTaskDir(string, *allocdir.AllocDir) error { return nil } +func (e *UniversalExecutor) Start() error { return nil } +func (e *UniversalExecutor) Open(pid string) error { return nil } +func (e *UniversalExecutor) Wait() error { return nil } +func (e *UniversalExecutor) ID() (string, error) { return "", nil } +func (e *UniversalExecutor) Shutdown() error { return nil } +func (e *UniversalExecutor) ForceStop() error { return nil } +func (e *UniversalExecutor) Command() *cmd { return nil } diff --git a/client/testutil/driver_compatible.go b/client/testutil/driver_compatible.go index df1d27d11..94ae6225c 100644 --- a/client/testutil/driver_compatible.go +++ b/client/testutil/driver_compatible.go @@ -8,8 +8,8 @@ import ( ) func ExecCompatible(t *testing.T) { - if runtime.GOOS != "windows" && syscall.Geteuid() != 0 { - t.Skip("Must be root on non-windows environments to run test") + if runtime.GOOS != "linux" || syscall.Geteuid() != 0 { + t.Skip("Test only available running as root on linux") } }