From c2cb2cc11fece4a1fdd5a37f516b36fc53af64e0 Mon Sep 17 00:00:00 2001 From: Alex Dadgar Date: Sun, 18 Dec 2016 16:32:14 -0800 Subject: [PATCH] Fix test and prevent job with payload from being submitted --- client/driver/driver_test.go | 1 + command/agent/job_endpoint_test.go | 1 + nomad/job_endpoint.go | 4 ++++ nomad/job_endpoint_test.go | 37 ++++++++++++++++++++++++++++++ nomad/structs/structs.go | 4 ++-- 5 files changed, 45 insertions(+), 2 deletions(-) diff --git a/client/driver/driver_test.go b/client/driver/driver_test.go index 6ca271301..740e78e67 100644 --- a/client/driver/driver_test.go +++ b/client/driver/driver_test.go @@ -118,6 +118,7 @@ func TestDriver_GetTaskEnv(t *testing.T) { } alloc := mock.Alloc() + alloc.Job.TaskGroups[0].Tasks[0] = task alloc.Name = "Bar" env, err := GetTaskEnv(nil, nil, task, alloc, "") if err != nil { diff --git a/command/agent/job_endpoint_test.go b/command/agent/job_endpoint_test.go index bbd845f7e..5ef1af572 100644 --- a/command/agent/job_endpoint_test.go +++ b/command/agent/job_endpoint_test.go @@ -584,6 +584,7 @@ func TestHTTP_JobDispatch(t *testing.T) { httpTest(t, nil, func(s *TestServer) { // Create the constructor job job := mock.Job() + job.Type = structs.JobTypeBatch job.Constructor = &structs.ConstructorConfig{} args := structs.JobRegisterRequest{ diff --git a/nomad/job_endpoint.go b/nomad/job_endpoint.go index b97bd14a2..3db0489d5 100644 --- a/nomad/job_endpoint.go +++ b/nomad/job_endpoint.go @@ -773,6 +773,10 @@ func validateJob(job *structs.Job) error { multierror.Append(validationErrors, fmt.Errorf("job type cannot be core")) } + if len(job.Payload) != 0 { + multierror.Append(validationErrors, fmt.Errorf("job can't be submitted with a payload, only dispatched")) + } + return validationErrors.ErrorOrNil() } diff --git a/nomad/job_endpoint_test.go b/nomad/job_endpoint_test.go index 17cbc3211..ed8f1443a 100644 --- a/nomad/job_endpoint_test.go +++ b/nomad/job_endpoint_test.go @@ -116,6 +116,35 @@ func TestJobEndpoint_Register_InvalidDriverConfig(t *testing.T) { } } +func TestJobEndpoint_Register_Payload(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.Payload = []byte{0x1} + 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(), "payload") { + t.Fatalf("expected a payload error but got: %v", err) + } +} + func TestJobEndpoint_Register_Existing(t *testing.T) { s1 := testServer(t, func(c *Config) { c.NumSchedulers = 0 // Prevent automatic dequeue @@ -259,6 +288,7 @@ func TestJobEndpoint_Register_Constructor(t *testing.T) { // Create the register request for a constructor job. job := mock.Job() + job.Type = structs.JobTypeBatch job.Constructor = &structs.ConstructorConfig{} req := &structs.JobRegisterRequest{ Job: job, @@ -766,6 +796,7 @@ func TestJobEndpoint_Evaluate_Constructor(t *testing.T) { // Create the register request job := mock.Job() + job.Type = structs.JobTypeBatch job.Constructor = &structs.ConstructorConfig{} req := &structs.JobRegisterRequest{ Job: job, @@ -983,6 +1014,7 @@ func TestJobEndpoint_Deregister_Constructor(t *testing.T) { // Create the register request job := mock.Job() + job.Type = structs.JobTypeBatch job.Constructor = &structs.ConstructorConfig{} reg := &structs.JobRegisterRequest{ Job: job, @@ -1860,28 +1892,33 @@ func TestJobEndpoint_Dispatch(t *testing.T) { // No requirements d1 := mock.Job() + d1.Type = structs.JobTypeBatch d1.Constructor = &structs.ConstructorConfig{} // Require input data d2 := mock.Job() + d2.Type = structs.JobTypeBatch d2.Constructor = &structs.ConstructorConfig{ Payload: structs.DispatchPayloadRequired, } // Disallow input data d3 := mock.Job() + d3.Type = structs.JobTypeBatch d3.Constructor = &structs.ConstructorConfig{ Payload: structs.DispatchPayloadForbidden, } // Require meta d4 := mock.Job() + d4.Type = structs.JobTypeBatch d4.Constructor = &structs.ConstructorConfig{ MetaRequired: []string{"foo", "bar"}, } // Optional meta d5 := mock.Job() + d5.Type = structs.JobTypeBatch d5.Constructor = &structs.ConstructorConfig{ MetaOptional: []string{"foo", "bar"}, } diff --git a/nomad/structs/structs.go b/nomad/structs/structs.go index facc49e33..0ba3e2b50 100644 --- a/nomad/structs/structs.go +++ b/nomad/structs/structs.go @@ -2477,7 +2477,7 @@ func (t *Task) Validate(ephemeralDisk *EphemeralDisk) error { // Validate the dispatch input block if there if t.DispatchInput != nil { if err := t.DispatchInput.Validate(); err != nil { - mErr.Errors = append(mErr.Errors, err) + mErr.Errors = append(mErr.Errors, fmt.Errorf("Dispatch Input validation failed: %v", err)) } } @@ -3006,7 +3006,7 @@ func (ta *TaskArtifact) Validate() error { if err != nil { mErr.Errors = append(mErr.Errors, fmt.Errorf("invalid destination path: %v", err)) } else if escaped { - mErr.Errors = append(mErr.Errors, fmt.Errorf("destination escapes task's directory")) + mErr.Errors = append(mErr.Errors, fmt.Errorf("destination escapes allocation directory")) } // Verify the checksum