Merge pull request #1089 from hashicorp/f-validate-driver-on-submit

Validate driver config on job register
This commit is contained in:
Alex Dadgar 2016-04-13 16:54:59 -07:00
commit 7b41cfec7b
6 changed files with 61 additions and 1 deletions

View File

@ -21,6 +21,7 @@ func assertWriteMeta(t *testing.T, wm *WriteMeta) {
func testJob() *Job {
task := NewTask("task1", "exec").
SetConfig("command", "/bin/sleep").
Require(&Resources{
CPU: 100,
MemoryMB: 256,

View File

@ -67,6 +67,7 @@ func TestHTTP_PrefixJobsList(t *testing.T) {
// Create the job
job := mock.Job()
job.ID = ids[i]
job.TaskGroups[0].Count = 1
args := structs.JobRegisterRequest{
Job: job,
WriteRequest: structs.WriteRequest{Region: "global"},

View File

@ -40,6 +40,7 @@ func testServer(
func testJob(jobID string) *api.Job {
task := api.NewTask("task1", "exec").
SetConfig("command", "/bin/sleep").
Require(&api.Resources{
MemoryMB: 256,
DiskMB: 20,

View File

@ -6,6 +6,8 @@ import (
"github.com/armon/go-metrics"
"github.com/hashicorp/go-memdb"
"github.com/hashicorp/go-multierror"
"github.com/hashicorp/nomad/client/driver"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/hashicorp/nomad/nomad/watch"
)
@ -34,6 +36,31 @@ func (j *Job) Register(args *structs.JobRegisterRequest, reply *structs.JobRegis
return err
}
// Validate the driver configurations.
var driverErrors multierror.Error
for _, tg := range args.Job.TaskGroups {
for _, task := range tg.Tasks {
d, err := driver.NewDriver(
task.Driver,
driver.NewEmptyDriverContext(),
)
if err != nil {
msg := "failed to create driver for task %q in group %q for validation: %v"
driverErrors.Errors = append(driverErrors.Errors, fmt.Errorf(msg, tg.Name, task.Name, err))
continue
}
if err := d.Validate(task.Config); err != nil {
formatted := fmt.Errorf("group %q -> task %q -> config: %v", tg.Name, task.Name, err)
driverErrors.Errors = append(driverErrors.Errors, formatted)
}
}
}
if len(driverErrors.Errors) != 0 {
return driverErrors.ErrorOrNil()
}
if args.Job.Type == structs.JobTypeCore {
return fmt.Errorf("job type cannot be core")
}

View File

@ -2,6 +2,7 @@ package nomad
import (
"reflect"
"strings"
"testing"
"time"
@ -85,6 +86,35 @@ func TestJobEndpoint_Register(t *testing.T) {
}
}
func TestJobEndpoint_Register_InvalidDriverConfig(t *testing.T) {
s1 := testServer(t, func(c *Config) {
c.NumSchedulers = 0 // Prevent automatic dequeue
})
defer s1.Shutdown()
codec := rpcClient(t, s1)
testutil.WaitForLeader(t, s1.RPC)
// Create the register request with a job containing an invalid driver
// config
job := mock.Job()
job.TaskGroups[0].Tasks[0].Config["foo"] = 1
req := &structs.JobRegisterRequest{
Job: job,
WriteRequest: structs.WriteRequest{Region: "global"},
}
// Fetch the response
var resp structs.JobRegisterResponse
err := msgpackrpc.CallWithCodec(codec, "Job.Register", req, &resp)
if err == nil {
t.Fatalf("expected a validation error")
}
if !strings.Contains(err.Error(), "-> config:") {
t.Fatalf("expected a driver config validation error but got: %v", err)
}
}
func TestJobEndpoint_Register_Existing(t *testing.T) {
s1 := testServer(t, func(c *Config) {
c.NumSchedulers = 0 // Prevent automatic dequeue

View File

@ -10,4 +10,4 @@ go build -o $TEMPDIR/nomad || exit 1
# Run the tests
echo "--> Running tests"
go list ./... | grep -v '/vendor/' | sudo -E PATH=$TEMPDIR:$PATH xargs -n1 go test -cover -timeout=300s
go list ./... | grep -v '/vendor/' | sudo -E PATH=$TEMPDIR:$PATH xargs -n1 go test -cover -timeout=360s