diff --git a/client/driver/rkt.go b/client/driver/rkt.go index 641ff29d9..8bebbaf91 100644 --- a/client/driver/rkt.go +++ b/client/driver/rkt.go @@ -35,7 +35,7 @@ type RktDriver struct { // rktHandle is returned from Start/Open as a handle to the PID type rktHandle struct { proc *os.Process - name string + image string logger *log.Logger waitCh chan error doneCh chan struct{} @@ -44,8 +44,8 @@ type rktHandle struct { // rktPID is a struct to map the pid running the process to the vm image on // disk type rktPID struct { - Pid int - Name string + Pid int + Image string } // NewRktDriver is used to create a new exec driver @@ -82,14 +82,9 @@ func (d *RktDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool, e // Run an existing Rkt image. func (d *RktDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, error) { // Validate that the config is valid. - trust_prefix, ok := task.Config["trust_prefix"] - if !ok || trust_prefix == "" { - return nil, fmt.Errorf("Missing trust prefix for rkt") - } - - name, ok := task.Config["name"] - if !ok || name == "" { - return nil, fmt.Errorf("Missing ACI name for rkt") + img, ok := task.Config["image"] + if !ok || img == "" { + return nil, fmt.Errorf("Missing ACI image for rkt") } // Get the tasks local directory. @@ -101,15 +96,18 @@ func (d *RktDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, e taskLocal := filepath.Join(taskDir, allocdir.TaskLocal) // Add the given trust prefix - var outBuf, errBuf bytes.Buffer - cmd := exec.Command("rkt", "trust", fmt.Sprintf("--prefix=%s", trust_prefix)) - cmd.Stdout = &outBuf - cmd.Stderr = &errBuf - if err := cmd.Run(); err != nil { - return nil, fmt.Errorf("Error running rkt: %s\n\nOutput: %s\n\nError: %s", - err, outBuf.String(), errBuf.String()) + trust_prefix, trust_cmd := task.Config["trust_prefix"] + if trust_cmd { + var outBuf, errBuf bytes.Buffer + cmd := exec.Command("rkt", "trust", fmt.Sprintf("--prefix=%s", trust_prefix)) + cmd.Stdout = &outBuf + cmd.Stderr = &errBuf + if err := cmd.Run(); err != nil { + return nil, fmt.Errorf("Error running rkt trust: %s\n\nOutput: %s\n\nError: %s", + err, outBuf.String(), errBuf.String()) + } + d.logger.Printf("[DEBUG] driver.rkt: added trust prefix: %q", trust_prefix) } - d.logger.Printf("[DEBUG] driver.rkt: added trust prefix: %q", trust_prefix) // Build the command. var cmd_args []string @@ -120,11 +118,16 @@ func (d *RktDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, e cmd_args = append(cmd_args, fmt.Sprintf("--set-env=%v=%v", k, v)) } + // Disble signature verification if the trust command was not run. + if !trust_cmd { + cmd_args = append(cmd_args, "--insecure-skip-verify") + } + // Append the run command. - cmd_args = append(cmd_args, "run", "--mds-register=false", name) + cmd_args = append(cmd_args, "run", "--mds-register=false", img) // Check if the user has overriden the exec command. - if exec_cmd, ok := task.Config["exec"]; ok { + if exec_cmd, ok := task.Config["command"]; ok { cmd_args = append(cmd_args, fmt.Sprintf("--exec=%v", exec_cmd)) } @@ -159,19 +162,18 @@ func (d *RktDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle, e return nil, fmt.Errorf("Error opening file to redirect stderr: %v", err) } - cmd = exec.Command("rkt", cmd_args...) + cmd := exec.Command("rkt", cmd_args...) cmd.Stdout = stdo cmd.Stderr = stde if err := cmd.Start(); err != nil { - return nil, fmt.Errorf("Error running rkt: %s\n\nOutput: %s\n\nError: %s", - err, outBuf.String(), errBuf.String()) + return nil, fmt.Errorf("Error running rkt: %v", err) } - d.logger.Printf("[DEBUG] driver.rkt: started ACI %q with: %v", name, cmd.Args) + d.logger.Printf("[DEBUG] driver.rkt: started ACI %q with: %v", img, cmd.Args) h := &rktHandle{ proc: cmd.Process, - name: name, + image: img, logger: d.logger, doneCh: make(chan struct{}), waitCh: make(chan error, 1), @@ -197,7 +199,7 @@ func (d *RktDriver) Open(ctx *ExecContext, handleID string) (DriverHandle, error // Return a driver handle h := &rktHandle{ proc: proc, - name: qpid.Name, + image: qpid.Image, logger: d.logger, doneCh: make(chan struct{}), waitCh: make(chan error, 1), @@ -210,8 +212,8 @@ func (d *RktDriver) Open(ctx *ExecContext, handleID string) (DriverHandle, error func (h *rktHandle) ID() string { // Return a handle to the PID pid := &rktPID{ - Pid: h.proc.Pid, - Name: h.name, + Pid: h.proc.Pid, + Image: h.image, } data, err := json.Marshal(pid) if err != nil { diff --git a/client/driver/rkt_test.go b/client/driver/rkt_test.go index 9b7c10136..94d45cdcc 100644 --- a/client/driver/rkt_test.go +++ b/client/driver/rkt_test.go @@ -18,13 +18,13 @@ import ( func TestRktDriver_Handle(t *testing.T) { h := &rktHandle{ proc: &os.Process{Pid: 123}, - name: "foo", + image: "foo", doneCh: make(chan struct{}), waitCh: make(chan error, 1), } actual := h.ID() - expected := `Rkt:{"Pid":123,"Name":"foo"}` + expected := `Rkt:{"Pid":123,"Image":"foo"}` if actual != expected { t.Errorf("Expected `%s`, found `%s`", expected, actual) } @@ -62,8 +62,8 @@ func TestRktDriver_Start(t *testing.T) { Name: "etcd", Config: map[string]string{ "trust_prefix": "coreos.com/etcd", - "name": "coreos.com/etcd:v2.0.4", - "exec": "/etcd", + "image": "coreos.com/etcd:v2.0.4", + "command": "/etcd", }, } @@ -101,8 +101,8 @@ func TestRktDriver_Start_Wait(t *testing.T) { Name: "etcd", Config: map[string]string{ "trust_prefix": "coreos.com/etcd", - "name": "coreos.com/etcd:v2.0.4", - "exec": "/etcd", + "image": "coreos.com/etcd:v2.0.4", + "command": "/etcd", "args": "--version", }, } @@ -137,14 +137,55 @@ func TestRktDriver_Start_Wait(t *testing.T) { } } +func TestRktDriver_Start_Wait_Skip_Trust(t *testing.T) { + ctestutils.RktCompatible(t) + task := &structs.Task{ + Name: "etcd", + Config: map[string]string{ + "image": "coreos.com/etcd:v2.0.4", + "command": "/etcd", + "args": "--version", + }, + } + + driverCtx := testDriverContext(task.Name) + ctx := testDriverExecContext(task, driverCtx) + d := NewRktDriver(driverCtx) + defer ctx.AllocDir.Destroy() + + handle, err := d.Start(ctx, task) + if err != nil { + t.Fatalf("err: %v", err) + } + if handle == nil { + t.Fatalf("missing handle") + } + defer handle.Kill() + + // Update should be a no-op + err = handle.Update(task) + if err != nil { + t.Fatalf("err: %v", err) + } + + select { + case err := <-handle.WaitCh(): + if err != nil { + t.Fatalf("err: %v", err) + } + case <-time.After(5 * time.Second): + t.Fatalf("timeout") + } +} + func TestRktDriver_Start_Wait_Logs(t *testing.T) { ctestutils.RktCompatible(t) task := &structs.Task{ Name: "etcd", Config: map[string]string{ "trust_prefix": "coreos.com/etcd", - "name": "coreos.com/etcd:v2.0.4", - "exec": "/etcd", + "image": "coreos.com/etcd:v2.0.4", + "command": "/etcd", "args": "--version", }, } diff --git a/website/source/docs/drivers/rkt.html.md b/website/source/docs/drivers/rkt.html.md index c837c154c..7db5707d8 100644 --- a/website/source/docs/drivers/rkt.html.md +++ b/website/source/docs/drivers/rkt.html.md @@ -18,10 +18,12 @@ containers. The `Rkt` driver supports the following configuration in the job spec: -* `trust_prefix` - **(Required)** The trust prefix to be passed to rkt. Must be reachable from -the box running the nomad agent. -* `name` - **(Required)** Fully qualified name of an image to run using rkt -* `exec` - **(Optional**) A command to execute on the ACI +* `trust_prefix` - **(Optional)** The trust prefix to be passed to rkt. Must be reachable from +the box running the nomad agent. If not specified, the image is run without +verifying the image signature. +* `image` - **(Required)** The image to run which may be specified by name, +hash, ACI address or docker registry. +* `command` - **(Optional**) A command to execute on the ACI. * `args` - **(Optional**) A string of args to pass into the image. ## Client Requirements