github.com/quite/nomad@v0.8.6/nomad/structs/network_test.go (about) 1 package structs 2 3 import ( 4 "net" 5 "reflect" 6 "testing" 7 ) 8 9 func TestNetworkIndex_Overcommitted(t *testing.T) { 10 idx := NewNetworkIndex() 11 12 // Consume some network 13 reserved := &NetworkResource{ 14 Device: "eth0", 15 IP: "192.168.0.100", 16 MBits: 505, 17 ReservedPorts: []Port{{"one", 8000}, {"two", 9000}}, 18 } 19 collide := idx.AddReserved(reserved) 20 if collide { 21 t.Fatalf("bad") 22 } 23 if !idx.Overcommitted() { 24 t.Fatalf("have no resources") 25 } 26 27 // Add resources 28 n := &Node{ 29 Resources: &Resources{ 30 Networks: []*NetworkResource{ 31 { 32 Device: "eth0", 33 CIDR: "192.168.0.100/32", 34 MBits: 1000, 35 }, 36 }, 37 }, 38 } 39 idx.SetNode(n) 40 if idx.Overcommitted() { 41 t.Fatalf("have resources") 42 } 43 44 // Double up our usage 45 idx.AddReserved(reserved) 46 if !idx.Overcommitted() { 47 t.Fatalf("should be overcommitted") 48 } 49 } 50 51 func TestNetworkIndex_SetNode(t *testing.T) { 52 idx := NewNetworkIndex() 53 n := &Node{ 54 Resources: &Resources{ 55 Networks: []*NetworkResource{ 56 { 57 Device: "eth0", 58 CIDR: "192.168.0.100/32", 59 MBits: 1000, 60 }, 61 }, 62 }, 63 Reserved: &Resources{ 64 Networks: []*NetworkResource{ 65 { 66 Device: "eth0", 67 IP: "192.168.0.100", 68 ReservedPorts: []Port{{"ssh", 22}}, 69 MBits: 1, 70 }, 71 }, 72 }, 73 } 74 collide := idx.SetNode(n) 75 if collide { 76 t.Fatalf("bad") 77 } 78 79 if len(idx.AvailNetworks) != 1 { 80 t.Fatalf("Bad") 81 } 82 if idx.AvailBandwidth["eth0"] != 1000 { 83 t.Fatalf("Bad") 84 } 85 if idx.UsedBandwidth["eth0"] != 1 { 86 t.Fatalf("Bad") 87 } 88 if !idx.UsedPorts["192.168.0.100"].Check(22) { 89 t.Fatalf("Bad") 90 } 91 } 92 93 func TestNetworkIndex_AddAllocs(t *testing.T) { 94 idx := NewNetworkIndex() 95 allocs := []*Allocation{ 96 { 97 TaskResources: map[string]*Resources{ 98 "web": { 99 Networks: []*NetworkResource{ 100 { 101 Device: "eth0", 102 IP: "192.168.0.100", 103 MBits: 20, 104 ReservedPorts: []Port{{"one", 8000}, {"two", 9000}}, 105 }, 106 }, 107 }, 108 }, 109 }, 110 { 111 TaskResources: map[string]*Resources{ 112 "api": { 113 Networks: []*NetworkResource{ 114 { 115 Device: "eth0", 116 IP: "192.168.0.100", 117 MBits: 50, 118 ReservedPorts: []Port{{"one", 10000}}, 119 }, 120 }, 121 }, 122 }, 123 }, 124 } 125 collide := idx.AddAllocs(allocs) 126 if collide { 127 t.Fatalf("bad") 128 } 129 130 if idx.UsedBandwidth["eth0"] != 70 { 131 t.Fatalf("Bad") 132 } 133 if !idx.UsedPorts["192.168.0.100"].Check(8000) { 134 t.Fatalf("Bad") 135 } 136 if !idx.UsedPorts["192.168.0.100"].Check(9000) { 137 t.Fatalf("Bad") 138 } 139 if !idx.UsedPorts["192.168.0.100"].Check(10000) { 140 t.Fatalf("Bad") 141 } 142 } 143 144 func TestNetworkIndex_AddReserved(t *testing.T) { 145 idx := NewNetworkIndex() 146 147 reserved := &NetworkResource{ 148 Device: "eth0", 149 IP: "192.168.0.100", 150 MBits: 20, 151 ReservedPorts: []Port{{"one", 8000}, {"two", 9000}}, 152 } 153 collide := idx.AddReserved(reserved) 154 if collide { 155 t.Fatalf("bad") 156 } 157 158 if idx.UsedBandwidth["eth0"] != 20 { 159 t.Fatalf("Bad") 160 } 161 if !idx.UsedPorts["192.168.0.100"].Check(8000) { 162 t.Fatalf("Bad") 163 } 164 if !idx.UsedPorts["192.168.0.100"].Check(9000) { 165 t.Fatalf("Bad") 166 } 167 168 // Try to reserve the same network 169 collide = idx.AddReserved(reserved) 170 if !collide { 171 t.Fatalf("bad") 172 } 173 } 174 175 func TestNetworkIndex_yieldIP(t *testing.T) { 176 idx := NewNetworkIndex() 177 n := &Node{ 178 Resources: &Resources{ 179 Networks: []*NetworkResource{ 180 { 181 Device: "eth0", 182 CIDR: "192.168.0.100/30", 183 MBits: 1000, 184 }, 185 }, 186 }, 187 Reserved: &Resources{ 188 Networks: []*NetworkResource{ 189 { 190 Device: "eth0", 191 IP: "192.168.0.100", 192 ReservedPorts: []Port{{"ssh", 22}}, 193 MBits: 1, 194 }, 195 }, 196 }, 197 } 198 idx.SetNode(n) 199 200 var out []string 201 idx.yieldIP(func(n *NetworkResource, ip net.IP) (stop bool) { 202 out = append(out, ip.String()) 203 return 204 }) 205 206 expect := []string{"192.168.0.100", "192.168.0.101", 207 "192.168.0.102", "192.168.0.103"} 208 if !reflect.DeepEqual(out, expect) { 209 t.Fatalf("bad: %v", out) 210 } 211 } 212 213 func TestNetworkIndex_AssignNetwork(t *testing.T) { 214 idx := NewNetworkIndex() 215 n := &Node{ 216 Resources: &Resources{ 217 Networks: []*NetworkResource{ 218 { 219 Device: "eth0", 220 CIDR: "192.168.0.100/30", 221 MBits: 1000, 222 }, 223 }, 224 }, 225 Reserved: &Resources{ 226 Networks: []*NetworkResource{ 227 { 228 Device: "eth0", 229 IP: "192.168.0.100", 230 ReservedPorts: []Port{{"ssh", 22}}, 231 MBits: 1, 232 }, 233 }, 234 }, 235 } 236 idx.SetNode(n) 237 238 allocs := []*Allocation{ 239 { 240 TaskResources: map[string]*Resources{ 241 "web": { 242 Networks: []*NetworkResource{ 243 { 244 Device: "eth0", 245 IP: "192.168.0.100", 246 MBits: 20, 247 ReservedPorts: []Port{{"one", 8000}, {"two", 9000}}, 248 }, 249 }, 250 }, 251 }, 252 }, 253 { 254 TaskResources: map[string]*Resources{ 255 "api": { 256 Networks: []*NetworkResource{ 257 { 258 Device: "eth0", 259 IP: "192.168.0.100", 260 MBits: 50, 261 ReservedPorts: []Port{{"main", 10000}}, 262 }, 263 }, 264 }, 265 }, 266 }, 267 } 268 idx.AddAllocs(allocs) 269 270 // Ask for a reserved port 271 ask := &NetworkResource{ 272 ReservedPorts: []Port{{"main", 8000}}, 273 } 274 offer, err := idx.AssignNetwork(ask) 275 if err != nil { 276 t.Fatalf("err: %v", err) 277 } 278 if offer == nil { 279 t.Fatalf("bad") 280 } 281 if offer.IP != "192.168.0.101" { 282 t.Fatalf("bad: %#v", offer) 283 } 284 rp := Port{"main", 8000} 285 if len(offer.ReservedPorts) != 1 || offer.ReservedPorts[0] != rp { 286 t.Fatalf("bad: %#v", offer) 287 } 288 289 // Ask for dynamic ports 290 ask = &NetworkResource{ 291 DynamicPorts: []Port{{"http", 0}, {"https", 0}, {"admin", 0}}, 292 } 293 offer, err = idx.AssignNetwork(ask) 294 if err != nil { 295 t.Fatalf("err: %v", err) 296 } 297 if offer == nil { 298 t.Fatalf("bad") 299 } 300 if offer.IP != "192.168.0.100" { 301 t.Fatalf("bad: %#v", offer) 302 } 303 if len(offer.DynamicPorts) != 3 { 304 t.Fatalf("There should be three dynamic ports") 305 } 306 for _, port := range offer.DynamicPorts { 307 if port.Value == 0 { 308 t.Fatalf("Dynamic Port: %v should have been assigned a host port", port.Label) 309 } 310 } 311 312 // Ask for reserved + dynamic ports 313 ask = &NetworkResource{ 314 ReservedPorts: []Port{{"main", 2345}}, 315 DynamicPorts: []Port{{"http", 0}, {"https", 0}, {"admin", 0}}, 316 } 317 offer, err = idx.AssignNetwork(ask) 318 if err != nil { 319 t.Fatalf("err: %v", err) 320 } 321 if offer == nil { 322 t.Fatalf("bad") 323 } 324 if offer.IP != "192.168.0.100" { 325 t.Fatalf("bad: %#v", offer) 326 } 327 328 rp = Port{"main", 2345} 329 if len(offer.ReservedPorts) != 1 || offer.ReservedPorts[0] != rp { 330 t.Fatalf("bad: %#v", offer) 331 } 332 333 // Ask for too much bandwidth 334 ask = &NetworkResource{ 335 MBits: 1000, 336 } 337 offer, err = idx.AssignNetwork(ask) 338 if err.Error() != "bandwidth exceeded" { 339 t.Fatalf("err: %v", err) 340 } 341 if offer != nil { 342 t.Fatalf("bad") 343 } 344 } 345 346 // This test ensures that even with a small domain of available ports we are 347 // able to make a dynamic port allocation. 348 func TestNetworkIndex_AssignNetwork_Dynamic_Contention(t *testing.T) { 349 350 // Create a node that only has one free port 351 idx := NewNetworkIndex() 352 n := &Node{ 353 Resources: &Resources{ 354 Networks: []*NetworkResource{ 355 { 356 Device: "eth0", 357 CIDR: "192.168.0.100/32", 358 MBits: 1000, 359 }, 360 }, 361 }, 362 Reserved: &Resources{ 363 Networks: []*NetworkResource{ 364 { 365 Device: "eth0", 366 IP: "192.168.0.100", 367 MBits: 1, 368 }, 369 }, 370 }, 371 } 372 for i := MinDynamicPort; i < MaxDynamicPort; i++ { 373 n.Reserved.Networks[0].ReservedPorts = append(n.Reserved.Networks[0].ReservedPorts, Port{Value: i}) 374 } 375 376 idx.SetNode(n) 377 378 // Ask for dynamic ports 379 ask := &NetworkResource{ 380 DynamicPorts: []Port{{"http", 0}}, 381 } 382 offer, err := idx.AssignNetwork(ask) 383 if err != nil { 384 t.Fatalf("err: %v", err) 385 } 386 if offer == nil { 387 t.Fatalf("bad") 388 } 389 if offer.IP != "192.168.0.100" { 390 t.Fatalf("bad: %#v", offer) 391 } 392 if len(offer.DynamicPorts) != 1 { 393 t.Fatalf("There should be three dynamic ports") 394 } 395 if p := offer.DynamicPorts[0].Value; p != MaxDynamicPort { 396 t.Fatalf("Dynamic Port: should have been assigned %d; got %d", p, MaxDynamicPort) 397 } 398 } 399 400 func TestIntContains(t *testing.T) { 401 l := []int{1, 2, 10, 20} 402 if isPortReserved(l, 50) { 403 t.Fatalf("bad") 404 } 405 if !isPortReserved(l, 20) { 406 t.Fatalf("bad") 407 } 408 if !isPortReserved(l, 1) { 409 t.Fatalf("bad") 410 } 411 }