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  }