github.com/ryanslade/nomad@v0.2.4-0.20160128061903-fc95782f2089/nomad/alloc_endpoint_test.go (about)

     1  package nomad
     2  
     3  import (
     4  	"reflect"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/hashicorp/net-rpc-msgpackrpc"
     9  	"github.com/hashicorp/nomad/nomad/mock"
    10  	"github.com/hashicorp/nomad/nomad/structs"
    11  	"github.com/hashicorp/nomad/testutil"
    12  )
    13  
    14  func TestAllocEndpoint_List(t *testing.T) {
    15  	s1 := testServer(t, nil)
    16  	defer s1.Shutdown()
    17  	codec := rpcClient(t, s1)
    18  	testutil.WaitForLeader(t, s1.RPC)
    19  
    20  	// Create the register request
    21  	alloc := mock.Alloc()
    22  	state := s1.fsm.State()
    23  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc})
    24  	if err != nil {
    25  		t.Fatalf("err: %v", err)
    26  	}
    27  
    28  	// Lookup the allocations
    29  	get := &structs.AllocListRequest{
    30  		QueryOptions: structs.QueryOptions{Region: "global"},
    31  	}
    32  	var resp structs.AllocListResponse
    33  	if err := msgpackrpc.CallWithCodec(codec, "Alloc.List", get, &resp); err != nil {
    34  		t.Fatalf("err: %v", err)
    35  	}
    36  	if resp.Index != 1000 {
    37  		t.Fatalf("Bad index: %d %d", resp.Index, 1000)
    38  	}
    39  
    40  	if len(resp.Allocations) != 1 {
    41  		t.Fatalf("bad: %#v", resp.Allocations)
    42  	}
    43  	if resp.Allocations[0].ID != alloc.ID {
    44  		t.Fatalf("bad: %#v", resp.Allocations[0])
    45  	}
    46  
    47  	// Lookup the allocations by prefix
    48  	get = &structs.AllocListRequest{
    49  		QueryOptions: structs.QueryOptions{Region: "global", Prefix: alloc.ID[:4]},
    50  	}
    51  
    52  	var resp2 structs.AllocListResponse
    53  	if err := msgpackrpc.CallWithCodec(codec, "Alloc.List", get, &resp2); err != nil {
    54  		t.Fatalf("err: %v", err)
    55  	}
    56  	if resp2.Index != 1000 {
    57  		t.Fatalf("Bad index: %d %d", resp2.Index, 1000)
    58  	}
    59  
    60  	if len(resp2.Allocations) != 1 {
    61  		t.Fatalf("bad: %#v", resp2.Allocations)
    62  	}
    63  	if resp2.Allocations[0].ID != alloc.ID {
    64  		t.Fatalf("bad: %#v", resp2.Allocations[0])
    65  	}
    66  }
    67  
    68  func TestAllocEndpoint_List_Blocking(t *testing.T) {
    69  	s1 := testServer(t, nil)
    70  	defer s1.Shutdown()
    71  	state := s1.fsm.State()
    72  	codec := rpcClient(t, s1)
    73  	testutil.WaitForLeader(t, s1.RPC)
    74  
    75  	// Create the alloc
    76  	alloc := mock.Alloc()
    77  
    78  	// Upsert alloc triggers watches
    79  	time.AfterFunc(100*time.Millisecond, func() {
    80  		if err := state.UpsertAllocs(2, []*structs.Allocation{alloc}); err != nil {
    81  			t.Fatalf("err: %v", err)
    82  		}
    83  	})
    84  
    85  	req := &structs.AllocListRequest{
    86  		QueryOptions: structs.QueryOptions{
    87  			Region:        "global",
    88  			MinQueryIndex: 1,
    89  		},
    90  	}
    91  	start := time.Now()
    92  	var resp structs.AllocListResponse
    93  	if err := msgpackrpc.CallWithCodec(codec, "Alloc.List", req, &resp); err != nil {
    94  		t.Fatalf("err: %v", err)
    95  	}
    96  
    97  	if elapsed := time.Since(start); elapsed < 100*time.Millisecond {
    98  		t.Fatalf("should block (returned in %s) %#v", elapsed, resp)
    99  	}
   100  	if resp.Index != 2 {
   101  		t.Fatalf("Bad index: %d %d", resp.Index, 2)
   102  	}
   103  	if len(resp.Allocations) != 1 || resp.Allocations[0].ID != alloc.ID {
   104  		t.Fatalf("bad: %#v", resp.Allocations)
   105  	}
   106  
   107  	// Client updates trigger watches
   108  	alloc2 := mock.Alloc()
   109  	alloc2.ID = alloc.ID
   110  	alloc2.ClientStatus = structs.AllocClientStatusRunning
   111  	time.AfterFunc(100*time.Millisecond, func() {
   112  		if err := state.UpdateAllocFromClient(3, alloc2); err != nil {
   113  			t.Fatalf("err: %v", err)
   114  		}
   115  	})
   116  
   117  	req.MinQueryIndex = 2
   118  	start = time.Now()
   119  	var resp2 structs.AllocListResponse
   120  	if err := msgpackrpc.CallWithCodec(codec, "Alloc.List", req, &resp2); err != nil {
   121  		t.Fatalf("err: %v", err)
   122  	}
   123  
   124  	if elapsed := time.Since(start); elapsed < 100*time.Millisecond {
   125  		t.Fatalf("should block (returned in %s) %#v", elapsed, resp2)
   126  	}
   127  	if resp2.Index != 3 {
   128  		t.Fatalf("Bad index: %d %d", resp2.Index, 3)
   129  	}
   130  	if len(resp2.Allocations) != 1 || resp.Allocations[0].ID != alloc.ID ||
   131  		resp2.Allocations[0].ClientStatus != structs.AllocClientStatusRunning {
   132  		t.Fatalf("bad: %#v", resp2.Allocations)
   133  	}
   134  }
   135  
   136  func TestAllocEndpoint_GetAlloc(t *testing.T) {
   137  	s1 := testServer(t, nil)
   138  	defer s1.Shutdown()
   139  	codec := rpcClient(t, s1)
   140  	testutil.WaitForLeader(t, s1.RPC)
   141  
   142  	// Create the register request
   143  	alloc := mock.Alloc()
   144  	state := s1.fsm.State()
   145  	err := state.UpsertAllocs(1000, []*structs.Allocation{alloc})
   146  	if err != nil {
   147  		t.Fatalf("err: %v", err)
   148  	}
   149  
   150  	// Lookup the jobs
   151  	get := &structs.AllocSpecificRequest{
   152  		AllocID:      alloc.ID,
   153  		QueryOptions: structs.QueryOptions{Region: "global"},
   154  	}
   155  	var resp structs.SingleAllocResponse
   156  	if err := msgpackrpc.CallWithCodec(codec, "Alloc.GetAlloc", get, &resp); err != nil {
   157  		t.Fatalf("err: %v", err)
   158  	}
   159  	if resp.Index != 1000 {
   160  		t.Fatalf("Bad index: %d %d", resp.Index, 1000)
   161  	}
   162  
   163  	if !reflect.DeepEqual(alloc, resp.Alloc) {
   164  		t.Fatalf("bad: %#v", resp.Alloc)
   165  	}
   166  }
   167  
   168  func TestAllocEndpoint_GetAlloc_Blocking(t *testing.T) {
   169  	s1 := testServer(t, nil)
   170  	defer s1.Shutdown()
   171  	state := s1.fsm.State()
   172  	codec := rpcClient(t, s1)
   173  	testutil.WaitForLeader(t, s1.RPC)
   174  
   175  	// Create the allocs
   176  	alloc1 := mock.Alloc()
   177  	alloc2 := mock.Alloc()
   178  
   179  	// First create an unrelated alloc
   180  	time.AfterFunc(100*time.Millisecond, func() {
   181  		err := state.UpsertAllocs(100, []*structs.Allocation{alloc1})
   182  		if err != nil {
   183  			t.Fatalf("err: %v", err)
   184  		}
   185  	})
   186  
   187  	// Create the alloc we are watching later
   188  	time.AfterFunc(200*time.Millisecond, func() {
   189  		err := state.UpsertAllocs(200, []*structs.Allocation{alloc2})
   190  		if err != nil {
   191  			t.Fatalf("err: %v", err)
   192  		}
   193  	})
   194  
   195  	// Lookup the jobs
   196  	get := &structs.AllocSpecificRequest{
   197  		AllocID: alloc2.ID,
   198  		QueryOptions: structs.QueryOptions{
   199  			Region:        "global",
   200  			MinQueryIndex: 50,
   201  		},
   202  	}
   203  	var resp structs.SingleAllocResponse
   204  	start := time.Now()
   205  	if err := msgpackrpc.CallWithCodec(codec, "Alloc.GetAlloc", get, &resp); err != nil {
   206  		t.Fatalf("err: %v", err)
   207  	}
   208  
   209  	if elapsed := time.Since(start); elapsed < 200*time.Millisecond {
   210  		t.Fatalf("should block (returned in %s) %#v", elapsed, resp)
   211  	}
   212  	if resp.Index != 200 {
   213  		t.Fatalf("Bad index: %d %d", resp.Index, 200)
   214  	}
   215  	if resp.Alloc == nil || resp.Alloc.ID != alloc2.ID {
   216  		t.Fatalf("bad: %#v", resp.Alloc)
   217  	}
   218  }