{"action":"created","comment":{"url":"https://api.github.com/repos/hashicorp/nomad/pulls/comments/52051552","id":52051552,"diff_hunk":"@@ -0,0 +1,217 @@\n+package executor\n+\n+import (\n+\t\"fmt\"\n+\t\"log\"\n+\t\"os\"\n+\t\"os/exec\"\n+\t\"path/filepath\"\n+\t\"runtime\"\n+\t\"sync\"\n+\t\"syscall\"\n+\t\"time\"\n+\n+\tcgroupConfig \"github.com/opencontainers/runc/libcontainer/configs\"\n+\n+\t\"github.com/hashicorp/nomad/client/allocdir\"\n+\t\"github.com/hashicorp/nomad/client/driver/env\"\n+\t\"github.com/hashicorp/nomad/nomad/structs\"\n+)\n+\n+// ExecutorContext is a wrapper to hold context to configure the command user\n+// wants to run\n+type ExecutorContext struct {\n+\tTaskEnv          *env.TaskEnvironment\n+\tAllocDir         *allocdir.AllocDir\n+\tTaskName         string\n+\tTaskResources    *structs.Resources\n+\tFSIsolation      bool\n+\tResourceLimits   bool\n+\tUnprivilegedUser bool\n+}\n+\n+// ExecCommand is a wrapper to hold the user command\n+type ExecCommand struct {\n+\tCmd  string\n+\tArgs []string\n+}\n+\n+// ProcessState holds information about the state of\n+// a user process\n+type ProcessState struct {\n+\tPid      int\n+\tExitCode int\n+\tTime     time.Time\n+}\n+\n+// Executor is the interface which allows a driver to launch and supervise\n+// a process user wants to run\n+type Executor interface {\n+\tLaunchCmd(command *ExecCommand, ctx *ExecutorContext) (*ProcessState, error)\n+\tWait() (*ProcessState, error)\n+\tShutDown() error\n+\tExit() error\n+}\n+\n+// UniversalExecutor is an implementation of the Executor which launches and\n+// supervises processes. In addition to process supervision it provides resource\n+// and file system isolation\n+type UniversalExecutor struct {\n+\tcmd exec.Cmd\n+\tctx *ExecutorContext\n+\n+\ttaskDir       string\n+\tgroups        *cgroupConfig.Cgroup\n+\texitState     *ProcessState\n+\tprocessExited chan interface{}\n+\n+\tlogger *log.Logger\n+\tlock   sync.Mutex\n+}\n+\n+// NewExecutor returns an Executor\n+func NewExecutor(logger *log.Logger) Executor {\n+\treturn &UniversalExecutor{logger: logger, processExited: make(chan interface{})}\n+}\n+\n+// LaunchCmd launches a process and returns it's state. It also configures an\n+// applies isolation on certain platforms.\n+func (e *UniversalExecutor) LaunchCmd(command *ExecCommand, ctx *ExecutorContext) (*ProcessState, error) {\n+\te.logger.Printf(\"[INFO] executor: launching command %v\", command.Cmd)\n+\n+\te.ctx = ctx\n+\n+\t// configuring the task dir\n+\tif err := e.configureTaskDir(); err != nil {\n+\t\treturn nil, err\n+\t}\n+\n+\t// confiuguring the chroot\n+\tif err := e.configureIsolation(); err != nil {\n+\t\treturn nil, err\n+\t}\n+\n+\t// setting the user of the process\n+\tif e.ctx.UnprivilegedUser {\n+\t\tif err := e.runAs(\"nobody\"); err != nil {\n+\t\t\treturn nil, err\n+\t\t}\n+\t}\n+\n+\t// configuring log rotate\n+\tstdoPath := filepath.Join(e.taskDir, allocdir.TaskLocal, fmt.Sprintf(\"%v.stdout\", ctx.TaskName))\n+\tstdo, err := os.OpenFile(stdoPath, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0666)\n+\tif err != nil {\n+\t\treturn nil, err\n+\t}\n+\te.cmd.Stdout = stdo\n+\n+\tstdePath := filepath.Join(e.taskDir, allocdir.TaskLocal, fmt.Sprintf(\"%v.stderr\", ctx.TaskName))\n+\tstde, err := os.OpenFile(stdePath, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0666)\n+\tif err != nil {\n+\t\treturn nil, err\n+\t}\n+\te.cmd.Stderr = stde\n+\n+\t// setting the env, path and args for the command\n+\te.cmd.Env = ctx.TaskEnv.EnvList()\n+\te.cmd.Path = ctx.TaskEnv.ReplaceEnv(command.Cmd)\n+\te.cmd.Args = append([]string{e.cmd.Path}, ctx.TaskEnv.ParseAndReplace(command.Args)...)\n+\tif filepath.Base(command.Cmd) == command.Cmd {\n+\t\tif lp, err := exec.LookPath(command.Cmd); err != nil {\n+\t\t} else {\n+\t\t\te.cmd.Path = lp\n+\t\t}\n+\t}\n+\n+\t// starting the process\n+\tif err := e.cmd.Start(); err != nil {\n+\t\treturn nil, fmt.Errorf(\"error starting command: %v\", err)\n+\t}\n+\n+\t// entering the user process in the cgroup\n+\te.applyLimits(e.cmd.Process.Pid)\n+\t// entering the plugin process in cgroup\n+\te.applyLimits(os.Getpid())","path":"client/driver/executor/executor.go","position":135,"original_position":135,"commit_id":"ab493c2fb3123998fd0904802ea993420fe5bd8b","original_commit_id":"ab493c2fb3123998fd0904802ea993420fe5bd8b","user":{"login":"diptanu","id":21833,"avatar_url":"https://avatars.githubusercontent.com/u/21833?v=3","gravatar_id":"","url":"https://api.github.com/users/diptanu","html_url":"https://github.com/diptanu","followers_url":"https://api.github.com/users/diptanu/followers","following_url":"https://api.github.com/users/diptanu/following{/other_user}","gists_url":"https://api.github.com/users/diptanu/gists{/gist_id}","starred_url":"https://api.github.com/users/diptanu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/diptanu/subscriptions","organizations_url":"https://api.github.com/users/diptanu/orgs","repos_url":"https://api.github.com/users/diptanu/repos","events_url":"https://api.github.com/users/diptanu/events{/privacy}","received_events_url":"https://api.github.com/users/diptanu/received_events","type":"User","site_admin":false},"body":"@dadgar Good catch.","created_at":"2016-02-05T18:13:45Z","updated_at":"2016-02-05T18:13:45Z","html_url":"https://github.com/hashicorp/nomad/pull/759#discussion_r52051552","pull_request_url":"https://api.github.com/repos/hashicorp/nomad/pulls/759","_links":{"self":{"href":"https://api.github.com/repos/hashicorp/nomad/pulls/comments/52051552"},"html":{"href":"https://github.com/hashicorp/nomad/pull/759#discussion_r52051552"},"pull_request":{"href":"https://api.github.com/repos/hashicorp/nomad/pulls/759"}}},"pull_request":{"url":"https://api.github.com/repos/hashicorp/nomad/pulls/759","id":58371231,"html_url":"https://github.com/hashicorp/nomad/pull/759","diff_url":"https://github.com/hashicorp/nomad/pull/759.diff","patch_url":"https://github.com/hashicorp/nomad/pull/759.patch","issue_url":"https://api.github.com/repos/hashicorp/nomad/issues/759","number":759,"state":"open","locked":false,"title":"Implement executor plugin","user":{"login":"diptanu","id":21833,"avatar_url":"https://avatars.githubusercontent.com/u/21833?v=3","gravatar_id":"","url":"https://api.github.com/users/diptanu","html_url":"https://github.com/diptanu","followers_url":"https://api.github.com/users/diptanu/followers","following_url":"https://api.github.com/users/diptanu/following{/other_user}","gists_url":"https://api.github.com/users/diptanu/gists{/gist_id}","starred_url":"https://api.github.com/users/diptanu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/diptanu/subscriptions","organizations_url":"https://api.github.com/users/diptanu/orgs","repos_url":"https://api.github.com/users/diptanu/repos","events_url":"https://api.github.com/users/diptanu/events{/privacy}","received_events_url":"https://api.github.com/users/diptanu/received_events","type":"User","site_admin":false},"body":"This PR introduces an executor plugin to launch and supervise processes.\r\n\r\nWhile working on this PR I found out there is a lot of duplication between all the exec based drivers. We can tackle them in a follow up PR post 0.3.","created_at":"2016-02-05T00:20:27Z","updated_at":"2016-02-05T18:13:45Z","closed_at":null,"merged_at":null,"merge_commit_sha":"06d1d00400ee6aac599fa43d1e06e2187ab5cbe3","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/hashicorp/nomad/pulls/759/commits","review_comments_url":"https://api.github.com/repos/hashicorp/nomad/pulls/759/comments","review_comment_url":"https://api.github.com/repos/hashicorp/nomad/pulls/comments{/number}","comments_url":"https://api.github.com/repos/hashicorp/nomad/issues/759/comments","statuses_url":"https://api.github.com/repos/hashicorp/nomad/statuses/ab493c2fb3123998fd0904802ea993420fe5bd8b","head":{"label":"hashicorp:r-executor-plugin","ref":"r-executor-plugin","sha":"ab493c2fb3123998fd0904802ea993420fe5bd8b","user":{"login":"hashicorp","id":761456,"avatar_url":"https://avatars.githubusercontent.com/u/761456?v=3","gravatar_id":"","url":"https://api.github.com/users/hashicorp","html_url":"https://github.com/hashicorp","followers_url":"https://api.github.com/users/hashicorp/followers","following_url":"https://api.github.com/users/hashicorp/following{/other_user}","gists_url":"https://api.github.com/users/hashicorp/gists{/gist_id}","starred_url":"https://api.github.com/users/hashicorp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hashicorp/subscriptions","organizations_url":"https://api.github.com/users/hashicorp/orgs","repos_url":"https://api.github.com/users/hashicorp/repos","events_url":"https://api.github.com/users/hashicorp/events{/privacy}","received_events_url":"https://api.github.com/users/hashicorp/received_events","type":"Organization","site_admin":false},"repo":{"id":36653430,"name":"nomad","full_name":"hashicorp/nomad","owner":{"login":"hashicorp","id":761456,"avatar_url":"https://avatars.githubusercontent.com/u/761456?v=3","gravatar_id":"","url":"https://api.github.com/users/hashicorp","html_url":"https://github.com/hashicorp","followers_url":"https://api.github.com/users/hashicorp/followers","following_url":"https://api.github.com/users/hashicorp/following{/other_user}","gists_url":"https://api.github.com/users/hashicorp/gists{/gist_id}","starred_url":"https://api.github.com/users/hashicorp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hashicorp/subscriptions","organizations_url":"https://api.github.com/users/hashicorp/orgs","repos_url":"https://api.github.com/users/hashicorp/repos","events_url":"https://api.github.com/users/hashicorp/events{/privacy}","received_events_url":"https://api.github.com/users/hashicorp/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/hashicorp/nomad","description":"A Distributed, Highly Available, Datacenter-Aware Scheduler","fork":false,"url":"https://api.github.com/repos/hashicorp/nomad","forks_url":"https://api.github.com/repos/hashicorp/nomad/forks","keys_url":"https://api.github.com/repos/hashicorp/nomad/keys{/key_id}","collaborators_url":"https://api.github.com/repos/hashicorp/nomad/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/hashicorp/nomad/teams","hooks_url":"https://api.github.com/repos/hashicorp/nomad/hooks","issue_events_url":"https://api.github.com/repos/hashicorp/nomad/issues/events{/number}","events_url":"https://api.github.com/repos/hashicorp/nomad/events","assignees_url":"https://api.github.com/repos/hashicorp/nomad/assignees{/user}","branches_url":"https://api.github.com/repos/hashicorp/nomad/branches{/branch}","tags_url":"https://api.github.com/repos/hashicorp/nomad/tags","blobs_url":"https://api.github.com/repos/hashicorp/nomad/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/hashicorp/nomad/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/hashicorp/nomad/git/refs{/sha}","trees_url":"https://api.github.com/repos/hashicorp/nomad/git/trees{/sha}","statuses_url":"https://api.github.com/repos/hashicorp/nomad/statuses/{sha}","languages_url":"https://api.github.com/repos/hashicorp/nomad/languages","stargazers_url":"https://api.github.com/repos/hashicorp/nomad/stargazers","contributors_url":"https://api.github.com/repos/hashicorp/nomad/contributors","subscribers_url":"https://api.github.com/repos/hashicorp/nomad/subscribers","subscription_url":"https://api.github.com/repos/hashicorp/nomad/subscription","commits_url":"https://api.github.com/repos/hashicorp/nomad/commits{/sha}","git_commits_url":"https://api.github.com/repos/hashicorp/nomad/git/commits{/sha}","comments_url":"https://api.github.com/repos/hashicorp/nomad/comments{/number}","issue_comment_url":"https://api.github.com/repos/hashicorp/nomad/issues/comments{/number}","contents_url":"https://api.github.com/repos/hashicorp/nomad/contents/{+path}","compare_url":"https://api.github.com/repos/hashicorp/nomad/compare/{base}...{head}","merges_url":"https://api.github.com/repos/hashicorp/nomad/merges","archive_url":"https://api.github.com/repos/hashicorp/nomad/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/hashicorp/nomad/downloads","issues_url":"https://api.github.com/repos/hashicorp/nomad/issues{/number}","pulls_url":"https://api.github.com/repos/hashicorp/nomad/pulls{/number}","milestones_url":"https://api.github.com/repos/hashicorp/nomad/milestones{/number}","notifications_url":"https://api.github.com/repos/hashicorp/nomad/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/hashicorp/nomad/labels{/name}","releases_url":"https://api.github.com/repos/hashicorp/nomad/releases{/id}","deployments_url":"https://api.github.com/repos/hashicorp/nomad/deployments","created_at":"2015-06-01T10:21:00Z","updated_at":"2016-02-05T14:03:35Z","pushed_at":"2016-02-05T08:25:50Z","git_url":"git://github.com/hashicorp/nomad.git","ssh_url":"git@github.com:hashicorp/nomad.git","clone_url":"https://github.com/hashicorp/nomad.git","svn_url":"https://github.com/hashicorp/nomad","homepage":"https://www.nomadproject.io/","size":19141,"stargazers_count":1280,"watchers_count":1280,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":134,"mirror_url":null,"open_issues_count":102,"forks":134,"open_issues":102,"watchers":1280,"default_branch":"master"}},"base":{"label":"hashicorp:master","ref":"master","sha":"8701ce33cedf02da5089f945bae732302b57530f","user":{"login":"hashicorp","id":761456,"avatar_url":"https://avatars.githubusercontent.com/u/761456?v=3","gravatar_id":"","url":"https://api.github.com/users/hashicorp","html_url":"https://github.com/hashicorp","followers_url":"https://api.github.com/users/hashicorp/followers","following_url":"https://api.github.com/users/hashicorp/following{/other_user}","gists_url":"https://api.github.com/users/hashicorp/gists{/gist_id}","starred_url":"https://api.github.com/users/hashicorp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hashicorp/subscriptions","organizations_url":"https://api.github.com/users/hashicorp/orgs","repos_url":"https://api.github.com/users/hashicorp/repos","events_url":"https://api.github.com/users/hashicorp/events{/privacy}","received_events_url":"https://api.github.com/users/hashicorp/received_events","type":"Organization","site_admin":false},"repo":{"id":36653430,"name":"nomad","full_name":"hashicorp/nomad","owner":{"login":"hashicorp","id":761456,"avatar_url":"https://avatars.githubusercontent.com/u/761456?v=3","gravatar_id":"","url":"https://api.github.com/users/hashicorp","html_url":"https://github.com/hashicorp","followers_url":"https://api.github.com/users/hashicorp/followers","following_url":"https://api.github.com/users/hashicorp/following{/other_user}","gists_url":"https://api.github.com/users/hashicorp/gists{/gist_id}","starred_url":"https://api.github.com/users/hashicorp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hashicorp/subscriptions","organizations_url":"https://api.github.com/users/hashicorp/orgs","repos_url":"https://api.github.com/users/hashicorp/repos","events_url":"https://api.github.com/users/hashicorp/events{/privacy}","received_events_url":"https://api.github.com/users/hashicorp/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/hashicorp/nomad","description":"A Distributed, Highly Available, Datacenter-Aware Scheduler","fork":false,"url":"https://api.github.com/repos/hashicorp/nomad","forks_url":"https://api.github.com/repos/hashicorp/nomad/forks","keys_url":"https://api.github.com/repos/hashicorp/nomad/keys{/key_id}","collaborators_url":"https://api.github.com/repos/hashicorp/nomad/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/hashicorp/nomad/teams","hooks_url":"https://api.github.com/repos/hashicorp/nomad/hooks","issue_events_url":"https://api.github.com/repos/hashicorp/nomad/issues/events{/number}","events_url":"https://api.github.com/repos/hashicorp/nomad/events","assignees_url":"https://api.github.com/repos/hashicorp/nomad/assignees{/user}","branches_url":"https://api.github.com/repos/hashicorp/nomad/branches{/branch}","tags_url":"https://api.github.com/repos/hashicorp/nomad/tags","blobs_url":"https://api.github.com/repos/hashicorp/nomad/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/hashicorp/nomad/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/hashicorp/nomad/git/refs{/sha}","trees_url":"https://api.github.com/repos/hashicorp/nomad/git/trees{/sha}","statuses_url":"https://api.github.com/repos/hashicorp/nomad/statuses/{sha}","languages_url":"https://api.github.com/repos/hashicorp/nomad/languages","stargazers_url":"https://api.github.com/repos/hashicorp/nomad/stargazers","contributors_url":"https://api.github.com/repos/hashicorp/nomad/contributors","subscribers_url":"https://api.github.com/repos/hashicorp/nomad/subscribers","subscription_url":"https://api.github.com/repos/hashicorp/nomad/subscription","commits_url":"https://api.github.com/repos/hashicorp/nomad/commits{/sha}","git_commits_url":"https://api.github.com/repos/hashicorp/nomad/git/commits{/sha}","comments_url":"https://api.github.com/repos/hashicorp/nomad/comments{/number}","issue_comment_url":"https://api.github.com/repos/hashicorp/nomad/issues/comments{/number}","contents_url":"https://api.github.com/repos/hashicorp/nomad/contents/{+path}","compare_url":"https://api.github.com/repos/hashicorp/nomad/compare/{base}...{head}","merges_url":"https://api.github.com/repos/hashicorp/nomad/merges","archive_url":"https://api.github.com/repos/hashicorp/nomad/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/hashicorp/nomad/downloads","issues_url":"https://api.github.com/repos/hashicorp/nomad/issues{/number}","pulls_url":"https://api.github.com/repos/hashicorp/nomad/pulls{/number}","milestones_url":"https://api.github.com/repos/hashicorp/nomad/milestones{/number}","notifications_url":"https://api.github.com/repos/hashicorp/nomad/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/hashicorp/nomad/labels{/name}","releases_url":"https://api.github.com/repos/hashicorp/nomad/releases{/id}","deployments_url":"https://api.github.com/repos/hashicorp/nomad/deployments","created_at":"2015-06-01T10:21:00Z","updated_at":"2016-02-05T14:03:35Z","pushed_at":"2016-02-05T08:25:50Z","git_url":"git://github.com/hashicorp/nomad.git","ssh_url":"git@github.com:hashicorp/nomad.git","clone_url":"https://github.com/hashicorp/nomad.git","svn_url":"https://github.com/hashicorp/nomad","homepage":"https://www.nomadproject.io/","size":19141,"stargazers_count":1280,"watchers_count":1280,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":134,"mirror_url":null,"open_issues_count":102,"forks":134,"open_issues":102,"watchers":1280,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/hashicorp/nomad/pulls/759"},"html":{"href":"https://github.com/hashicorp/nomad/pull/759"},"issue":{"href":"https://api.github.com/repos/hashicorp/nomad/issues/759"},"comments":{"href":"https://api.github.com/repos/hashicorp/nomad/issues/759/comments"},"review_comments":{"href":"https://api.github.com/repos/hashicorp/nomad/pulls/759/comments"},"review_comment":{"href":"https://api.github.com/repos/hashicorp/nomad/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/hashicorp/nomad/pulls/759/commits"},"statuses":{"href":"https://api.github.com/repos/hashicorp/nomad/statuses/ab493c2fb3123998fd0904802ea993420fe5bd8b"}}}}