github.com/dkerwin/nomad@v0.3.3-0.20160525181927-74554135514b/api/jobs_test.go (about)

     1  package api
     2  
     3  import (
     4  	"reflect"
     5  	"sort"
     6  	"strings"
     7  	"testing"
     8  
     9  	"github.com/hashicorp/nomad/testutil"
    10  )
    11  
    12  func TestJobs_Register(t *testing.T) {
    13  	c, s := makeClient(t, nil, nil)
    14  	defer s.Stop()
    15  	jobs := c.Jobs()
    16  
    17  	// Listing jobs before registering returns nothing
    18  	resp, qm, err := jobs.List(nil)
    19  	if err != nil {
    20  		t.Fatalf("err: %s", err)
    21  	}
    22  	if qm.LastIndex != 0 {
    23  		t.Fatalf("bad index: %d", qm.LastIndex)
    24  	}
    25  	if n := len(resp); n != 0 {
    26  		t.Fatalf("expected 0 jobs, got: %d", n)
    27  	}
    28  
    29  	// Create a job and attempt to register it
    30  	job := testJob()
    31  	eval, wm, err := jobs.Register(job, nil)
    32  	if err != nil {
    33  		t.Fatalf("err: %s", err)
    34  	}
    35  	if eval == "" {
    36  		t.Fatalf("missing eval id")
    37  	}
    38  	assertWriteMeta(t, wm)
    39  
    40  	// Query the jobs back out again
    41  	resp, qm, err = jobs.List(nil)
    42  	if err != nil {
    43  		t.Fatalf("err: %s", err)
    44  	}
    45  	assertQueryMeta(t, qm)
    46  
    47  	// Check that we got the expected response
    48  	if len(resp) != 1 || resp[0].ID != job.ID {
    49  		t.Fatalf("bad: %#v", resp[0])
    50  	}
    51  }
    52  
    53  func TestJobs_Info(t *testing.T) {
    54  	c, s := makeClient(t, nil, nil)
    55  	defer s.Stop()
    56  	jobs := c.Jobs()
    57  
    58  	// Trying to retrieve a job by ID before it exists
    59  	// returns an error
    60  	_, _, err := jobs.Info("job1", nil)
    61  	if err == nil || !strings.Contains(err.Error(), "not found") {
    62  		t.Fatalf("expected not found error, got: %#v", err)
    63  	}
    64  
    65  	// Register the job
    66  	job := testJob()
    67  	_, wm, err := jobs.Register(job, nil)
    68  	if err != nil {
    69  		t.Fatalf("err: %s", err)
    70  	}
    71  	assertWriteMeta(t, wm)
    72  
    73  	// Query the job again and ensure it exists
    74  	result, qm, err := jobs.Info("job1", nil)
    75  	if err != nil {
    76  		t.Fatalf("err: %s", err)
    77  	}
    78  	assertQueryMeta(t, qm)
    79  
    80  	// Check that the result is what we expect
    81  	if result == nil || result.ID != job.ID {
    82  		t.Fatalf("expect: %#v, got: %#v", job, result)
    83  	}
    84  }
    85  
    86  func TestJobs_PrefixList(t *testing.T) {
    87  	c, s := makeClient(t, nil, nil)
    88  	defer s.Stop()
    89  	jobs := c.Jobs()
    90  
    91  	// Listing when nothing exists returns empty
    92  	results, qm, err := jobs.PrefixList("dummy")
    93  	if err != nil {
    94  		t.Fatalf("err: %s", err)
    95  	}
    96  	if qm.LastIndex != 0 {
    97  		t.Fatalf("bad index: %d", qm.LastIndex)
    98  	}
    99  	if n := len(results); n != 0 {
   100  		t.Fatalf("expected 0 jobs, got: %d", n)
   101  	}
   102  
   103  	// Register the job
   104  	job := testJob()
   105  	_, wm, err := jobs.Register(job, nil)
   106  	if err != nil {
   107  		t.Fatalf("err: %s", err)
   108  	}
   109  	assertWriteMeta(t, wm)
   110  
   111  	// Query the job again and ensure it exists
   112  	// Listing when nothing exists returns empty
   113  	results, qm, err = jobs.PrefixList(job.ID[:1])
   114  	if err != nil {
   115  		t.Fatalf("err: %s", err)
   116  	}
   117  
   118  	// Check if we have the right list
   119  	if len(results) != 1 || results[0].ID != job.ID {
   120  		t.Fatalf("bad: %#v", results)
   121  	}
   122  }
   123  
   124  func TestJobs_List(t *testing.T) {
   125  	c, s := makeClient(t, nil, nil)
   126  	defer s.Stop()
   127  	jobs := c.Jobs()
   128  
   129  	// Listing when nothing exists returns empty
   130  	results, qm, err := jobs.List(nil)
   131  	if err != nil {
   132  		t.Fatalf("err: %s", err)
   133  	}
   134  	if qm.LastIndex != 0 {
   135  		t.Fatalf("bad index: %d", qm.LastIndex)
   136  	}
   137  	if n := len(results); n != 0 {
   138  		t.Fatalf("expected 0 jobs, got: %d", n)
   139  	}
   140  
   141  	// Register the job
   142  	job := testJob()
   143  	_, wm, err := jobs.Register(job, nil)
   144  	if err != nil {
   145  		t.Fatalf("err: %s", err)
   146  	}
   147  	assertWriteMeta(t, wm)
   148  
   149  	// Query the job again and ensure it exists
   150  	// Listing when nothing exists returns empty
   151  	results, qm, err = jobs.List(nil)
   152  	if err != nil {
   153  		t.Fatalf("err: %s", err)
   154  	}
   155  
   156  	// Check if we have the right list
   157  	if len(results) != 1 || results[0].ID != job.ID {
   158  		t.Fatalf("bad: %#v", results)
   159  	}
   160  }
   161  
   162  func TestJobs_Allocations(t *testing.T) {
   163  	c, s := makeClient(t, nil, nil)
   164  	defer s.Stop()
   165  	jobs := c.Jobs()
   166  
   167  	// Looking up by a non-existent job returns nothing
   168  	allocs, qm, err := jobs.Allocations("job1", nil)
   169  	if err != nil {
   170  		t.Fatalf("err: %s", err)
   171  	}
   172  	if qm.LastIndex != 0 {
   173  		t.Fatalf("bad index: %d", qm.LastIndex)
   174  	}
   175  	if n := len(allocs); n != 0 {
   176  		t.Fatalf("expected 0 allocs, got: %d", n)
   177  	}
   178  
   179  	// TODO: do something here to create some allocations for
   180  	// an existing job, lookup again.
   181  }
   182  
   183  func TestJobs_Evaluations(t *testing.T) {
   184  	c, s := makeClient(t, nil, nil)
   185  	defer s.Stop()
   186  	jobs := c.Jobs()
   187  
   188  	// Looking up by a non-existent job ID returns nothing
   189  	evals, qm, err := jobs.Evaluations("job1", nil)
   190  	if err != nil {
   191  		t.Fatalf("err: %s", err)
   192  	}
   193  	if qm.LastIndex != 0 {
   194  		t.Fatalf("bad index: %d", qm.LastIndex)
   195  	}
   196  	if n := len(evals); n != 0 {
   197  		t.Fatalf("expected 0 evals, got: %d", n)
   198  	}
   199  
   200  	// Insert a job. This also creates an evaluation so we should
   201  	// be able to query that out after.
   202  	job := testJob()
   203  	evalID, wm, err := jobs.Register(job, nil)
   204  	if err != nil {
   205  		t.Fatalf("err: %s", err)
   206  	}
   207  	assertWriteMeta(t, wm)
   208  
   209  	// Look up the evaluations again.
   210  	evals, qm, err = jobs.Evaluations("job1", nil)
   211  	if err != nil {
   212  		t.Fatalf("err: %s", err)
   213  	}
   214  	assertQueryMeta(t, qm)
   215  
   216  	// Check that we got the evals back
   217  	if n := len(evals); n == 0 || evals[0].ID != evalID {
   218  		t.Fatalf("expected 1 eval (%s), got: %#v", evalID, evals)
   219  	}
   220  }
   221  
   222  func TestJobs_Deregister(t *testing.T) {
   223  	c, s := makeClient(t, nil, nil)
   224  	defer s.Stop()
   225  	jobs := c.Jobs()
   226  
   227  	// Register a new job
   228  	job := testJob()
   229  	_, wm, err := jobs.Register(job, nil)
   230  	if err != nil {
   231  		t.Fatalf("err: %s", err)
   232  	}
   233  	assertWriteMeta(t, wm)
   234  
   235  	// Attempting delete on non-existing job returns an error
   236  	if _, _, err = jobs.Deregister("nope", nil); err != nil {
   237  		t.Fatalf("unexpected error deregistering job: %v", err)
   238  
   239  	}
   240  
   241  	// Deleting an existing job works
   242  	evalID, wm3, err := jobs.Deregister("job1", nil)
   243  	if err != nil {
   244  		t.Fatalf("err: %s", err)
   245  	}
   246  	assertWriteMeta(t, wm3)
   247  	if evalID == "" {
   248  		t.Fatalf("missing eval ID")
   249  	}
   250  
   251  	// Check that the job is really gone
   252  	result, qm, err := jobs.List(nil)
   253  	if err != nil {
   254  		t.Fatalf("err: %s", err)
   255  	}
   256  	assertQueryMeta(t, qm)
   257  	if n := len(result); n != 0 {
   258  		t.Fatalf("expected 0 jobs, got: %d", n)
   259  	}
   260  }
   261  
   262  func TestJobs_ForceEvaluate(t *testing.T) {
   263  	c, s := makeClient(t, nil, nil)
   264  	defer s.Stop()
   265  	jobs := c.Jobs()
   266  
   267  	// Force-eval on a non-existent job fails
   268  	_, _, err := jobs.ForceEvaluate("job1", nil)
   269  	if err == nil || !strings.Contains(err.Error(), "not found") {
   270  		t.Fatalf("expected not found error, got: %#v", err)
   271  	}
   272  
   273  	// Create a new job
   274  	_, wm, err := jobs.Register(testJob(), nil)
   275  	if err != nil {
   276  		t.Fatalf("err: %s", err)
   277  	}
   278  	assertWriteMeta(t, wm)
   279  
   280  	// Try force-eval again
   281  	evalID, wm, err := jobs.ForceEvaluate("job1", nil)
   282  	if err != nil {
   283  		t.Fatalf("err: %s", err)
   284  	}
   285  	assertWriteMeta(t, wm)
   286  
   287  	// Retrieve the evals and see if we get a matching one
   288  	evals, qm, err := jobs.Evaluations("job1", nil)
   289  	if err != nil {
   290  		t.Fatalf("err: %s", err)
   291  	}
   292  	assertQueryMeta(t, qm)
   293  	for _, eval := range evals {
   294  		if eval.ID == evalID {
   295  			return
   296  		}
   297  	}
   298  	t.Fatalf("evaluation %q missing", evalID)
   299  }
   300  
   301  func TestJobs_PeriodicForce(t *testing.T) {
   302  	c, s := makeClient(t, nil, nil)
   303  	defer s.Stop()
   304  	jobs := c.Jobs()
   305  
   306  	// Force-eval on a non-existent job fails
   307  	_, _, err := jobs.PeriodicForce("job1", nil)
   308  	if err == nil || !strings.Contains(err.Error(), "not found") {
   309  		t.Fatalf("expected not found error, got: %#v", err)
   310  	}
   311  
   312  	// Create a new job
   313  	job := testPeriodicJob()
   314  	_, _, err = jobs.Register(job, nil)
   315  	if err != nil {
   316  		t.Fatalf("err: %s", err)
   317  	}
   318  
   319  	testutil.WaitForResult(func() (bool, error) {
   320  		out, _, err := jobs.Info(job.ID, nil)
   321  		if err != nil || out == nil || out.ID != job.ID {
   322  			return false, err
   323  		}
   324  		return true, nil
   325  	}, func(err error) {
   326  		t.Fatalf("err: %s", err)
   327  	})
   328  
   329  	// Try force again
   330  	evalID, wm, err := jobs.PeriodicForce(job.ID, nil)
   331  	if err != nil {
   332  		t.Fatalf("err: %s", err)
   333  	}
   334  	assertWriteMeta(t, wm)
   335  
   336  	if evalID == "" {
   337  		t.Fatalf("empty evalID")
   338  	}
   339  
   340  	// Retrieve the eval
   341  	evals := c.Evaluations()
   342  	eval, qm, err := evals.Info(evalID, nil)
   343  	if err != nil {
   344  		t.Fatalf("err: %s", err)
   345  	}
   346  	assertQueryMeta(t, qm)
   347  	if eval.ID == evalID {
   348  		return
   349  	}
   350  	t.Fatalf("evaluation %q missing", evalID)
   351  }
   352  
   353  func TestJobs_Plan(t *testing.T) {
   354  	c, s := makeClient(t, nil, nil)
   355  	defer s.Stop()
   356  	jobs := c.Jobs()
   357  
   358  	// Create a job and attempt to register it
   359  	job := testJob()
   360  	eval, wm, err := jobs.Register(job, nil)
   361  	if err != nil {
   362  		t.Fatalf("err: %s", err)
   363  	}
   364  	if eval == "" {
   365  		t.Fatalf("missing eval id")
   366  	}
   367  	assertWriteMeta(t, wm)
   368  
   369  	// Check that passing a nil job fails
   370  	if _, _, err := jobs.Plan(nil, true, nil); err == nil {
   371  		t.Fatalf("expect an error when job isn't provided")
   372  	}
   373  
   374  	// Make a plan request
   375  	planResp, wm, err := jobs.Plan(job, true, nil)
   376  	if err != nil {
   377  		t.Fatalf("err: %s", err)
   378  	}
   379  	if planResp == nil {
   380  		t.Fatalf("nil response")
   381  	}
   382  
   383  	if planResp.JobModifyIndex == 0 {
   384  		t.Fatalf("bad JobModifyIndex value: %#v", planResp)
   385  	}
   386  	if planResp.Diff == nil {
   387  		t.Fatalf("got nil diff: %#v", planResp)
   388  	}
   389  	if planResp.Annotations == nil {
   390  		t.Fatalf("got nil annotations: %#v", planResp)
   391  	}
   392  	// Can make this assertion because there are no clients.
   393  	if len(planResp.CreatedEvals) == 0 {
   394  		t.Fatalf("got no CreatedEvals: %#v", planResp)
   395  	}
   396  
   397  	// Make a plan request w/o the diff
   398  	planResp, wm, err = jobs.Plan(job, false, nil)
   399  	if err != nil {
   400  		t.Fatalf("err: %s", err)
   401  	}
   402  	assertWriteMeta(t, wm)
   403  
   404  	if planResp == nil {
   405  		t.Fatalf("nil response")
   406  	}
   407  
   408  	if planResp.JobModifyIndex == 0 {
   409  		t.Fatalf("bad JobModifyIndex value: %d", planResp.JobModifyIndex)
   410  	}
   411  	if planResp.Diff != nil {
   412  		t.Fatalf("got non-nil diff: %#v", planResp)
   413  	}
   414  	if planResp.Annotations == nil {
   415  		t.Fatalf("got nil annotations: %#v", planResp)
   416  	}
   417  	// Can make this assertion because there are no clients.
   418  	if len(planResp.CreatedEvals) == 0 {
   419  		t.Fatalf("got no CreatedEvals: %#v", planResp)
   420  	}
   421  }
   422  
   423  func TestJobs_NewBatchJob(t *testing.T) {
   424  	job := NewBatchJob("job1", "myjob", "region1", 5)
   425  	expect := &Job{
   426  		Region:   "region1",
   427  		ID:       "job1",
   428  		Name:     "myjob",
   429  		Type:     JobTypeBatch,
   430  		Priority: 5,
   431  	}
   432  	if !reflect.DeepEqual(job, expect) {
   433  		t.Fatalf("expect: %#v, got: %#v", expect, job)
   434  	}
   435  }
   436  
   437  func TestJobs_NewServiceJob(t *testing.T) {
   438  	job := NewServiceJob("job1", "myjob", "region1", 5)
   439  	expect := &Job{
   440  		Region:   "region1",
   441  		ID:       "job1",
   442  		Name:     "myjob",
   443  		Type:     JobTypeService,
   444  		Priority: 5,
   445  	}
   446  	if !reflect.DeepEqual(job, expect) {
   447  		t.Fatalf("expect: %#v, got: %#v", expect, job)
   448  	}
   449  }
   450  
   451  func TestJobs_SetMeta(t *testing.T) {
   452  	job := &Job{Meta: nil}
   453  
   454  	// Initializes a nil map
   455  	out := job.SetMeta("foo", "bar")
   456  	if job.Meta == nil {
   457  		t.Fatalf("should initialize metadata")
   458  	}
   459  
   460  	// Check that the job was returned
   461  	if job != out {
   462  		t.Fatalf("expect: %#v, got: %#v", job, out)
   463  	}
   464  
   465  	// Setting another pair is additive
   466  	job.SetMeta("baz", "zip")
   467  	expect := map[string]string{"foo": "bar", "baz": "zip"}
   468  	if !reflect.DeepEqual(job.Meta, expect) {
   469  		t.Fatalf("expect: %#v, got: %#v", expect, job.Meta)
   470  	}
   471  }
   472  
   473  func TestJobs_Constrain(t *testing.T) {
   474  	job := &Job{Constraints: nil}
   475  
   476  	// Create and add a constraint
   477  	out := job.Constrain(NewConstraint("kernel.name", "=", "darwin"))
   478  	if n := len(job.Constraints); n != 1 {
   479  		t.Fatalf("expected 1 constraint, got: %d", n)
   480  	}
   481  
   482  	// Check that the job was returned
   483  	if job != out {
   484  		t.Fatalf("expect: %#v, got: %#v", job, out)
   485  	}
   486  
   487  	// Adding another constraint preserves the original
   488  	job.Constrain(NewConstraint("memory.totalbytes", ">=", "128000000"))
   489  	expect := []*Constraint{
   490  		&Constraint{
   491  			LTarget: "kernel.name",
   492  			RTarget: "darwin",
   493  			Operand: "=",
   494  		},
   495  		&Constraint{
   496  			LTarget: "memory.totalbytes",
   497  			RTarget: "128000000",
   498  			Operand: ">=",
   499  		},
   500  	}
   501  	if !reflect.DeepEqual(job.Constraints, expect) {
   502  		t.Fatalf("expect: %#v, got: %#v", expect, job.Constraints)
   503  	}
   504  }
   505  
   506  func TestJobs_Sort(t *testing.T) {
   507  	jobs := []*JobListStub{
   508  		&JobListStub{ID: "job2"},
   509  		&JobListStub{ID: "job0"},
   510  		&JobListStub{ID: "job1"},
   511  	}
   512  	sort.Sort(JobIDSort(jobs))
   513  
   514  	expect := []*JobListStub{
   515  		&JobListStub{ID: "job0"},
   516  		&JobListStub{ID: "job1"},
   517  		&JobListStub{ID: "job2"},
   518  	}
   519  	if !reflect.DeepEqual(jobs, expect) {
   520  		t.Fatalf("\n\n%#v\n\n%#v", jobs, expect)
   521  	}
   522  }