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 }