github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/network/address_test.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package network_test 5 6 import ( 7 "net" 8 9 jc "github.com/juju/testing/checkers" 10 gc "gopkg.in/check.v1" 11 12 "github.com/juju/juju/network" 13 "github.com/juju/juju/testing" 14 ) 15 16 type AddressSuite struct { 17 testing.BaseSuite 18 } 19 20 var _ = gc.Suite(&AddressSuite{}) 21 22 func (s *AddressSuite) TestNewScopedAddressIPv4(c *gc.C) { 23 type test struct { 24 value string 25 scope network.Scope 26 expectedScope network.Scope 27 } 28 29 tests := []test{{ 30 value: "127.0.0.1", 31 scope: network.ScopeUnknown, 32 expectedScope: network.ScopeMachineLocal, 33 }, { 34 value: "127.0.0.1", 35 scope: network.ScopePublic, 36 expectedScope: network.ScopePublic, // don't second guess != Unknown 37 }, { 38 value: "10.0.3.1", 39 scope: network.ScopeUnknown, 40 expectedScope: network.ScopeCloudLocal, 41 }, { 42 value: "172.16.15.14", 43 scope: network.ScopeUnknown, 44 expectedScope: network.ScopeCloudLocal, 45 }, { 46 value: "192.168.0.1", 47 scope: network.ScopeUnknown, 48 expectedScope: network.ScopeCloudLocal, 49 }, { 50 value: "169.254.1.1", 51 scope: network.ScopeUnknown, 52 expectedScope: network.ScopeLinkLocal, 53 }, { 54 value: "8.8.8.8", 55 scope: network.ScopeUnknown, 56 expectedScope: network.ScopePublic, 57 }} 58 59 for i, t := range tests { 60 c.Logf("test %d: %s %s", i, t.value, t.scope) 61 addr := network.NewScopedAddress(t.value, t.scope) 62 c.Check(addr.Value, gc.Equals, t.value) 63 c.Check(addr.Type, gc.Equals, network.IPv4Address) 64 c.Check(addr.Scope, gc.Equals, t.expectedScope) 65 } 66 } 67 68 func (s *AddressSuite) TestNewScopedAddressIPv6(c *gc.C) { 69 // Examples below taken from 70 // http://en.wikipedia.org/wiki/IPv6_address 71 testAddresses := []struct { 72 value string 73 scope network.Scope 74 }{ 75 // IPv6 loopback address 76 {"::1", network.ScopeMachineLocal}, 77 // used documentation examples 78 {"2001:db8::1", network.ScopePublic}, 79 // link-local 80 {"fe80::1", network.ScopeLinkLocal}, 81 // unique local address (ULA) - first group 82 {"fc00::1", network.ScopeCloudLocal}, 83 // unique local address (ULA) - second group 84 {"fd00::1", network.ScopeCloudLocal}, 85 // IPv4-mapped IPv6 address 86 {"::ffff:0:0:1", network.ScopePublic}, 87 // IPv4-translated IPv6 address (SIIT) 88 {"::ffff:0:0:0:1", network.ScopePublic}, 89 // "well-known" prefix for IPv4/IPv6 auto translation 90 {"64:ff9b::1", network.ScopePublic}, 91 // used for 6to4 addressing 92 {"2002::1", network.ScopePublic}, 93 // used for Teredo tunneling 94 {"2001::1", network.ScopePublic}, 95 // used for IPv6 benchmarking 96 {"2001:2::1", network.ScopePublic}, 97 // used for cryptographic hash identifiers 98 {"2001:10::1", network.ScopePublic}, 99 // interface-local multicast (all nodes) 100 {"ff01::1", network.ScopeLinkLocal}, 101 // link-local multicast (all nodes) 102 {"ff02::1", network.ScopeLinkLocal}, 103 // interface-local multicast (all routers) 104 {"ff01::2", network.ScopeLinkLocal}, 105 // link-local multicast (all routers) 106 {"ff02::2", network.ScopeLinkLocal}, 107 } 108 for i, test := range testAddresses { 109 c.Logf("test %d: %q -> %q", i, test.value, test.scope) 110 addr := network.NewScopedAddress(test.value, network.ScopeUnknown) 111 c.Check(addr.Value, gc.Equals, test.value) 112 c.Check(addr.Type, gc.Equals, network.IPv6Address) 113 c.Check(addr.Scope, gc.Equals, test.scope) 114 } 115 } 116 117 func (s *AddressSuite) TestNewAddressIPv4(c *gc.C) { 118 value := "0.1.2.3" 119 addr1 := network.NewScopedAddress(value, network.ScopeUnknown) 120 addr2 := network.NewAddress(value) 121 addr3 := network.NewScopedAddress(value, network.ScopeLinkLocal) 122 // NewAddress behaves exactly like NewScopedAddress with ScopeUnknown 123 c.Assert(addr1, jc.DeepEquals, addr2) 124 c.Assert(addr2.Scope, gc.Equals, network.ScopePublic) // derived from value 125 c.Assert(addr2.Value, gc.Equals, value) 126 c.Assert(addr2.Type, gc.Equals, network.IPv4Address) 127 c.Assert(addr2.Scope, gc.Not(gc.Equals), addr3.Scope) // different scope 128 c.Assert(addr3.Scope, gc.Equals, network.ScopeLinkLocal) 129 } 130 131 func (s *AddressSuite) TestNewAddressIPv6(c *gc.C) { 132 value := "2001:db8::1" 133 addr1 := network.NewScopedAddress(value, network.ScopeUnknown) 134 addr2 := network.NewAddress(value) 135 addr3 := network.NewScopedAddress(value, network.ScopeLinkLocal) 136 // NewAddress behaves exactly like NewScopedAddress with ScopeUnknown 137 c.Assert(addr1, jc.DeepEquals, addr2) 138 c.Assert(addr2.Scope, gc.Equals, network.ScopePublic) // derived from value 139 c.Assert(addr2.Value, gc.Equals, value) 140 c.Assert(addr2.Type, gc.Equals, network.IPv6Address) 141 c.Assert(addr2.Scope, gc.Not(gc.Equals), addr3.Scope) // different scope 142 c.Assert(addr3.Scope, gc.Equals, network.ScopeLinkLocal) 143 } 144 145 func (s *AddressSuite) TestNewAddresses(c *gc.C) { 146 testAddresses := []struct { 147 values []string 148 addrType network.AddressType 149 scope network.Scope 150 }{{ 151 []string{"127.0.0.1", "127.0.1.2"}, 152 network.IPv4Address, 153 network.ScopeMachineLocal, 154 }, { 155 []string{"::1"}, 156 network.IPv6Address, 157 network.ScopeMachineLocal, 158 }, { 159 []string{"192.168.1.1", "192.168.178.255", "10.5.1.1", "172.16.1.1"}, 160 network.IPv4Address, 161 network.ScopeCloudLocal, 162 }, { 163 []string{"fc00::1", "fd00::2"}, 164 network.IPv6Address, 165 network.ScopeCloudLocal, 166 }, { 167 []string{"8.8.8.8", "8.8.4.4"}, 168 network.IPv4Address, 169 network.ScopePublic, 170 }, { 171 []string{"2001:db8::1", "64:ff9b::1", "2002::1"}, 172 network.IPv6Address, 173 network.ScopePublic, 174 }, { 175 []string{"169.254.1.23", "169.254.1.1"}, 176 network.IPv4Address, 177 network.ScopeLinkLocal, 178 }, { 179 []string{"ff01::2", "ff01::1"}, 180 network.IPv6Address, 181 network.ScopeLinkLocal, 182 }, { 183 []string{"example.com", "example.org"}, 184 network.HostName, 185 network.ScopeUnknown, 186 }} 187 188 for i, test := range testAddresses { 189 c.Logf("test %d: %v -> %q", i, test.values, test.scope) 190 addresses := network.NewAddresses(test.values...) 191 c.Check(addresses, gc.HasLen, len(test.values)) 192 for j, addr := range addresses { 193 c.Check(addr.Value, gc.Equals, test.values[j]) 194 c.Check(addr.Type, gc.Equals, test.addrType) 195 c.Check(addr.Scope, gc.Equals, test.scope) 196 } 197 } 198 } 199 200 func (s *AddressSuite) TestNewScopedAddressHostname(c *gc.C) { 201 addr := network.NewScopedAddress("localhost", network.ScopeUnknown) 202 c.Check(addr.Value, gc.Equals, "localhost") 203 c.Check(addr.Type, gc.Equals, network.HostName) 204 c.Check(addr.Scope, gc.Equals, network.ScopeUnknown) 205 addr = network.NewScopedAddress("example.com", network.ScopeUnknown) 206 c.Check(addr.Value, gc.Equals, "example.com") 207 c.Check(addr.Type, gc.Equals, network.HostName) 208 c.Check(addr.Scope, gc.Equals, network.ScopeUnknown) 209 } 210 211 type selectTest struct { 212 about string 213 addresses []network.Address 214 expectedIndex int 215 preferIPv6 bool 216 } 217 218 // expected returns the expected address for the test. 219 func (t selectTest) expected() (network.Address, bool) { 220 if t.expectedIndex == -1 { 221 return network.Address{}, false 222 } 223 return t.addresses[t.expectedIndex], true 224 } 225 226 var selectPublicTests = []selectTest{{ 227 "no addresses gives empty string result", 228 []network.Address{}, 229 -1, 230 false, 231 }, { 232 "a public IPv4 address is selected", 233 []network.Address{ 234 {"8.8.8.8", network.IPv4Address, "public", network.ScopePublic}, 235 }, 236 0, 237 false, 238 }, { 239 "a public IPv6 address is selected", 240 []network.Address{ 241 {"2001:db8::1", network.IPv6Address, "public", network.ScopePublic}, 242 }, 243 0, 244 false, 245 }, { 246 "first public address is selected", 247 []network.Address{ 248 {"8.8.8.8", network.IPv4Address, "public", network.ScopePublic}, 249 {"2001:db8::1", network.IPv6Address, "public", network.ScopePublic}, 250 }, 251 0, 252 false, 253 }, { 254 "the first public address is selected when cloud local fallbacks exist", 255 []network.Address{ 256 {"172.16.1.1", network.IPv4Address, "cloud", network.ScopeCloudLocal}, 257 {"8.8.8.8", network.IPv4Address, "public", network.ScopePublic}, 258 {"fc00:1", network.IPv6Address, "cloud", network.ScopeCloudLocal}, 259 {"2001:db8::1", network.IPv6Address, "public", network.ScopePublic}, 260 }, 261 1, 262 false, 263 }, { 264 "IPv6 public address is preferred to a cloud local one when preferIPv6 is true", 265 []network.Address{ 266 {"8.8.8.8", network.IPv4Address, "public", network.ScopePublic}, 267 {"172.16.1.1", network.IPv4Address, "cloud", network.ScopeCloudLocal}, 268 {"fc00:1", network.IPv6Address, "cloud", network.ScopeCloudLocal}, 269 {"2001:db8::1", network.IPv6Address, "public", network.ScopePublic}, 270 }, 271 3, 272 true, 273 }, { 274 "a machine IPv4 local address is not selected", 275 []network.Address{ 276 {"127.0.0.1", network.IPv4Address, "machine", network.ScopeMachineLocal}, 277 }, 278 -1, 279 false, 280 }, { 281 "a machine IPv6 local address is not selected", 282 []network.Address{ 283 {"::1", network.IPv6Address, "machine", network.ScopeMachineLocal}, 284 }, 285 -1, 286 false, 287 }, { 288 "a link-local IPv4 address is not selected", 289 []network.Address{ 290 {"169.254.1.1", network.IPv4Address, "link", network.ScopeLinkLocal}, 291 }, 292 -1, 293 false, 294 }, { 295 "a link-local (multicast or not) IPv6 address is not selected", 296 []network.Address{ 297 {"fe80::1", network.IPv6Address, "link", network.ScopeLinkLocal}, 298 {"ff01::2", network.IPv6Address, "link", network.ScopeLinkLocal}, 299 {"ff02::1:1", network.IPv6Address, "link", network.ScopeLinkLocal}, 300 }, 301 -1, 302 false, 303 }, { 304 "a public name is preferred to an unknown or cloud local address", 305 []network.Address{ 306 {"127.0.0.1", network.IPv4Address, "local", network.ScopeUnknown}, 307 {"10.0.0.1", network.IPv4Address, "cloud", network.ScopeCloudLocal}, 308 {"fc00::1", network.IPv6Address, "cloud", network.ScopeCloudLocal}, 309 {"public.invalid.testing", network.HostName, "public", network.ScopePublic}, 310 }, 311 3, 312 false, 313 }, { 314 "first unknown address selected", 315 []network.Address{ 316 {"10.0.0.1", network.IPv4Address, "cloud", network.ScopeUnknown}, 317 {"8.8.8.8", network.IPv4Address, "floating", network.ScopeUnknown}, 318 }, 319 0, 320 false, 321 }, { 322 "first public address is picked when both public IPs and public hostnames exist", 323 []network.Address{ 324 {"10.0.0.1", network.IPv4Address, "cloud", network.ScopeUnknown}, 325 {"example.com", network.HostName, "public", network.ScopePublic}, 326 {"8.8.8.8", network.IPv4Address, "floating", network.ScopePublic}, 327 }, 328 1, 329 false, 330 }, { 331 "first public IPv6 address is picked when both public IPs and public hostnames exist when preferIPv6 is true", 332 []network.Address{ 333 {"10.0.0.1", network.IPv4Address, "cloud", network.ScopeUnknown}, 334 {"8.8.8.8", network.IPv4Address, "floating", network.ScopePublic}, 335 {"example.com", network.HostName, "public", network.ScopePublic}, 336 {"2001:db8::1", network.IPv6Address, "other", network.ScopePublic}, 337 }, 338 3, 339 true, 340 }} 341 342 func (s *AddressSuite) TestSelectPublicAddress(c *gc.C) { 343 oldValue := network.GetPreferIPv6() 344 defer func() { 345 network.SetPreferIPv6(oldValue) 346 }() 347 for i, t := range selectPublicTests { 348 c.Logf("test %d: %s", i, t.about) 349 network.SetPreferIPv6(t.preferIPv6) 350 expectAddr, expectOK := t.expected() 351 actualAddr, actualOK := network.SelectPublicAddress(t.addresses) 352 c.Check(actualOK, gc.Equals, expectOK) 353 c.Check(actualAddr, gc.Equals, expectAddr) 354 } 355 } 356 357 var selectInternalTests = []selectTest{{ 358 "no addresses gives empty string result", 359 []network.Address{}, 360 -1, 361 false, 362 }, { 363 "a public IPv4 address is selected", 364 []network.Address{ 365 {"8.8.8.8", network.IPv4Address, "public", network.ScopePublic}, 366 }, 367 0, 368 false, 369 }, { 370 "a public IPv6 address is selected", 371 []network.Address{ 372 {"2001:db8::1", network.IPv6Address, "public", network.ScopePublic}, 373 }, 374 0, 375 false, 376 }, { 377 "a public IPv6 address is selected when both IPv4 and IPv6 addresses exist and preferIPv6 is true", 378 []network.Address{ 379 {"8.8.8.8", network.IPv4Address, "public", network.ScopePublic}, 380 {"2001:db8::1", network.IPv6Address, "public", network.ScopePublic}, 381 }, 382 1, 383 true, 384 }, { 385 "the first public IPv4 address is selected when preferIPv6 is true and no IPv6 addresses", 386 []network.Address{ 387 {"127.0.0.1", network.IPv4Address, "machine", network.ScopeMachineLocal}, 388 {"8.8.8.8", network.IPv4Address, "public", network.ScopePublic}, 389 {"169.254.1.1", network.IPv4Address, "link", network.ScopeLinkLocal}, 390 {"8.8.4.4", network.IPv4Address, "public", network.ScopePublic}, 391 }, 392 1, 393 true, 394 }, { 395 "a cloud local IPv4 address is selected", 396 []network.Address{ 397 {"8.8.8.8", network.IPv4Address, "public", network.ScopePublic}, 398 {"10.0.0.1", network.IPv4Address, "private", network.ScopeCloudLocal}, 399 }, 400 1, 401 false, 402 }, { 403 "a cloud local IPv6 address is selected", 404 []network.Address{ 405 {"fc00::1", network.IPv6Address, "private", network.ScopeCloudLocal}, 406 {"2001:db8::1", network.IPv6Address, "public", network.ScopePublic}, 407 }, 408 0, 409 false, 410 }, { 411 "a machine local or link-local address is not selected", 412 []network.Address{ 413 {"127.0.0.1", network.IPv4Address, "machine", network.ScopeMachineLocal}, 414 {"::1", network.IPv6Address, "machine", network.ScopeMachineLocal}, 415 {"fe80::1", network.IPv6Address, "machine", network.ScopeLinkLocal}, 416 }, 417 -1, 418 false, 419 }, { 420 "a cloud local address is preferred to a public address", 421 []network.Address{ 422 {"2001:db8::1", network.IPv6Address, "public", network.ScopePublic}, 423 {"fc00::1", network.IPv6Address, "cloud", network.ScopeCloudLocal}, 424 {"8.8.8.8", network.IPv4Address, "public", network.ScopePublic}, 425 {"10.0.0.1", network.IPv4Address, "cloud", network.ScopeCloudLocal}, 426 }, 427 1, 428 false, 429 }, { 430 "an IPv6 cloud local address is preferred to a public address when preferIPv6 is true", 431 []network.Address{ 432 {"8.8.8.8", network.IPv4Address, "public", network.ScopePublic}, 433 {"2001:db8::1", network.IPv6Address, "public", network.ScopePublic}, 434 {"fc00::1", network.IPv6Address, "cloud", network.ScopeCloudLocal}, 435 {"10.0.0.1", network.IPv4Address, "cloud", network.ScopeCloudLocal}, 436 }, 437 2, 438 false, 439 }} 440 441 func (s *AddressSuite) TestSelectInternalAddress(c *gc.C) { 442 oldValue := network.GetPreferIPv6() 443 defer func() { 444 network.SetPreferIPv6(oldValue) 445 }() 446 for i, t := range selectInternalTests { 447 c.Logf("test %d: %s", i, t.about) 448 network.SetPreferIPv6(t.preferIPv6) 449 expectAddr, expectOK := t.expected() 450 actualAddr, actualOK := network.SelectInternalAddress(t.addresses, false) 451 c.Check(actualOK, gc.Equals, expectOK) 452 c.Check(actualAddr, gc.Equals, expectAddr) 453 } 454 } 455 456 var selectInternalMachineTests = []selectTest{{ 457 "first cloud local address is selected", 458 []network.Address{ 459 {"fc00::1", network.IPv6Address, "cloud", network.ScopeCloudLocal}, 460 {"2001:db8::1", network.IPv6Address, "public", network.ScopePublic}, 461 {"10.0.0.1", network.IPv4Address, "cloud", network.ScopeCloudLocal}, 462 {"8.8.8.8", network.IPv4Address, "public", network.ScopePublic}, 463 }, 464 0, 465 false, 466 }, { 467 "first cloud local hostname is selected when preferIPv6 is false", 468 []network.Address{ 469 {"example.com", network.HostName, "public", network.ScopePublic}, 470 {"cloud1.internal", network.HostName, "cloud", network.ScopeCloudLocal}, 471 {"cloud2.internal", network.HostName, "cloud", network.ScopeCloudLocal}, 472 {"example.org", network.HostName, "public", network.ScopePublic}, 473 }, 474 1, 475 false, 476 }, { 477 "first cloud local hostname is selected when preferIPv6 is true (public first)", 478 []network.Address{ 479 {"example.org", network.HostName, "public", network.ScopePublic}, 480 {"example.com", network.HostName, "public", network.ScopePublic}, 481 {"cloud1.internal", network.HostName, "cloud", network.ScopeCloudLocal}, 482 {"cloud2.internal", network.HostName, "cloud", network.ScopeCloudLocal}, 483 }, 484 2, 485 true, 486 }, { 487 "first cloud local hostname is selected when preferIPv6 is true (public last)", 488 []network.Address{ 489 {"cloud1.internal", network.HostName, "cloud", network.ScopeCloudLocal}, 490 {"cloud2.internal", network.HostName, "cloud", network.ScopeCloudLocal}, 491 {"example.org", network.HostName, "public", network.ScopePublic}, 492 {"example.com", network.HostName, "public", network.ScopePublic}, 493 }, 494 0, 495 true, 496 }, { 497 "first IPv6 cloud local address is selected when preferIPv6 is true", 498 []network.Address{ 499 {"10.0.0.1", network.IPv4Address, "cloud", network.ScopeCloudLocal}, 500 {"8.8.8.8", network.IPv4Address, "public", network.ScopePublic}, 501 {"fc00::1", network.IPv6Address, "cloud", network.ScopeCloudLocal}, 502 {"2001:db8::1", network.IPv6Address, "public", network.ScopePublic}, 503 }, 504 2, 505 true, 506 }, { 507 "first IPv4 cloud local address is selected when preferIPv6 is true and no IPv6 addresses", 508 []network.Address{ 509 {"169.254.1.1", network.IPv4Address, "link", network.ScopeLinkLocal}, 510 {"10.0.0.1", network.IPv4Address, "cloud", network.ScopeCloudLocal}, 511 {"172.16.1.1", network.IPv4Address, "cloud", network.ScopeCloudLocal}, 512 }, 513 1, 514 true, 515 }, { 516 "first machine local address is selected", 517 []network.Address{ 518 {"127.0.0.1", network.IPv4Address, "container", network.ScopeMachineLocal}, 519 {"::1", network.IPv6Address, "container", network.ScopeMachineLocal}, 520 }, 521 0, 522 false, 523 }, { 524 "first IPv6 machine local address is selected when preferIPv6 is true", 525 []network.Address{ 526 {"127.0.0.1", network.IPv4Address, "container", network.ScopeMachineLocal}, 527 {"::1", network.IPv6Address, "container", network.ScopeMachineLocal}, 528 {"fe80::1", network.IPv6Address, "container", network.ScopeLinkLocal}, 529 }, 530 1, 531 true, 532 }, { 533 "first IPv4 machine local address is selected when preferIPv6 is true and no IPv6 addresses", 534 []network.Address{ 535 {"169.254.1.1", network.IPv4Address, "link", network.ScopeLinkLocal}, 536 {"127.0.0.1", network.IPv4Address, "container", network.ScopeMachineLocal}, 537 {"127.0.0.2", network.IPv4Address, "container", network.ScopeMachineLocal}, 538 }, 539 1, 540 true, 541 }, { 542 "first machine local address is selected when preferIPv6 is false even with public/cloud hostnames", 543 []network.Address{ 544 {"public.example.com", network.HostName, "public", network.ScopePublic}, 545 {"::1", network.IPv6Address, "container", network.ScopeMachineLocal}, 546 {"unknown.example.com", network.HostName, "public", network.ScopeUnknown}, 547 {"cloud.internal", network.HostName, "public", network.ScopeCloudLocal}, 548 {"127.0.0.1", network.IPv4Address, "container", network.ScopeMachineLocal}, 549 {"fe80::1", network.IPv6Address, "container", network.ScopeLinkLocal}, 550 {"127.0.0.2", network.IPv4Address, "container", network.ScopeMachineLocal}, 551 }, 552 1, 553 false, 554 }, { 555 "first cloud local hostname is selected when preferIPv6 is false even with other machine/cloud addresses", 556 []network.Address{ 557 {"169.254.1.1", network.IPv4Address, "link", network.ScopeLinkLocal}, 558 {"cloud-unknown.internal", network.HostName, "container", network.ScopeUnknown}, 559 {"cloud-local.internal", network.HostName, "container", network.ScopeCloudLocal}, 560 {"fc00::1", network.IPv6Address, "cloud", network.ScopeCloudLocal}, 561 {"127.0.0.1", network.IPv4Address, "container", network.ScopeMachineLocal}, 562 {"127.0.0.2", network.IPv4Address, "container", network.ScopeMachineLocal}, 563 }, 564 2, 565 false, 566 }, { 567 "first IPv6 machine local address is selected when preferIPv6 is true even with public/cloud hostnames", 568 []network.Address{ 569 {"127.0.0.1", network.IPv4Address, "container", network.ScopeMachineLocal}, 570 {"public.example.com", network.HostName, "public", network.ScopePublic}, 571 {"unknown.example.com", network.HostName, "public", network.ScopeUnknown}, 572 {"cloud.internal", network.HostName, "public", network.ScopeCloudLocal}, 573 {"::1", network.IPv6Address, "container", network.ScopeMachineLocal}, 574 {"fe80::1", network.IPv6Address, "container", network.ScopeLinkLocal}, 575 }, 576 4, 577 true, 578 }, { 579 "first IPv6 cloud local address is selected when preferIPv6 is true even with cloud local hostnames", 580 []network.Address{ 581 {"169.254.1.1", network.IPv4Address, "link", network.ScopeLinkLocal}, 582 {"cloud-unknown.internal", network.HostName, "container", network.ScopeUnknown}, 583 {"cloud-local.internal", network.HostName, "container", network.ScopeCloudLocal}, 584 {"fc00::1", network.IPv6Address, "cloud", network.ScopeCloudLocal}, 585 {"127.0.0.1", network.IPv4Address, "container", network.ScopeMachineLocal}, 586 {"fc00::2", network.IPv6Address, "cloud", network.ScopeCloudLocal}, 587 {"127.0.0.2", network.IPv4Address, "container", network.ScopeMachineLocal}, 588 }, 589 3, 590 true, 591 }} 592 593 func (s *AddressSuite) TestSelectInternalMachineAddress(c *gc.C) { 594 oldValue := network.GetPreferIPv6() 595 defer func() { 596 network.SetPreferIPv6(oldValue) 597 }() 598 for i, t := range selectInternalMachineTests { 599 c.Logf("test %d: %s", i, t.about) 600 network.SetPreferIPv6(t.preferIPv6) 601 expectAddr, expectOK := t.expected() 602 actualAddr, actualOK := network.SelectInternalAddress(t.addresses, true) 603 c.Check(actualOK, gc.Equals, expectOK) 604 c.Check(actualAddr, gc.Equals, expectAddr) 605 } 606 } 607 608 var stringTests = []struct { 609 addr network.Address 610 str string 611 }{{ 612 addr: network.Address{ 613 Type: network.IPv4Address, 614 Value: "127.0.0.1", 615 }, 616 str: "127.0.0.1", 617 }, { 618 addr: network.Address{ 619 Type: network.IPv6Address, 620 Value: "2001:db8::1", 621 Scope: network.ScopePublic, 622 }, 623 str: "public:2001:db8::1", 624 }, { 625 addr: network.Address{ 626 Type: network.HostName, 627 Value: "foo.com", 628 }, 629 str: "foo.com", 630 }, { 631 addr: network.Address{ 632 Type: network.HostName, 633 Value: "foo.com", 634 Scope: network.ScopeUnknown, 635 }, 636 str: "foo.com", 637 }, { 638 addr: network.Address{ 639 Type: network.HostName, 640 Value: "foo.com", 641 Scope: network.ScopePublic, 642 }, 643 str: "public:foo.com", 644 }, { 645 addr: network.Address{ 646 Type: network.HostName, 647 Value: "foo.com", 648 Scope: network.ScopePublic, 649 NetworkName: "netname", 650 }, 651 str: "public:foo.com(netname)", 652 }} 653 654 func (s *AddressSuite) TestString(c *gc.C) { 655 for i, test := range stringTests { 656 c.Logf("test %d: %#v", i, test.addr) 657 c.Check(test.addr.String(), gc.Equals, test.str) 658 c.Check(test.addr.GoString(), gc.Equals, test.str) 659 } 660 } 661 662 func (*AddressSuite) TestSortAddresses(c *gc.C) { 663 addrs := network.NewAddresses( 664 "127.0.0.1", 665 "::1", 666 "fc00::1", 667 "169.254.1.2", 668 "localhost", 669 "2001:db8::1", 670 "fe80::2", 671 "7.8.8.8", 672 "172.16.0.1", 673 "example.com", 674 "8.8.8.8", 675 ) 676 // Simulate prefer-ipv6: false first. 677 network.SortAddresses(addrs, false) 678 c.Assert(addrs, jc.DeepEquals, network.NewAddresses( 679 // Public IPv4 addresses on top. 680 "7.8.8.8", 681 "8.8.8.8", 682 // After that public IPv6 addresses. 683 "2001:db8::1", 684 // Then hostnames. 685 "example.com", 686 "localhost", 687 // Then IPv4 cloud-local addresses. 688 "172.16.0.1", 689 // Then IPv6 cloud-local addresses. 690 "fc00::1", 691 // Then machine-local IPv4 addresses. 692 "127.0.0.1", 693 // Then machine-local IPv6 addresses. 694 "::1", 695 // Then link-local IPv4 addresses. 696 "169.254.1.2", 697 // Finally, link-local IPv6 addresses. 698 "fe80::2", 699 )) 700 701 // Now, simulate prefer-ipv6: true. 702 network.SortAddresses(addrs, true) 703 c.Assert(addrs, jc.DeepEquals, network.NewAddresses( 704 // Public IPv6 addresses on top. 705 "2001:db8::1", 706 // After that public IPv4 addresses. 707 "7.8.8.8", 708 "8.8.8.8", 709 // Then hostnames. 710 "example.com", 711 "localhost", 712 // Then IPv6 cloud-local addresses. 713 "fc00::1", 714 // Then IPv4 cloud-local addresses. 715 "172.16.0.1", 716 // Then machine-local IPv6 addresses. 717 "::1", 718 // Then machine-local IPv4 addresses. 719 "127.0.0.1", 720 // Then link-local IPv6 addresses. 721 "fe80::2", 722 // Finally, link-local IPv4 addresses. 723 "169.254.1.2", 724 )) 725 } 726 727 func (*AddressSuite) TestIPv4ToDecimal(c *gc.C) { 728 zeroIP, err := network.IPv4ToDecimal(net.ParseIP("0.0.0.0")) 729 c.Assert(err, jc.ErrorIsNil) 730 c.Assert(zeroIP, gc.Equals, uint32(0)) 731 732 nilIP := net.ParseIP("bad format") 733 _, err = network.IPv4ToDecimal(nilIP) 734 c.Assert(err, gc.ErrorMatches, `"<nil>" is not a valid IPv4 address`) 735 736 _, err = network.IPv4ToDecimal(net.ParseIP("2001:db8::1")) 737 c.Assert(err, gc.ErrorMatches, `"2001:db8::1" is not a valid IPv4 address`) 738 739 nonZeroIP, err := network.IPv4ToDecimal(net.ParseIP("192.168.1.1")) 740 c.Assert(err, jc.ErrorIsNil) 741 c.Assert(nonZeroIP, gc.Equals, uint32(3232235777)) 742 } 743 744 func (*AddressSuite) TestDecimalToIPv4(c *gc.C) { 745 addr := network.DecimalToIPv4(uint32(0)) 746 c.Assert(addr.String(), gc.Equals, "0.0.0.0") 747 748 addr = network.DecimalToIPv4(uint32(3232235777)) 749 c.Assert(addr.String(), gc.Equals, "192.168.1.1") 750 } 751 752 func (*AddressSuite) TestExactScopeMatch(c *gc.C) { 753 network.SetPreferIPv6(false) 754 addr := network.NewScopedAddress("10.0.0.2", network.ScopeCloudLocal) 755 match := network.ExactScopeMatch(addr, network.ScopeCloudLocal) 756 c.Assert(match, jc.IsTrue) 757 match = network.ExactScopeMatch(addr, network.ScopePublic) 758 c.Assert(match, jc.IsFalse) 759 760 addr = network.NewScopedAddress("8.8.8.8", network.ScopePublic) 761 match = network.ExactScopeMatch(addr, network.ScopeCloudLocal) 762 c.Assert(match, jc.IsFalse) 763 match = network.ExactScopeMatch(addr, network.ScopePublic) 764 c.Assert(match, jc.IsTrue) 765 } 766 767 func (*AddressSuite) TestExactScopeMatchHonoursPreferIPv6(c *gc.C) { 768 network.SetPreferIPv6(true) 769 addr := network.NewScopedAddress("10.0.0.2", network.ScopeCloudLocal) 770 match := network.ExactScopeMatch(addr, network.ScopeCloudLocal) 771 c.Assert(match, jc.IsFalse) 772 match = network.ExactScopeMatch(addr, network.ScopePublic) 773 c.Assert(match, jc.IsFalse) 774 775 addr = network.NewScopedAddress("8.8.8.8", network.ScopePublic) 776 match = network.ExactScopeMatch(addr, network.ScopeCloudLocal) 777 c.Assert(match, jc.IsFalse) 778 match = network.ExactScopeMatch(addr, network.ScopePublic) 779 c.Assert(match, jc.IsFalse) 780 781 addr = network.NewScopedAddress("2001:db8::ff00:42:8329", network.ScopePublic) 782 match = network.ExactScopeMatch(addr, network.ScopeCloudLocal) 783 c.Assert(match, jc.IsFalse) 784 match = network.ExactScopeMatch(addr, network.ScopePublic) 785 c.Assert(match, jc.IsTrue) 786 787 addr = network.NewScopedAddress("fc00::1", network.ScopeCloudLocal) 788 match = network.ExactScopeMatch(addr, network.ScopeCloudLocal) 789 c.Assert(match, jc.IsTrue) 790 match = network.ExactScopeMatch(addr, network.ScopePublic) 791 c.Assert(match, jc.IsFalse) 792 }