Skip to content

Commit ebc9ef6

Browse files
committed
update raw_exec to support artifact_source
1 parent 3fe532e commit ebc9ef6

File tree

4 files changed

+82
-8
lines changed

4 files changed

+82
-8
lines changed

client/driver/exec_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ func TestExecDriver_Start_Wait(t *testing.T) {
120120
}
121121
}
122122

123-
func TestExecDriver_Start_Artifact_Wait(t *testing.T) {
123+
func TestRawExecDriver_Start_Artifact_Wait(t *testing.T) {
124124
ctestutils.ExecCompatible(t)
125125
task := &structs.Task{
126126
Name: "sleep",

client/driver/raw_exec.go

+32-6
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,17 @@ package driver
22

33
import (
44
"fmt"
5+
"log"
56
"os"
67
"os/exec"
8+
"path"
79
"path/filepath"
810
"runtime"
911
"strconv"
1012
"strings"
1113
"time"
1214

15+
"github.com/hashicorp/go-getter"
1316
"github.com/hashicorp/nomad/client/allocdir"
1417
"github.com/hashicorp/nomad/client/config"
1518
"github.com/hashicorp/nomad/client/driver/args"
@@ -61,12 +64,6 @@ func (d *RawExecDriver) Fingerprint(cfg *config.Config, node *structs.Node) (boo
6164
}
6265

6366
func (d *RawExecDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, error) {
64-
// Get the command
65-
command, ok := task.Config["command"]
66-
if !ok || command == "" {
67-
return nil, fmt.Errorf("missing command for raw_exec driver")
68-
}
69-
7067
// Get the tasks local directory.
7168
taskName := d.DriverContext.taskName
7269
taskDir, ok := ctx.AllocDir.TaskDirs[taskName]
@@ -75,6 +72,35 @@ func (d *RawExecDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandl
7572
}
7673
taskLocal := filepath.Join(taskDir, allocdir.TaskLocal)
7774

75+
// Get the command
76+
command, ok := task.Config["command"]
77+
if !ok || command == "" {
78+
source, sok := task.Config["artifact_source"]
79+
if !sok || source == "" {
80+
return nil, fmt.Errorf("missing command or source for exec driver")
81+
}
82+
83+
// Proceed to download an artifact to be executed.
84+
// We use go-getter to support a variety of protocols, but need to change
85+
// file permissions of the resulted download to be executable
86+
destDir := filepath.Join(taskDir, allocdir.TaskLocal)
87+
88+
// Create a location to download the artifact.
89+
artifactName := path.Base(source)
90+
command = filepath.Join(destDir, artifactName)
91+
if err := getter.GetFile(command, source); err != nil {
92+
return nil, fmt.Errorf("[Err] driver.Exec: Error downloading source for Exec driver: %s", err)
93+
}
94+
95+
cmd := exec.Command("chmod", "+x", command)
96+
if err := cmd.Run(); err != nil {
97+
log.Printf("[Err] driver.Exec: Error making artifact executable: %s", err)
98+
}
99+
100+
// re-assign the command to be the local execution path
101+
command = filepath.Join(allocdir.TaskLocal, artifactName)
102+
}
103+
78104
// Get the environment variables.
79105
envVars := TaskEnvironmentVariables(ctx, task)
80106

client/driver/raw_exec_test.go

+44
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,50 @@ func TestRawExecDriver_StartOpen_Wait(t *testing.T) {
9292
}
9393
}
9494

95+
func TestRawExecDriver_StartOpen_Artifact_Source_Wait(t *testing.T) {
96+
task := &structs.Task{
97+
Name: "sleep",
98+
Config: map[string]string{
99+
"artifact_source": "https://dl.dropboxusercontent.com/u/47675/jar_thing/hi_linux_amd64",
100+
},
101+
}
102+
driverCtx := testDriverContext(task.Name)
103+
ctx := testDriverExecContext(task, driverCtx)
104+
defer ctx.AllocDir.Destroy()
105+
106+
d := NewRawExecDriver(driverCtx)
107+
handle, err := d.Start(ctx, task)
108+
if err != nil {
109+
t.Fatalf("err: %v", err)
110+
}
111+
if handle == nil {
112+
t.Fatalf("missing handle")
113+
}
114+
115+
// Attempt to open
116+
handle2, err := d.Open(ctx, handle.ID())
117+
if err != nil {
118+
t.Fatalf("err: %v", err)
119+
}
120+
if handle2 == nil {
121+
t.Fatalf("missing handle")
122+
}
123+
124+
// Task should terminate quickly
125+
select {
126+
case <-handle2.WaitCh():
127+
case <-time.After(2 * time.Second):
128+
t.Fatalf("timeout")
129+
}
130+
131+
// Check they are both tracking the same PID.
132+
pid1 := handle.(*rawExecHandle).proc.Pid
133+
pid2 := handle2.(*rawExecHandle).proc.Pid
134+
if pid1 != pid2 {
135+
t.Fatalf("tracking incorrect Pid; %v != %v", pid1, pid2)
136+
}
137+
}
138+
95139
func TestRawExecDriver_Start_Wait(t *testing.T) {
96140
task := &structs.Task{
97141
Name: "sleep",

website/source/docs/drivers/raw_exec.html.md

+5-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ As such, it should be used with extreme care and is disabled by default.
1919
The `raw_exec` driver supports the following configuration in the job spec:
2020

2121
* `command` - The command to execute. Must be provided.
22-
22+
* `artifact_source` – Source location of an executable artifact. Must be accessible
23+
from the Nomad client
2324
* `args` - The argument list to the command, space seperated. Optional.
2425

2526
## Client Requirements
@@ -35,6 +36,9 @@ options = {
3536
}
3637
```
3738

39+
You must specify either a `command` or a `artifact_source` to be executed. Any
40+
`command` is assumed to be present on the running client.
41+
3842
## Client Attributes
3943

4044
The `raw_exec` driver will set the following client attributes:

0 commit comments

Comments
 (0)