github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/state/address_test.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package state_test 5 6 import ( 7 "github.com/juju/mgo/v3" 8 "github.com/juju/mgo/v3/bson" 9 jc "github.com/juju/testing/checkers" 10 gc "gopkg.in/check.v1" 11 12 "github.com/juju/juju/controller" 13 "github.com/juju/juju/core/network" 14 "github.com/juju/juju/state" 15 statetesting "github.com/juju/juju/state/testing" 16 "github.com/juju/juju/testing/factory" 17 ) 18 19 type AddressSuite struct{} 20 21 var _ = gc.Suite(&AddressSuite{}) 22 23 func (s *AddressSuite) TestAddressConversion(c *gc.C) { 24 netAddress := network.SpaceAddress{ 25 MachineAddress: network.MachineAddress{ 26 Value: "0.0.0.0", 27 Type: network.IPv4Address, 28 Scope: network.ScopeUnknown, 29 }, 30 } 31 state.AssertAddressConversion(c, netAddress) 32 } 33 34 func (s *AddressSuite) TestHostPortConversion(c *gc.C) { 35 netAddress := network.SpaceAddress{ 36 MachineAddress: network.MachineAddress{ 37 Value: "0.0.0.0", 38 Type: network.IPv4Address, 39 Scope: network.ScopeUnknown, 40 }, 41 } 42 netHostPort := network.SpaceHostPort{ 43 SpaceAddress: netAddress, 44 NetPort: 4711, 45 } 46 state.AssertHostPortConversion(c, netHostPort) 47 } 48 49 type ControllerAddressesSuite struct { 50 ConnSuite 51 } 52 53 var _ = gc.Suite(&ControllerAddressesSuite{}) 54 55 func (s *ControllerAddressesSuite) SetUpTest(c *gc.C) { 56 s.ConnSuite.SetUpTest(c) 57 // Make sure there is a machine with manage state in existence. 58 machine := s.Factory.MakeMachine(c, &factory.MachineParams{ 59 Jobs: []state.MachineJob{state.JobManageModel, state.JobHostUnits}, 60 Addresses: network.SpaceAddresses{ 61 network.NewSpaceAddress("192.168.2.144"), 62 network.NewSpaceAddress("10.0.1.2"), 63 }, 64 }) 65 c.Logf("machine addresses: %#v", machine.Addresses()) 66 s.WaitForModelWatchersIdle(c, s.Model.UUID()) 67 } 68 69 func (s *ControllerAddressesSuite) TestControllerModel(c *gc.C) { 70 addresses, err := s.State.Addresses() 71 c.Assert(err, jc.ErrorIsNil) 72 c.Assert(addresses, jc.SameContents, []string{"10.0.1.2:1234"}) 73 } 74 75 func (s *ControllerAddressesSuite) TestOtherModel(c *gc.C) { 76 st := s.Factory.MakeModel(c, nil) 77 defer func() { _ = st.Close() }() 78 addresses, err := st.Addresses() 79 c.Assert(err, jc.ErrorIsNil) 80 c.Assert(addresses, jc.SameContents, []string{"10.0.1.2:1234"}) 81 } 82 83 func (s *ControllerAddressesSuite) TestSetAPIHostPortsNoMgmtSpace(c *gc.C) { 84 addrs, err := s.State.APIHostPortsForClients() 85 c.Assert(err, jc.ErrorIsNil) 86 c.Assert(addrs, gc.HasLen, 0) 87 88 newHostPorts := []network.SpaceHostPorts{{{ 89 SpaceAddress: network.NewSpaceAddress("0.2.4.6", network.WithScope(network.ScopeCloudLocal)), 90 NetPort: 1, 91 }, { 92 SpaceAddress: network.NewSpaceAddress("0.4.8.16", network.WithScope(network.ScopePublic)), 93 NetPort: 2, 94 }}, {{ 95 SpaceAddress: network.NewSpaceAddress("0.6.1.2", network.WithScope(network.ScopeCloudLocal)), 96 NetPort: 5, 97 }}} 98 err = s.State.SetAPIHostPorts(newHostPorts) 99 c.Assert(err, jc.ErrorIsNil) 100 101 ctrlSt, err := s.StatePool.SystemState() 102 c.Assert(err, jc.ErrorIsNil) 103 gotHostPorts, err := ctrlSt.APIHostPortsForClients() 104 c.Assert(err, jc.ErrorIsNil) 105 c.Assert(gotHostPorts, jc.DeepEquals, newHostPorts) 106 107 gotHostPorts, err = ctrlSt.APIHostPortsForAgents() 108 c.Assert(err, jc.ErrorIsNil) 109 c.Assert(gotHostPorts, jc.DeepEquals, newHostPorts) 110 111 newHostPorts = []network.SpaceHostPorts{{{ 112 SpaceAddress: network.NewSpaceAddress("0.2.4.6", network.WithScope(network.ScopeCloudLocal)), 113 NetPort: 13, 114 }}} 115 err = s.State.SetAPIHostPorts(newHostPorts) 116 c.Assert(err, jc.ErrorIsNil) 117 118 gotHostPorts, err = s.State.APIHostPortsForClients() 119 c.Assert(err, jc.ErrorIsNil) 120 c.Assert(gotHostPorts, jc.DeepEquals, newHostPorts) 121 122 gotHostPorts, err = ctrlSt.APIHostPortsForAgents() 123 c.Assert(err, jc.ErrorIsNil) 124 c.Assert(gotHostPorts, jc.DeepEquals, newHostPorts) 125 } 126 127 func (s *ControllerAddressesSuite) TestSetAPIHostPortsNoMgmtSpaceConcurrentSame(c *gc.C) { 128 hostPorts := []network.SpaceHostPorts{{{ 129 SpaceAddress: network.NewSpaceAddress("0.4.8.16", network.WithScope(network.ScopePublic)), 130 NetPort: 2, 131 }}, {{ 132 SpaceAddress: network.NewSpaceAddress("0.2.4.6", network.WithScope(network.ScopeCloudLocal)), 133 NetPort: 1, 134 }}} 135 136 // API host ports are concurrently changed to the same 137 // desired value; second arrival will fail its assertion, 138 // refresh finding nothing to do, and then issue a 139 // read-only assertion that succeeds. 140 ctrC := state.ControllersC 141 var prevRevno int64 142 var prevAgentsRevno int64 143 defer state.SetBeforeHooks(c, s.State, func() { 144 err := s.State.SetAPIHostPorts(hostPorts) 145 c.Assert(err, jc.ErrorIsNil) 146 revno, err := state.TxnRevno(s.State, ctrC, "apiHostPorts") 147 c.Assert(err, jc.ErrorIsNil) 148 prevRevno = revno 149 revno, err = state.TxnRevno(s.State, ctrC, "apiHostPortsForAgents") 150 c.Assert(err, jc.ErrorIsNil) 151 prevAgentsRevno = revno 152 }).Check() 153 154 err := s.State.SetAPIHostPorts(hostPorts) 155 c.Assert(err, jc.ErrorIsNil) 156 c.Assert(prevRevno, gc.Not(gc.Equals), 0) 157 158 revno, err := state.TxnRevno(s.State, ctrC, "apiHostPorts") 159 c.Assert(err, jc.ErrorIsNil) 160 c.Assert(revno, gc.Equals, prevRevno) 161 162 revno, err = state.TxnRevno(s.State, ctrC, "apiHostPortsForAgents") 163 c.Assert(err, jc.ErrorIsNil) 164 c.Assert(revno, gc.Equals, prevAgentsRevno) 165 } 166 167 func (s *ControllerAddressesSuite) TestSetAPIHostPortsNoMgmtSpaceConcurrentDifferent(c *gc.C) { 168 hostPorts0 := []network.SpaceHostPort{{ 169 SpaceAddress: network.NewSpaceAddress("0.4.8.16", network.WithScope(network.ScopePublic)), 170 NetPort: 2, 171 }} 172 hostPorts1 := []network.SpaceHostPort{{ 173 SpaceAddress: network.NewSpaceAddress("0.2.4.6", network.WithScope(network.ScopeCloudLocal)), 174 NetPort: 1, 175 }} 176 177 // API host ports are concurrently changed to different 178 // values; second arrival will fail its assertion, refresh 179 // finding and reattempt. 180 181 ctrC := state.ControllersC 182 var prevRevno int64 183 var prevAgentsRevno int64 184 defer state.SetBeforeHooks(c, s.State, func() { 185 err := s.State.SetAPIHostPorts([]network.SpaceHostPorts{hostPorts0}) 186 c.Assert(err, jc.ErrorIsNil) 187 revno, err := state.TxnRevno(s.State, ctrC, "apiHostPorts") 188 c.Assert(err, jc.ErrorIsNil) 189 prevRevno = revno 190 revno, err = state.TxnRevno(s.State, ctrC, "apiHostPortsForAgents") 191 c.Assert(err, jc.ErrorIsNil) 192 prevAgentsRevno = revno 193 }).Check() 194 195 err := s.State.SetAPIHostPorts([]network.SpaceHostPorts{hostPorts1}) 196 c.Assert(err, jc.ErrorIsNil) 197 c.Assert(prevRevno, gc.Not(gc.Equals), 0) 198 199 revno, err := state.TxnRevno(s.State, ctrC, "apiHostPorts") 200 c.Assert(err, jc.ErrorIsNil) 201 c.Assert(revno, gc.Not(gc.Equals), prevRevno) 202 203 revno, err = state.TxnRevno(s.State, ctrC, "apiHostPortsForAgents") 204 c.Assert(err, jc.ErrorIsNil) 205 c.Assert(revno, gc.Not(gc.Equals), prevAgentsRevno) 206 207 ctrlSt, err := s.StatePool.SystemState() 208 c.Assert(err, jc.ErrorIsNil) 209 hostPorts, err := ctrlSt.APIHostPortsForClients() 210 c.Assert(err, jc.ErrorIsNil) 211 c.Assert(hostPorts, gc.DeepEquals, []network.SpaceHostPorts{hostPorts1}) 212 213 hostPorts, err = ctrlSt.APIHostPortsForAgents() 214 c.Assert(err, jc.ErrorIsNil) 215 c.Assert(hostPorts, gc.DeepEquals, []network.SpaceHostPorts{hostPorts1}) 216 } 217 218 func (s *ControllerAddressesSuite) TestSetAPIHostPortsWithMgmtSpace(c *gc.C) { 219 sp, err := s.State.AddSpace("mgmt01", "", nil, false) 220 c.Assert(err, jc.ErrorIsNil) 221 222 s.SetJujuManagementSpace(c, "mgmt01") 223 224 addrs, err := s.State.APIHostPortsForClients() 225 c.Assert(err, jc.ErrorIsNil) 226 c.Assert(addrs, gc.HasLen, 0) 227 228 hostPort1 := network.SpaceHostPort{ 229 SpaceAddress: network.NewSpaceAddress("0.2.4.6", network.WithScope(network.ScopeCloudLocal)), 230 NetPort: 1, 231 } 232 hostPort2 := network.SpaceHostPort{ 233 SpaceAddress: network.SpaceAddress{ 234 MachineAddress: network.MachineAddress{ 235 Value: "0.4.8.16", 236 Type: network.IPv4Address, 237 Scope: network.ScopePublic, 238 }, 239 SpaceID: sp.Id(), 240 }, 241 NetPort: 2, 242 } 243 hostPort3 := network.SpaceHostPort{ 244 SpaceAddress: network.NewSpaceAddress("0.4.1.2", network.WithScope(network.ScopeCloudLocal)), 245 NetPort: 5, 246 } 247 newHostPorts := []network.SpaceHostPorts{{hostPort1, hostPort2}, {hostPort3}} 248 249 err = s.State.SetAPIHostPorts(newHostPorts) 250 c.Assert(err, jc.ErrorIsNil) 251 252 ctrlSt, err := s.StatePool.SystemState() 253 c.Assert(err, jc.ErrorIsNil) 254 gotHostPorts, err := ctrlSt.APIHostPortsForClients() 255 c.Assert(err, jc.ErrorIsNil) 256 c.Assert(gotHostPorts, jc.DeepEquals, newHostPorts) 257 258 gotHostPorts, err = ctrlSt.APIHostPortsForAgents() 259 c.Assert(err, jc.ErrorIsNil) 260 // First slice filtered down to the address in the management space. 261 // Second filtered to zero elements, so retains the supplied slice. 262 c.Assert(gotHostPorts, jc.DeepEquals, []network.SpaceHostPorts{{hostPort2}, {hostPort3}}) 263 } 264 265 func (s *ControllerAddressesSuite) TestSetAPIHostPortsForAgentsNoDocument(c *gc.C) { 266 addrs, err := s.State.APIHostPortsForClients() 267 c.Assert(err, jc.ErrorIsNil) 268 c.Assert(addrs, gc.HasLen, 0) 269 270 newHostPorts := []network.SpaceHostPorts{{{ 271 SpaceAddress: network.NewSpaceAddress("0.2.4.6", network.WithScope(network.ScopeCloudLocal)), 272 NetPort: 1, 273 }}} 274 275 // Delete the addresses for agents document before setting. 276 col := s.State.MongoSession().DB("juju").C(state.ControllersC) 277 key := "apiHostPortsForAgents" 278 err = col.RemoveId(key) 279 c.Assert(err, jc.ErrorIsNil) 280 c.Assert(col.FindId(key).One(&bson.D{}), gc.Equals, mgo.ErrNotFound) 281 282 err = s.State.SetAPIHostPorts(newHostPorts) 283 c.Assert(err, jc.ErrorIsNil) 284 285 ctrlSt, err := s.StatePool.SystemState() 286 c.Assert(err, jc.ErrorIsNil) 287 gotHostPorts, err := ctrlSt.APIHostPortsForAgents() 288 c.Assert(err, jc.ErrorIsNil) 289 c.Assert(gotHostPorts, jc.DeepEquals, newHostPorts) 290 } 291 292 func (s *ControllerAddressesSuite) TestAPIHostPortsForAgentsNoDocument(c *gc.C) { 293 addrs, err := s.State.APIHostPortsForClients() 294 c.Assert(err, jc.ErrorIsNil) 295 c.Assert(addrs, gc.HasLen, 0) 296 297 newHostPorts := []network.SpaceHostPorts{{{ 298 SpaceAddress: network.NewSpaceAddress("0.2.4.6", network.WithScope(network.ScopeCloudLocal)), 299 NetPort: 1, 300 }}} 301 302 err = s.State.SetAPIHostPorts(newHostPorts) 303 c.Assert(err, jc.ErrorIsNil) 304 305 // Delete the addresses for agents document after setting. 306 col := s.State.MongoSession().DB("juju").C(state.ControllersC) 307 key := "apiHostPortsForAgents" 308 err = col.RemoveId(key) 309 c.Assert(err, jc.ErrorIsNil) 310 c.Assert(col.FindId(key).One(&bson.D{}), gc.Equals, mgo.ErrNotFound) 311 312 ctrlSt, err := s.StatePool.SystemState() 313 c.Assert(err, jc.ErrorIsNil) 314 gotHostPorts, err := ctrlSt.APIHostPortsForAgents() 315 c.Assert(err, jc.ErrorIsNil) 316 c.Assert(gotHostPorts, jc.DeepEquals, newHostPorts) 317 } 318 319 func (s *ControllerAddressesSuite) TestWatchAPIHostPortsForClients(c *gc.C) { 320 w := s.State.WatchAPIHostPortsForClients() 321 defer statetesting.AssertStop(c, w) 322 323 // Initial event. 324 wc := statetesting.NewNotifyWatcherC(c, w) 325 wc.AssertOneChange() 326 327 err := s.State.SetAPIHostPorts([]network.SpaceHostPorts{network.NewSpaceHostPorts(99, "0.1.2.3")}) 328 c.Assert(err, jc.ErrorIsNil) 329 330 wc.AssertOneChange() 331 332 // Stop, check closed. 333 statetesting.AssertStop(c, w) 334 wc.AssertClosed() 335 } 336 337 func (s *ControllerAddressesSuite) TestWatchAPIHostPortsForAgents(c *gc.C) { 338 sp, err := s.State.AddSpace("mgmt01", "", nil, false) 339 c.Assert(err, jc.ErrorIsNil) 340 341 s.SetJujuManagementSpace(c, "mgmt01") 342 343 w := s.State.WatchAPIHostPortsForAgents() 344 defer statetesting.AssertStop(c, w) 345 346 // Initial event. 347 wc := statetesting.NewNotifyWatcherC(c, w) 348 wc.AssertOneChange() 349 350 mgmtHP := network.SpaceHostPort{ 351 SpaceAddress: network.SpaceAddress{ 352 MachineAddress: network.MachineAddress{ 353 Value: "0.4.8.16", 354 Type: network.IPv4Address, 355 Scope: network.ScopeCloudLocal, 356 }, 357 SpaceID: sp.Id(), 358 }, 359 NetPort: 2, 360 } 361 362 err = s.State.SetAPIHostPorts([]network.SpaceHostPorts{{mgmtHP}}) 363 c.Assert(err, jc.ErrorIsNil) 364 wc.AssertOneChange() 365 366 // This should cause no change to APIHostPortsForAgents. 367 // We expect only one watcher notification. 368 err = s.State.SetAPIHostPorts([]network.SpaceHostPorts{{ 369 mgmtHP, 370 network.SpaceHostPort{ 371 SpaceAddress: network.NewSpaceAddress("0.1.2.3", network.WithScope(network.ScopeCloudLocal)), 372 NetPort: 99, 373 }, 374 }}) 375 c.Assert(err, jc.ErrorIsNil) 376 wc.AssertNoChange() 377 378 // Stop, check closed. 379 statetesting.AssertStop(c, w) 380 wc.AssertClosed() 381 } 382 383 type CAASAddressesSuite struct { 384 statetesting.StateSuite 385 } 386 387 var _ = gc.Suite(&CAASAddressesSuite{}) 388 389 func (s *CAASAddressesSuite) SetUpTest(c *gc.C) { 390 s.ControllerConfig = map[string]interface{}{ 391 controller.ControllerName: "trump", 392 } 393 s.StateSuite.SetUpTest(c) 394 state.SetModelTypeToCAAS(c, s.State, s.Model) 395 } 396 397 func (s *CAASAddressesSuite) TestAPIHostPortsCloudLocalOnly(c *gc.C) { 398 machineAddr := network.MachineAddress{ 399 Value: "10.10.10.10", 400 Type: network.IPv4Address, 401 Scope: network.ScopeCloudLocal, 402 } 403 localDNSAddr := network.MachineAddress{ 404 Value: "controller-service.controller-trump.svc.cluster.local", 405 Type: network.HostName, 406 Scope: network.ScopeCloudLocal, 407 } 408 409 ctrlSt, err := s.StatePool.SystemState() 410 c.Assert(err, jc.ErrorIsNil) 411 _, err = ctrlSt.SaveCloudService(state.SaveCloudServiceArgs{ 412 Id: s.Model.ControllerUUID(), 413 ProviderId: "whatever", 414 Addresses: network.SpaceAddresses{{MachineAddress: machineAddr}}, 415 }) 416 c.Assert(err, jc.ErrorIsNil) 417 418 exp := []network.SpaceHostPorts{{{ 419 SpaceAddress: network.SpaceAddress{MachineAddress: localDNSAddr}, 420 NetPort: 17777, 421 }, { 422 SpaceAddress: network.SpaceAddress{MachineAddress: machineAddr}, 423 NetPort: 17777, 424 }}} 425 426 addrs, err := ctrlSt.APIHostPortsForAgents() 427 c.Assert(err, jc.ErrorIsNil) 428 c.Assert(addrs, gc.DeepEquals, exp) 429 430 exp = []network.SpaceHostPorts{{{ 431 SpaceAddress: network.SpaceAddress{MachineAddress: machineAddr}, 432 NetPort: 17777, 433 }}} 434 addrs, err = ctrlSt.APIHostPortsForClients() 435 c.Assert(err, jc.ErrorIsNil) 436 c.Assert(addrs, gc.DeepEquals, exp) 437 } 438 439 func (s *CAASAddressesSuite) TestAPIHostPortsPublicOnly(c *gc.C) { 440 machineAddr := network.MachineAddress{ 441 Value: "10.10.10.10", 442 Type: network.IPv4Address, 443 Scope: network.ScopePublic, 444 } 445 localDNSAddr := network.MachineAddress{ 446 Value: "controller-service.controller-trump.svc.cluster.local", 447 Type: network.HostName, 448 Scope: network.ScopeCloudLocal, 449 } 450 451 ctrlSt, err := s.StatePool.SystemState() 452 c.Assert(err, jc.ErrorIsNil) 453 _, err = ctrlSt.SaveCloudService(state.SaveCloudServiceArgs{ 454 Id: s.Model.ControllerUUID(), 455 ProviderId: "whatever", 456 Addresses: network.SpaceAddresses{{MachineAddress: machineAddr}}, 457 }) 458 c.Assert(err, jc.ErrorIsNil) 459 460 exp := []network.SpaceHostPorts{{{ 461 SpaceAddress: network.SpaceAddress{MachineAddress: localDNSAddr}, 462 NetPort: 17777, 463 }, { 464 SpaceAddress: network.SpaceAddress{MachineAddress: machineAddr}, 465 NetPort: 17777, 466 }}} 467 468 addrs, err := ctrlSt.APIHostPortsForAgents() 469 c.Assert(err, jc.ErrorIsNil) 470 c.Assert(addrs, gc.DeepEquals, exp) 471 472 exp = []network.SpaceHostPorts{{{ 473 SpaceAddress: network.SpaceAddress{MachineAddress: machineAddr}, 474 NetPort: 17777, 475 }}} 476 addrs, err = ctrlSt.APIHostPortsForClients() 477 c.Assert(err, jc.ErrorIsNil) 478 c.Assert(addrs, gc.DeepEquals, exp) 479 } 480 481 func (s *CAASAddressesSuite) TestAPIHostPortsMultiple(c *gc.C) { 482 machineAddr1 := network.MachineAddress{ 483 Value: "10.10.10.1", 484 Type: network.IPv4Address, 485 Scope: network.ScopePublic, 486 } 487 machineAddr2 := network.MachineAddress{ 488 Value: "10.10.10.2", 489 Type: network.IPv4Address, 490 Scope: network.ScopePublic, 491 } 492 machineAddr3 := network.MachineAddress{ 493 Value: "100.10.10.1", 494 Type: network.IPv4Address, 495 Scope: network.ScopeCloudLocal, 496 } 497 machineAddr4 := network.MachineAddress{ 498 Value: "100.10.10.2", 499 Type: network.IPv4Address, 500 Scope: network.ScopeCloudLocal, 501 } 502 localDNSAddr := network.MachineAddress{ 503 Value: "controller-service.controller-trump.svc.cluster.local", 504 Type: network.HostName, 505 Scope: network.ScopeCloudLocal, 506 } 507 508 ctrlSt, err := s.StatePool.SystemState() 509 c.Assert(err, jc.ErrorIsNil) 510 _, err = ctrlSt.SaveCloudService(state.SaveCloudServiceArgs{ 511 Id: s.Model.ControllerUUID(), 512 ProviderId: "whatever", 513 Addresses: network.SpaceAddresses{ 514 {MachineAddress: machineAddr1}, 515 {MachineAddress: machineAddr2}, 516 {MachineAddress: machineAddr3}, 517 {MachineAddress: machineAddr4}, 518 }, 519 }) 520 c.Assert(err, jc.ErrorIsNil) 521 522 addrs, err := ctrlSt.APIHostPortsForAgents() 523 c.Assert(err, jc.ErrorIsNil) 524 525 // Local-cloud addresses must come first. 526 c.Assert(addrs[0][:3], jc.SameContents, network.SpaceHostPorts{ 527 { 528 SpaceAddress: network.SpaceAddress{MachineAddress: localDNSAddr}, 529 NetPort: 17777, 530 }, 531 { 532 SpaceAddress: network.SpaceAddress{MachineAddress: machineAddr3}, 533 NetPort: 17777, 534 }, 535 { 536 SpaceAddress: network.SpaceAddress{MachineAddress: machineAddr4}, 537 NetPort: 17777, 538 }, 539 }) 540 541 exp := network.SpaceHostPorts{ 542 { 543 SpaceAddress: network.SpaceAddress{MachineAddress: machineAddr1}, 544 NetPort: 17777, 545 }, 546 { 547 SpaceAddress: network.SpaceAddress{MachineAddress: machineAddr2}, 548 NetPort: 17777, 549 }, 550 } 551 552 // Public ones should also follow. 553 c.Assert(addrs[0][3:], jc.SameContents, exp) 554 555 // Only the public ones should be returned. 556 addrs, err = ctrlSt.APIHostPortsForClients() 557 c.Assert(err, jc.ErrorIsNil) 558 c.Assert(addrs, gc.DeepEquals, []network.SpaceHostPorts{exp}) 559 }