mirror of
https://github.com/kemko/nomad.git
synced 2026-01-04 09:25:46 +03:00
Plan api
This commit is contained in:
88
api/jobs.go
88
api/jobs.go
@@ -1,6 +1,7 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"time"
|
||||
)
|
||||
@@ -116,6 +117,24 @@ func (j *Jobs) PeriodicForce(jobID string, q *WriteOptions) (string, *WriteMeta,
|
||||
return resp.EvalID, wm, nil
|
||||
}
|
||||
|
||||
func (j *Jobs) Plan(job *Job, diff bool, q *WriteOptions) (*JobPlanResponse, *WriteMeta, error) {
|
||||
if job == nil {
|
||||
return nil, nil, fmt.Errorf("must pass non-nil job")
|
||||
}
|
||||
|
||||
var resp JobPlanResponse
|
||||
req := &JobPlanRequest{
|
||||
Job: job,
|
||||
Diff: diff,
|
||||
}
|
||||
wm, err := j.client.write("/v1/job/"+job.ID+"/plan", req, &resp, q)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return &resp, wm, nil
|
||||
}
|
||||
|
||||
// periodicForceResponse is used to deserialize a force response
|
||||
type periodicForceResponse struct {
|
||||
EvalID string
|
||||
@@ -256,3 +275,72 @@ type registerJobResponse struct {
|
||||
type deregisterJobResponse struct {
|
||||
EvalID string
|
||||
}
|
||||
|
||||
type JobPlanRequest struct {
|
||||
Job *Job
|
||||
Diff bool
|
||||
}
|
||||
|
||||
type JobPlanResponse struct {
|
||||
Cas uint64
|
||||
CreatedEvals []*Evaluation
|
||||
Diff *JobDiff
|
||||
SchedulerOutput *SchedulerOutput `json:"Plan"`
|
||||
}
|
||||
|
||||
type JobDiff struct {
|
||||
Type string
|
||||
ID string
|
||||
Fields []*FieldDiff
|
||||
Objects []*ObjectDiff
|
||||
TaskGroups []*TaskGroupDiff
|
||||
}
|
||||
|
||||
type TaskGroupDiff struct {
|
||||
Type string
|
||||
Name string
|
||||
Fields []*FieldDiff
|
||||
Objects []*ObjectDiff
|
||||
Tasks []*TaskDiff
|
||||
Updates map[string]uint64
|
||||
}
|
||||
|
||||
type TaskDiff struct {
|
||||
Type string
|
||||
Name string
|
||||
Fields []*FieldDiff
|
||||
Objects []*ObjectDiff
|
||||
Annotations []string
|
||||
}
|
||||
|
||||
type FieldDiff struct {
|
||||
Type string
|
||||
Name string
|
||||
Old, New string
|
||||
Annotations []string
|
||||
}
|
||||
|
||||
type ObjectDiff struct {
|
||||
Type string
|
||||
Name string
|
||||
Fields []*FieldDiff
|
||||
Objects []*ObjectDiff
|
||||
}
|
||||
|
||||
type SchedulerOutput struct {
|
||||
FailedAllocs []*Allocations
|
||||
Annotations *PlanAnnotations
|
||||
}
|
||||
|
||||
type PlanAnnotations struct {
|
||||
DesiredTGUpdates map[string]*DesiredUpdates
|
||||
}
|
||||
|
||||
type DesiredUpdates struct {
|
||||
Ignore uint64
|
||||
Place uint64
|
||||
Migrate uint64
|
||||
Stop uint64
|
||||
InPlaceUpdate uint64
|
||||
DestructiveUpdate uint64
|
||||
}
|
||||
|
||||
@@ -350,6 +350,76 @@ func TestJobs_PeriodicForce(t *testing.T) {
|
||||
t.Fatalf("evaluation %q missing", evalID)
|
||||
}
|
||||
|
||||
func TestJobs_Plan(t *testing.T) {
|
||||
c, s := makeClient(t, nil, nil)
|
||||
defer s.Stop()
|
||||
jobs := c.Jobs()
|
||||
|
||||
// Create a job and attempt to register it
|
||||
job := testJob()
|
||||
eval, wm, err := jobs.Register(job, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
if eval == "" {
|
||||
t.Fatalf("missing eval id")
|
||||
}
|
||||
assertWriteMeta(t, wm)
|
||||
|
||||
// Check that passing a nil job fails
|
||||
if _, _, err := jobs.Plan(nil, true, nil); err == nil {
|
||||
t.Fatalf("expect an error when job isn't provided")
|
||||
}
|
||||
|
||||
// Make a plan request
|
||||
planResp, wm, err := jobs.Plan(job, true, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
if planResp == nil {
|
||||
t.Fatalf("nil response")
|
||||
}
|
||||
|
||||
if planResp.Cas == 0 {
|
||||
t.Fatalf("bad Cas value: %#v", planResp)
|
||||
}
|
||||
if planResp.Diff == nil {
|
||||
t.Fatalf("got nil diff: %#v", planResp)
|
||||
}
|
||||
if planResp.SchedulerOutput == nil {
|
||||
t.Fatalf("got nil scheduler output: %#v", planResp)
|
||||
}
|
||||
// Can make this assertion because there are no clients.
|
||||
if len(planResp.CreatedEvals) == 0 {
|
||||
t.Fatalf("got no CreatedEvals: %#v", planResp)
|
||||
}
|
||||
|
||||
// Make a plan request w/o the diff
|
||||
planResp, wm, err = jobs.Plan(job, false, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
assertWriteMeta(t, wm)
|
||||
|
||||
if planResp == nil {
|
||||
t.Fatalf("nil response")
|
||||
}
|
||||
|
||||
if planResp.Cas == 0 {
|
||||
t.Fatalf("bad Cas value: %d", planResp.Cas)
|
||||
}
|
||||
if planResp.Diff != nil {
|
||||
t.Fatalf("got non-nil diff: %#v", planResp)
|
||||
}
|
||||
if planResp.SchedulerOutput == nil {
|
||||
t.Fatalf("got nil scheduler output: %#v", planResp)
|
||||
}
|
||||
// Can make this assertion because there are no clients.
|
||||
if len(planResp.CreatedEvals) == 0 {
|
||||
t.Fatalf("got no CreatedEvals: %#v", planResp)
|
||||
}
|
||||
}
|
||||
|
||||
func TestJobs_NewBatchJob(t *testing.T) {
|
||||
job := NewBatchJob("job1", "myjob", "region1", 5)
|
||||
expect := &Job{
|
||||
|
||||
@@ -99,6 +99,7 @@ func (s *HTTPServer) jobPlan(resp http.ResponseWriter, req *http.Request,
|
||||
if err := s.agent.RPC("Job.Plan", &args, &out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
setIndex(resp, out.Index)
|
||||
return out, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -474,6 +474,7 @@ func (j *Job) Plan(args *structs.JobPlanRequest, reply *structs.JobPlanResponse)
|
||||
reply.Cas = index
|
||||
reply.Plan = planner.Plan
|
||||
reply.CreatedEvals = planner.CreatedEvals
|
||||
reply.Index = index
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -416,7 +416,7 @@ type JobPlanResponse struct {
|
||||
// causes an in-place update or create/destroy
|
||||
Diff *JobDiff
|
||||
|
||||
QueryMeta
|
||||
WriteMeta
|
||||
}
|
||||
|
||||
// SingleAllocResponse is used to return a single allocation
|
||||
|
||||
Reference in New Issue
Block a user