github.com/hspak/nomad@v0.7.2-0.20180309000617-bc4ae22a39a5/api/nodes_test.go (about) 1 package api 2 3 import ( 4 "fmt" 5 "reflect" 6 "sort" 7 "strings" 8 "testing" 9 "time" 10 11 "github.com/hashicorp/nomad/helper/uuid" 12 "github.com/hashicorp/nomad/nomad/structs" 13 "github.com/hashicorp/nomad/testutil" 14 "github.com/stretchr/testify/require" 15 ) 16 17 func TestNodes_List(t *testing.T) { 18 t.Parallel() 19 c, s := makeClient(t, nil, func(c *testutil.TestServerConfig) { 20 c.DevMode = true 21 }) 22 defer s.Stop() 23 nodes := c.Nodes() 24 25 var qm *QueryMeta 26 var out []*NodeListStub 27 var err error 28 29 testutil.WaitForResult(func() (bool, error) { 30 out, qm, err = nodes.List(nil) 31 if err != nil { 32 return false, err 33 } 34 if n := len(out); n != 1 { 35 return false, fmt.Errorf("expected 1 node, got: %d", n) 36 } 37 return true, nil 38 }, func(err error) { 39 t.Fatalf("err: %s", err) 40 }) 41 42 // Check that we got valid QueryMeta. 43 assertQueryMeta(t, qm) 44 } 45 46 func TestNodes_PrefixList(t *testing.T) { 47 t.Parallel() 48 c, s := makeClient(t, nil, func(c *testutil.TestServerConfig) { 49 c.DevMode = true 50 }) 51 defer s.Stop() 52 nodes := c.Nodes() 53 54 var qm *QueryMeta 55 var out []*NodeListStub 56 var err error 57 58 // Get the node ID 59 var nodeID string 60 testutil.WaitForResult(func() (bool, error) { 61 out, _, err := nodes.List(nil) 62 if err != nil { 63 return false, err 64 } 65 if n := len(out); n != 1 { 66 return false, fmt.Errorf("expected 1 node, got: %d", n) 67 } 68 nodeID = out[0].ID 69 return true, nil 70 }, func(err error) { 71 t.Fatalf("err: %s", err) 72 }) 73 74 // Find node based on four character prefix 75 out, qm, err = nodes.PrefixList(nodeID[:4]) 76 if err != nil { 77 t.Fatalf("err: %s", err) 78 } 79 if n := len(out); n != 1 { 80 t.Fatalf("expected 1 node, got: %d ", n) 81 } 82 83 // Check that we got valid QueryMeta. 84 assertQueryMeta(t, qm) 85 } 86 87 func TestNodes_Info(t *testing.T) { 88 t.Parallel() 89 startTime := time.Now().Unix() 90 c, s := makeClient(t, nil, func(c *testutil.TestServerConfig) { 91 c.DevMode = true 92 }) 93 defer s.Stop() 94 nodes := c.Nodes() 95 96 // Retrieving a non-existent node returns error 97 _, _, err := nodes.Info("12345678-abcd-efab-cdef-123456789abc", nil) 98 if err == nil || !strings.Contains(err.Error(), "not found") { 99 t.Fatalf("expected not found error, got: %#v", err) 100 } 101 102 // Get the node ID 103 var nodeID, dc string 104 testutil.WaitForResult(func() (bool, error) { 105 out, _, err := nodes.List(nil) 106 if err != nil { 107 return false, err 108 } 109 if n := len(out); n != 1 { 110 return false, fmt.Errorf("expected 1 node, got: %d", n) 111 } 112 nodeID = out[0].ID 113 dc = out[0].Datacenter 114 return true, nil 115 }, func(err error) { 116 t.Fatalf("err: %s", err) 117 }) 118 119 // Querying for existing nodes returns properly 120 result, qm, err := nodes.Info(nodeID, nil) 121 if err != nil { 122 t.Fatalf("err: %s", err) 123 } 124 assertQueryMeta(t, qm) 125 126 // Check that the result is what we expect 127 if result.ID != nodeID || result.Datacenter != dc { 128 t.Fatalf("expected %s (%s), got: %s (%s)", 129 nodeID, dc, 130 result.ID, result.Datacenter) 131 } 132 133 // Check that the StatusUpdatedAt field is being populated correctly 134 if result.StatusUpdatedAt < startTime { 135 t.Fatalf("start time: %v, status updated: %v", startTime, result.StatusUpdatedAt) 136 } 137 } 138 139 func TestNodes_ToggleDrain(t *testing.T) { 140 t.Parallel() 141 c, s := makeClient(t, nil, func(c *testutil.TestServerConfig) { 142 c.DevMode = true 143 }) 144 defer s.Stop() 145 nodes := c.Nodes() 146 147 // Wait for node registration and get the ID 148 var nodeID string 149 testutil.WaitForResult(func() (bool, error) { 150 out, _, err := nodes.List(nil) 151 if err != nil { 152 return false, err 153 } 154 if n := len(out); n != 1 { 155 return false, fmt.Errorf("expected 1 node, got: %d", n) 156 } 157 nodeID = out[0].ID 158 return true, nil 159 }, func(err error) { 160 t.Fatalf("err: %s", err) 161 }) 162 163 // Check for drain mode 164 out, _, err := nodes.Info(nodeID, nil) 165 if err != nil { 166 t.Fatalf("err: %s", err) 167 } 168 if out.Drain { 169 t.Fatalf("drain mode should be off") 170 } 171 172 // Toggle it on 173 wm, err := nodes.ToggleDrain(nodeID, true, nil) 174 if err != nil { 175 t.Fatalf("err: %s", err) 176 } 177 assertWriteMeta(t, wm) 178 179 // Check again 180 out, _, err = nodes.Info(nodeID, nil) 181 if err != nil { 182 t.Fatalf("err: %s", err) 183 } 184 if !out.Drain { 185 t.Fatalf("drain mode should be on") 186 } 187 188 // Toggle off again 189 wm, err = nodes.ToggleDrain(nodeID, false, nil) 190 if err != nil { 191 t.Fatalf("err: %s", err) 192 } 193 assertWriteMeta(t, wm) 194 195 // Check again 196 out, _, err = nodes.Info(nodeID, nil) 197 if err != nil { 198 t.Fatalf("err: %s", err) 199 } 200 if out.Drain { 201 t.Fatalf("drain mode should be off") 202 } 203 } 204 205 func TestNodes_Allocations(t *testing.T) { 206 t.Parallel() 207 c, s := makeClient(t, nil, nil) 208 defer s.Stop() 209 nodes := c.Nodes() 210 211 // Looking up by a non-existent node returns nothing. We 212 // don't check the index here because it's possible the node 213 // has already registered, in which case we will get a non- 214 // zero result anyways. 215 allocs, _, err := nodes.Allocations("nope", nil) 216 if err != nil { 217 t.Fatalf("err: %s", err) 218 } 219 if n := len(allocs); n != 0 { 220 t.Fatalf("expected 0 allocs, got: %d", n) 221 } 222 } 223 224 func TestNodes_ForceEvaluate(t *testing.T) { 225 t.Parallel() 226 c, s := makeClient(t, nil, func(c *testutil.TestServerConfig) { 227 c.DevMode = true 228 }) 229 defer s.Stop() 230 nodes := c.Nodes() 231 232 // Force-eval on a non-existent node fails 233 _, _, err := nodes.ForceEvaluate("12345678-abcd-efab-cdef-123456789abc", nil) 234 if err == nil || !strings.Contains(err.Error(), "not found") { 235 t.Fatalf("expected not found error, got: %#v", err) 236 } 237 238 // Wait for node registration and get the ID 239 var nodeID string 240 testutil.WaitForResult(func() (bool, error) { 241 out, _, err := nodes.List(nil) 242 if err != nil { 243 return false, err 244 } 245 if n := len(out); n != 1 { 246 return false, fmt.Errorf("expected 1 node, got: %d", n) 247 } 248 nodeID = out[0].ID 249 return true, nil 250 }, func(err error) { 251 t.Fatalf("err: %s", err) 252 }) 253 254 // Try force-eval again. We don't check the WriteMeta because 255 // there are no allocations to process, so we would get an index 256 // of zero. Same goes for the eval ID. 257 _, _, err = nodes.ForceEvaluate(nodeID, nil) 258 if err != nil { 259 t.Fatalf("err: %s", err) 260 } 261 } 262 263 func TestNodes_Sort(t *testing.T) { 264 t.Parallel() 265 nodes := []*NodeListStub{ 266 {CreateIndex: 2}, 267 {CreateIndex: 1}, 268 {CreateIndex: 5}, 269 } 270 sort.Sort(NodeIndexSort(nodes)) 271 272 expect := []*NodeListStub{ 273 {CreateIndex: 5}, 274 {CreateIndex: 2}, 275 {CreateIndex: 1}, 276 } 277 if !reflect.DeepEqual(nodes, expect) { 278 t.Fatalf("\n\n%#v\n\n%#v", nodes, expect) 279 } 280 } 281 282 func TestNodes_GC(t *testing.T) { 283 t.Parallel() 284 require := require.New(t) 285 c, s := makeClient(t, nil, nil) 286 defer s.Stop() 287 nodes := c.Nodes() 288 289 err := nodes.GC(uuid.Generate(), nil) 290 require.NotNil(err) 291 require.True(structs.IsErrUnknownNode(err)) 292 } 293 294 func TestNodes_GcAlloc(t *testing.T) { 295 t.Parallel() 296 require := require.New(t) 297 c, s := makeClient(t, nil, nil) 298 defer s.Stop() 299 nodes := c.Nodes() 300 301 err := nodes.GcAlloc(uuid.Generate(), nil) 302 require.NotNil(err) 303 require.True(structs.IsErrUnknownAllocation(err)) 304 }