github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/state/ipaddresses_test.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package state_test
     5  
     6  import (
     7  	"fmt"
     8  	"sort"
     9  
    10  	"github.com/juju/collections/set"
    11  	"github.com/juju/errors"
    12  	jc "github.com/juju/testing/checkers"
    13  	gc "gopkg.in/check.v1"
    14  
    15  	"github.com/juju/juju/core/network"
    16  	"github.com/juju/juju/state"
    17  )
    18  
    19  // ipAddressesStateSuite contains white-box tests for IP addresses of link-layer
    20  // devices, which include access to mongo.
    21  type ipAddressesStateSuite struct {
    22  	ConnSuite
    23  
    24  	machine *state.Machine
    25  
    26  	otherState        *state.State
    27  	otherStateMachine *state.Machine
    28  }
    29  
    30  var _ = gc.Suite(&ipAddressesStateSuite{})
    31  
    32  type AddressSorter []*state.Address
    33  
    34  func (a AddressSorter) Len() int           { return len(a) }
    35  func (a AddressSorter) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
    36  func (a AddressSorter) Less(i, j int) bool { return a[i].DocID() < a[j].DocID() }
    37  
    38  var _ sort.Interface = (AddressSorter)(nil)
    39  
    40  func (s *ipAddressesStateSuite) SetUpTest(c *gc.C) {
    41  	s.ConnSuite.SetUpTest(c)
    42  
    43  	var err error
    44  	s.machine, err = s.State.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
    45  	c.Assert(err, jc.ErrorIsNil)
    46  
    47  	s.otherState = s.NewStateForModelNamed(c, "other-model")
    48  	s.otherStateMachine, err = s.otherState.AddMachine(state.UbuntuBase("12.10"), state.JobHostUnits)
    49  	c.Assert(err, jc.ErrorIsNil)
    50  
    51  	// Add the few subnets used by the tests into both models.
    52  	subnetInfos := []network.SubnetInfo{{
    53  		CIDR: "0.1.2.0/24",
    54  	}, {
    55  		CIDR: "fc00::/64",
    56  	}, {
    57  		CIDR: "10.20.0.0/16",
    58  	}, {
    59  		CIDR: "30.30.30.0/24",
    60  	}, {
    61  		CIDR: "252.80.0.0/12",
    62  		FanInfo: &network.FanCIDRs{
    63  			FanLocalUnderlay: "30.30.30.0/24",
    64  			FanOverlay:       "252.0.0.0/8",
    65  		},
    66  	}}
    67  	for _, info := range subnetInfos {
    68  		_, err = s.State.AddSubnet(info)
    69  		c.Check(err, jc.ErrorIsNil)
    70  		_, err = s.otherState.AddSubnet(info)
    71  		c.Check(err, jc.ErrorIsNil)
    72  	}
    73  }
    74  
    75  func (s *ipAddressesStateSuite) TestMachineMethodReturnsMachine(c *gc.C) {
    76  	_, addresses := s.addNamedDeviceWithAddresses(c, "eth0", "0.1.2.3/24")
    77  
    78  	result, err := addresses[0].Machine()
    79  	c.Assert(err, jc.ErrorIsNil)
    80  	c.Assert(result, jc.DeepEquals, s.machine)
    81  }
    82  
    83  func (s *ipAddressesStateSuite) addNamedDeviceWithAddresses(
    84  	c *gc.C, name string, addresses ...string,
    85  ) (*state.LinkLayerDevice, []*state.Address) {
    86  	device := s.addNamedDevice(c, name)
    87  
    88  	addressesArgs := make([]state.LinkLayerDeviceAddress, len(addresses))
    89  	for i, address := range addresses {
    90  		addressesArgs[i] = state.LinkLayerDeviceAddress{
    91  			DeviceName:   name,
    92  			ConfigMethod: network.ConfigStatic,
    93  			CIDRAddress:  address,
    94  		}
    95  	}
    96  	err := s.machine.SetDevicesAddresses(addressesArgs...)
    97  	c.Assert(err, jc.ErrorIsNil)
    98  	deviceAddresses, err := device.Addresses()
    99  	c.Assert(err, jc.ErrorIsNil)
   100  	c.Assert(deviceAddresses, gc.HasLen, len(addresses))
   101  	return device, deviceAddresses
   102  }
   103  
   104  func (s *ipAddressesStateSuite) addNamedDevice(c *gc.C, name string) *state.LinkLayerDevice {
   105  	return s.addNamedDeviceForMachine(c, name, s.machine)
   106  }
   107  
   108  func (s *ipAddressesStateSuite) addNamedDeviceForMachine(
   109  	c *gc.C, name string, machine *state.Machine,
   110  ) *state.LinkLayerDevice {
   111  	deviceArgs := state.LinkLayerDeviceArgs{
   112  		Name: name,
   113  		Type: network.EthernetDevice,
   114  	}
   115  	err := machine.SetLinkLayerDevices(deviceArgs)
   116  	c.Assert(err, jc.ErrorIsNil)
   117  	device, err := machine.LinkLayerDevice(name)
   118  	c.Assert(err, jc.ErrorIsNil)
   119  	return device
   120  }
   121  
   122  func (s *ipAddressesStateSuite) TestMachineMethodReturnsNotFoundErrorWhenMissing(c *gc.C) {
   123  	_, addresses := s.addNamedDeviceWithAddresses(c, "eth0", "0.1.2.3/24")
   124  	s.ensureMachineDeadAndRemove(c, s.machine)
   125  
   126  	result, err := addresses[0].Machine()
   127  	c.Assert(err, gc.ErrorMatches, "machine 0 not found")
   128  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   129  	c.Assert(result, gc.IsNil)
   130  }
   131  
   132  func (s *ipAddressesStateSuite) ensureMachineDeadAndRemove(c *gc.C, machine *state.Machine) {
   133  	s.ensureEntityDeadAndRemoved(c, machine)
   134  }
   135  
   136  type ensureDeaderRemover interface {
   137  	state.EnsureDeader
   138  	state.Remover
   139  }
   140  
   141  func (s *ipAddressesStateSuite) ensureEntityDeadAndRemoved(c *gc.C, entity ensureDeaderRemover) {
   142  	err := entity.EnsureDead()
   143  	c.Assert(err, jc.ErrorIsNil)
   144  	err = entity.Remove()
   145  	c.Assert(err, jc.ErrorIsNil)
   146  }
   147  
   148  func (s *ipAddressesStateSuite) TestDeviceMethodReturnsLinkLayerDevice(c *gc.C) {
   149  	addedDevice, addresses := s.addNamedDeviceWithAddresses(c, "eth0", "0.1.2.3/24")
   150  
   151  	returnedDevice, err := addresses[0].Device()
   152  	c.Assert(err, jc.ErrorIsNil)
   153  	c.Assert(returnedDevice, jc.DeepEquals, addedDevice)
   154  }
   155  
   156  func (s *ipAddressesStateSuite) TestDeviceMethodReturnsNotFoundErrorWhenMissing(c *gc.C) {
   157  	device, addresses := s.addNamedDeviceWithAddresses(c, "eth0", "0.1.2.3/24")
   158  	err := device.Remove()
   159  	c.Assert(err, jc.ErrorIsNil)
   160  
   161  	result, err := addresses[0].Device()
   162  	c.Assert(result, gc.IsNil)
   163  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   164  	c.Assert(err, gc.ErrorMatches, `device with ID .+ not found`)
   165  }
   166  
   167  func (s *ipAddressesStateSuite) TestSubnetMethodReturnsSubnet(c *gc.C) {
   168  	_, addresses := s.addNamedDeviceWithAddresses(c, "eth0", "10.20.30.41/16")
   169  
   170  	result, err := addresses[0].Subnet()
   171  	c.Assert(err, jc.ErrorIsNil)
   172  	c.Assert(result.CIDR(), gc.Equals, "10.20.0.0/16")
   173  }
   174  
   175  func (s *ipAddressesStateSuite) TestSubnetMethodReturnsNotFoundErrorWhenMissing(c *gc.C) {
   176  	_, addresses := s.addNamedDeviceWithAddresses(c, "eth0", "10.20.30.41/16")
   177  	subnet, err := s.State.SubnetByCIDR("10.20.0.0/16")
   178  	c.Assert(err, jc.ErrorIsNil)
   179  	s.ensureEntityDeadAndRemoved(c, subnet)
   180  
   181  	result, err := addresses[0].Subnet()
   182  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   183  	c.Assert(err, gc.ErrorMatches, `subnet "10.20.0.0/16" not found`)
   184  	c.Assert(result, gc.IsNil)
   185  }
   186  
   187  func (s *ipAddressesStateSuite) TestSubnetMethodReturnsNotFoundErrorWithUnknownOrLocalSubnet(c *gc.C) {
   188  	cidrs := []string{"127.0.0.0/8", "::1/128", "8.8.0.0/16"}
   189  	missingCIDRs := set.NewStrings(cidrs...)
   190  	_, addresses := s.addNamedDeviceWithAddresses(c, "eth0", cidrs...)
   191  
   192  	for _, address := range addresses {
   193  		result, err := address.Subnet()
   194  		c.Check(result, gc.IsNil)
   195  		c.Check(err, jc.Satisfies, errors.IsNotFound)
   196  		expectedError := fmt.Sprintf("subnet %q not found", address.SubnetCIDR())
   197  		c.Check(err, gc.ErrorMatches, expectedError)
   198  		missingCIDRs.Remove(address.SubnetCIDR())
   199  	}
   200  	c.Check(missingCIDRs.SortedValues(), gc.DeepEquals, []string{})
   201  }
   202  
   203  func (s *ipAddressesStateSuite) TestRemoveSuccess(c *gc.C) {
   204  	_, existingAddresses := s.addNamedDeviceWithAddresses(c, "eth0", "0.1.2.3/24")
   205  
   206  	s.removeAddressAndAssertSuccess(c, existingAddresses[0])
   207  	s.assertNoAddressesOnMachine(c, s.machine)
   208  }
   209  
   210  func (s *ipAddressesStateSuite) removeAddressAndAssertSuccess(c *gc.C, givenAddress *state.Address) {
   211  	err := givenAddress.Remove()
   212  	c.Assert(err, jc.ErrorIsNil)
   213  }
   214  
   215  func (s *ipAddressesStateSuite) assertNoAddressesOnMachine(c *gc.C, machine *state.Machine) {
   216  	s.assertAllAddressesOnMachineMatchCount(c, machine, 0)
   217  }
   218  
   219  func (s *ipAddressesStateSuite) assertAllAddressesOnMachineMatchCount(
   220  	c *gc.C, machine *state.Machine, expectedCount int,
   221  ) {
   222  	results, err := machine.AllDeviceAddresses()
   223  	c.Assert(err, jc.ErrorIsNil)
   224  	c.Assert(results, gc.HasLen, expectedCount, gc.Commentf(
   225  		"expected %d, got %d: %+v", expectedCount, len(results), results))
   226  }
   227  
   228  func (s *ipAddressesStateSuite) TestRemoveTwiceStillSucceeds(c *gc.C) {
   229  	_, existingAddresses := s.addNamedDeviceWithAddresses(c, "eth0", "0.1.2.3/24")
   230  
   231  	s.removeAddressAndAssertSuccess(c, existingAddresses[0])
   232  	s.removeAddressAndAssertSuccess(c, existingAddresses[0])
   233  	s.assertNoAddressesOnMachine(c, s.machine)
   234  }
   235  
   236  func (s *ipAddressesStateSuite) TestLinkLayerDeviceAddressesReturnsAllDeviceAddresses(c *gc.C) {
   237  	device, addedAddresses := s.addNamedDeviceWithAddresses(c, "eth0", "0.1.2.3/24", "10.20.30.40/16", "fc00::/64")
   238  	s.assertAllAddressesOnMachineMatchCount(c, s.machine, 3)
   239  
   240  	resultAddresses, err := device.Addresses()
   241  	c.Assert(err, jc.ErrorIsNil)
   242  	c.Assert(resultAddresses, jc.DeepEquals, addedAddresses)
   243  }
   244  
   245  func (s *ipAddressesStateSuite) TestLinkLayerDeviceRemoveAddressesSuccess(c *gc.C) {
   246  	device, _ := s.addNamedDeviceWithAddresses(c, "eth0", "10.20.30.40/16", "fc00::/64")
   247  	s.assertAllAddressesOnMachineMatchCount(c, s.machine, 2)
   248  
   249  	s.removeDeviceAddressesAndAssertNoneRemainOnMachine(c, device)
   250  }
   251  
   252  func (s *ipAddressesStateSuite) removeDeviceAddressesAndAssertNoneRemainOnMachine(
   253  	c *gc.C, device *state.LinkLayerDevice,
   254  ) {
   255  	err := device.RemoveAddresses()
   256  	c.Assert(err, jc.ErrorIsNil)
   257  	s.assertNoAddressesOnMachine(c, s.machine)
   258  }
   259  
   260  func (s *ipAddressesStateSuite) TestLinkLayerDeviceRemoveAddressesTwiceStillSucceeds(c *gc.C) {
   261  	device, _ := s.addNamedDeviceWithAddresses(c, "eth0", "10.20.30.40/16", "fc00::/64")
   262  	s.assertAllAddressesOnMachineMatchCount(c, s.machine, 2)
   263  
   264  	s.removeDeviceAddressesAndAssertNoneRemainOnMachine(c, device)
   265  	s.removeDeviceAddressesAndAssertNoneRemainOnMachine(c, device)
   266  }
   267  
   268  func (s *ipAddressesStateSuite) TestMachineRemoveAllAddressesSuccess(c *gc.C) {
   269  	s.addTwoDevicesWithTwoAddressesEach(c)
   270  	s.removeAllAddressesOnMachineAndAssertNoneRemain(c)
   271  }
   272  
   273  func (s *ipAddressesStateSuite) TestMachineRemoveAllAddressesRemovesProviderIDReferences(c *gc.C) {
   274  	s.addNamedDevice(c, "foo")
   275  	addrArgs := state.LinkLayerDeviceAddress{
   276  		DeviceName:   "foo",
   277  		ConfigMethod: network.ConfigStatic,
   278  		CIDRAddress:  "0.1.2.3/24",
   279  		ProviderID:   "bar",
   280  	}
   281  	err := s.machine.SetDevicesAddresses(addrArgs)
   282  	c.Assert(err, jc.ErrorIsNil)
   283  	s.removeAllAddressesOnMachineAndAssertNoneRemain(c)
   284  
   285  	// Re-adding the same address to a new device should now succeed.
   286  	err = s.machine.SetDevicesAddresses(addrArgs)
   287  	c.Assert(err, jc.ErrorIsNil)
   288  }
   289  
   290  func (s *ipAddressesStateSuite) addTwoDevicesWithTwoAddressesEach(c *gc.C) []*state.Address {
   291  	_, device1Addresses := s.addNamedDeviceWithAddresses(c, "eth1", "10.20.0.1/16", "10.20.0.2/16")
   292  	_, device2Addresses := s.addNamedDeviceWithAddresses(c, "eth0", "10.20.100.2/16", "fc00::/64")
   293  	s.assertAllAddressesOnMachineMatchCount(c, s.machine, 4)
   294  	addresses := append(device1Addresses, device2Addresses...)
   295  	sort.Sort(AddressSorter(addresses))
   296  	return addresses
   297  }
   298  
   299  func (s *ipAddressesStateSuite) removeAllAddressesOnMachineAndAssertNoneRemain(c *gc.C) {
   300  	err := s.machine.RemoveAllAddresses()
   301  	c.Assert(err, jc.ErrorIsNil)
   302  	s.assertNoAddressesOnMachine(c, s.machine)
   303  }
   304  
   305  func (s *ipAddressesStateSuite) TestMachineRemoveAllAddressesTwiceStillSucceeds(c *gc.C) {
   306  	s.addTwoDevicesWithTwoAddressesEach(c)
   307  	s.removeAllAddressesOnMachineAndAssertNoneRemain(c)
   308  	s.removeAllAddressesOnMachineAndAssertNoneRemain(c)
   309  }
   310  
   311  func (s *ipAddressesStateSuite) TestMachineAllAddressesSuccess(c *gc.C) {
   312  	addedAddresses := s.addTwoDevicesWithTwoAddressesEach(c)
   313  
   314  	allAddresses, err := s.machine.AllDeviceAddresses()
   315  	sort.Sort(AddressSorter(allAddresses))
   316  	c.Assert(err, jc.ErrorIsNil)
   317  	c.Assert(allAddresses, jc.DeepEquals, addedAddresses)
   318  }
   319  
   320  func (s *ipAddressesStateSuite) TestLinkLayerDeviceRemoveAlsoRemovesDeviceAddresses(c *gc.C) {
   321  	device, _ := s.addNamedDeviceWithAddresses(c, "eth0", "10.20.30.40/16", "fc00::/64")
   322  	s.assertAllAddressesOnMachineMatchCount(c, s.machine, 2)
   323  
   324  	err := device.Remove()
   325  	c.Assert(err, jc.ErrorIsNil)
   326  	s.assertNoAddressesOnMachine(c, s.machine)
   327  }
   328  
   329  func (s *ipAddressesStateSuite) TestMachineRemoveAlsoRemovesAllAddresses(c *gc.C) {
   330  	s.addTwoDevicesWithTwoAddressesEach(c)
   331  	s.ensureMachineDeadAndRemove(c, s.machine)
   332  	s.assertNoAddressesOnMachine(c, s.machine)
   333  }
   334  
   335  func (s *ipAddressesStateSuite) TestAllSpacesHandlesUnknownSubnets(c *gc.C) {
   336  	// This is not one of the registered subnets
   337  	s.addNamedDeviceWithAddresses(c, "eth0", "172.12.0.10/24")
   338  	spaces, err := s.machine.AllSpaces()
   339  	c.Assert(err, jc.ErrorIsNil)
   340  	c.Check(spaces.SortedValues(), gc.DeepEquals, []string{})
   341  }
   342  
   343  func resetSubnet(c *gc.C, st *state.State, subnetInfo network.SubnetInfo) {
   344  	// TODO (hml) 2019-07-26
   345  	// This comment is no longer valid.  Changes are in progress.
   346  	// Update when complete.
   347  	//
   348  	// We currently don't allow updating a subnet's information, so remove it
   349  	// and add it with the new value.
   350  	// XXX(jam): We should add mutation operations instead of this ugly hack
   351  	subnet, err := st.SubnetByCIDR(subnetInfo.CIDR)
   352  	c.Assert(err, jc.ErrorIsNil)
   353  	err = subnet.EnsureDead()
   354  	c.Assert(err, jc.ErrorIsNil)
   355  	err = subnet.Remove()
   356  	c.Assert(err, jc.ErrorIsNil)
   357  	_, err = st.AddSubnet(subnetInfo)
   358  	c.Assert(err, jc.ErrorIsNil)
   359  }
   360  
   361  func (s *ipAddressesStateSuite) TestAllSpacesOneSpace(c *gc.C) {
   362  	s.addTwoDevicesWithTwoAddressesEach(c)
   363  	space, err := s.State.AddSpace("default", "default", nil, true)
   364  	c.Assert(err, jc.ErrorIsNil)
   365  	resetSubnet(c, s.State, network.SubnetInfo{
   366  		CIDR:    "10.20.0.0/16",
   367  		SpaceID: space.Id(),
   368  	})
   369  	c.Assert(err, jc.ErrorIsNil)
   370  	resetSubnet(c, s.State, network.SubnetInfo{
   371  		CIDR:    "fc00::/64",
   372  		SpaceID: space.Id(),
   373  	})
   374  	c.Assert(err, jc.ErrorIsNil)
   375  	spaces, err := s.machine.AllSpaces()
   376  	c.Assert(err, jc.ErrorIsNil)
   377  	c.Check(spaces.SortedValues(), gc.DeepEquals, []string{space.Id()})
   378  }
   379  
   380  func (s *ipAddressesStateSuite) TestAllSpacesMultiSpace(c *gc.C) {
   381  	s.addTwoDevicesWithTwoAddressesEach(c)
   382  	space1, err := s.State.AddSpace("default", "default", nil, true)
   383  	c.Assert(err, jc.ErrorIsNil)
   384  	resetSubnet(c, s.State, network.SubnetInfo{
   385  		CIDR:    "10.20.0.0/16",
   386  		SpaceID: space1.Id(),
   387  	})
   388  	c.Assert(err, jc.ErrorIsNil)
   389  	space2, err := s.State.AddSpace("dmz-ipv6", "not-default", nil, true)
   390  	c.Assert(err, jc.ErrorIsNil)
   391  	resetSubnet(c, s.State, network.SubnetInfo{
   392  		CIDR:    "fc00::/64",
   393  		SpaceID: space2.Id(),
   394  	})
   395  	c.Assert(err, jc.ErrorIsNil)
   396  	spaces, err := s.machine.AllSpaces()
   397  	c.Assert(err, jc.ErrorIsNil)
   398  	c.Check(spaces.SortedValues(), gc.DeepEquals, []string{space1.Id(), space2.Id()})
   399  }
   400  
   401  func (s *ipAddressesStateSuite) TestAllSpacesReturnsDefaultSpace(c *gc.C) {
   402  	s.addTwoDevicesWithTwoAddressesEach(c)
   403  	spaces, err := s.machine.AllSpaces()
   404  	c.Assert(err, jc.ErrorIsNil)
   405  	c.Check(spaces.SortedValues(), gc.DeepEquals, []string{network.AlphaSpaceId})
   406  }
   407  
   408  func (s *ipAddressesStateSuite) TestSetDevicesAddressesDoesNothingWithEmptyArgs(c *gc.C) {
   409  	err := s.machine.SetDevicesAddresses() // takes varargs, which includes none.
   410  	c.Assert(err, jc.ErrorIsNil)
   411  }
   412  
   413  func (s *ipAddressesStateSuite) TestSetDevicesAddressesFailsWithEmptyCIDRAddress(c *gc.C) {
   414  	args := state.LinkLayerDeviceAddress{}
   415  	s.assertSetDevicesAddressesFailsValidationForArgs(c, args, "empty CIDRAddress not valid")
   416  }
   417  
   418  func (s *ipAddressesStateSuite) assertSetDevicesAddressesFailsValidationForArgs(
   419  	c *gc.C, args state.LinkLayerDeviceAddress, errorCauseMatches string,
   420  ) {
   421  	invalidAddressPrefix := fmt.Sprintf("invalid address %q: ", args.CIDRAddress)
   422  	err := s.assertSetDevicesAddressesFailsForArgs(c, args, invalidAddressPrefix+errorCauseMatches)
   423  	c.Assert(err, jc.Satisfies, errors.IsNotValid)
   424  }
   425  
   426  func (s *ipAddressesStateSuite) assertSetDevicesAddressesFailsForArgs(
   427  	c *gc.C, args state.LinkLayerDeviceAddress, errorCauseMatches string,
   428  ) error {
   429  	err := s.machine.SetDevicesAddresses(args)
   430  	expectedError := fmt.Sprintf(
   431  		"cannot set link-layer device addresses of machine %q: %s", s.machine.Id(), errorCauseMatches)
   432  	c.Assert(err, gc.ErrorMatches, expectedError)
   433  	return err
   434  }
   435  
   436  func (s *ipAddressesStateSuite) TestSetDevicesAddressesFailsWithInvalidCIDRAddress(c *gc.C) {
   437  	args := state.LinkLayerDeviceAddress{
   438  		CIDRAddress: "bad CIDR",
   439  	}
   440  	s.assertSetDevicesAddressesFailsValidationForArgs(c, args, "CIDRAddress: invalid CIDR address: bad CIDR")
   441  }
   442  
   443  func (s *ipAddressesStateSuite) TestSetDevicesAddressesFailsWithCIDRAddressWithoutMask(c *gc.C) {
   444  	args := state.LinkLayerDeviceAddress{
   445  		CIDRAddress: "10.10.10.10",
   446  	}
   447  	s.assertSetDevicesAddressesFailsValidationForArgs(c, args, "CIDRAddress: invalid CIDR address: 10.10.10.10")
   448  }
   449  
   450  func (s *ipAddressesStateSuite) TestSetDevicesAddressesFailsWithEmptyDeviceName(c *gc.C) {
   451  	args := state.LinkLayerDeviceAddress{
   452  		CIDRAddress: "0.1.2.3/24",
   453  	}
   454  	s.assertSetDevicesAddressesFailsValidationForArgs(c, args, "empty DeviceName not valid")
   455  }
   456  
   457  func (s *ipAddressesStateSuite) TestSetDevicesAddressesFailsWithUnknownDeviceName(c *gc.C) {
   458  	args := state.LinkLayerDeviceAddress{
   459  		CIDRAddress:  "0.1.2.3/24",
   460  		ConfigMethod: network.ConfigStatic,
   461  		DeviceName:   "missing",
   462  	}
   463  	expectedError := `invalid address "0.1.2.3/24": DeviceName "missing" on machine "0" not found`
   464  	err := s.assertSetDevicesAddressesFailsForArgs(c, args, expectedError)
   465  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   466  }
   467  
   468  func (s *ipAddressesStateSuite) TestSetDevicesAddressesFailsWithInvalidGatewayAddress(c *gc.C) {
   469  	s.addNamedDevice(c, "eth0")
   470  	args := state.LinkLayerDeviceAddress{
   471  		CIDRAddress:    "0.1.2.3/24",
   472  		DeviceName:     "eth0",
   473  		ConfigMethod:   network.ConfigStatic,
   474  		GatewayAddress: "boo hoo",
   475  	}
   476  	s.assertSetDevicesAddressesFailsValidationForArgs(c, args, `GatewayAddress "boo hoo" not valid`)
   477  }
   478  
   479  func (s *ipAddressesStateSuite) TestSetDevicesAddressesOKWhenCIDRAddressDoesNotMatchKnownSubnet(c *gc.C) {
   480  	device := s.addNamedDevice(c, "eth0")
   481  	args := state.LinkLayerDeviceAddress{
   482  		CIDRAddress:  "192.168.123.42/16",
   483  		DeviceName:   "eth0",
   484  		ConfigMethod: network.ConfigStatic,
   485  	}
   486  	err := s.machine.SetDevicesAddresses(args)
   487  	c.Assert(err, jc.ErrorIsNil)
   488  
   489  	assertDeviceHasOneAddressWithSubnetCIDREquals := func(subnetCIDR string) {
   490  		addresses, err := device.Addresses()
   491  		c.Assert(err, jc.ErrorIsNil)
   492  		c.Assert(addresses, gc.HasLen, 1)
   493  		c.Assert(addresses[0].SubnetCIDR(), gc.Equals, subnetCIDR)
   494  	}
   495  	assertDeviceHasOneAddressWithSubnetCIDREquals("192.168.0.0/16")
   496  
   497  	// Add the subnet so it's known and retry setting the same address to verify
   498  	// SubnetID gets updated.
   499  	_, err = s.State.AddSubnet(network.SubnetInfo{CIDR: "192.168.0.0/16"})
   500  	c.Assert(err, jc.ErrorIsNil)
   501  	err = s.machine.SetDevicesAddresses(args)
   502  	c.Assert(err, jc.ErrorIsNil)
   503  
   504  	assertDeviceHasOneAddressWithSubnetCIDREquals("192.168.0.0/16")
   505  }
   506  
   507  func (s *ipAddressesStateSuite) TestSetDevicesAddressesFailsWhenCIDRAddressMatchesDeadSubnet(c *gc.C) {
   508  	s.addNamedDevice(c, "eth0")
   509  	subnetCIDR := "10.20.0.0/16"
   510  	subnet, err := s.State.SubnetByCIDR(subnetCIDR)
   511  	c.Assert(err, jc.ErrorIsNil)
   512  	err = subnet.EnsureDead()
   513  	c.Assert(err, jc.ErrorIsNil)
   514  
   515  	args := state.LinkLayerDeviceAddress{
   516  		CIDRAddress:  "10.20.30.40/16",
   517  		DeviceName:   "eth0",
   518  		ConfigMethod: network.ConfigStatic,
   519  	}
   520  	expectedError := fmt.Sprintf(
   521  		"invalid address %q: subnet %q is not alive",
   522  		args.CIDRAddress, subnetCIDR,
   523  	)
   524  	_ = s.assertSetDevicesAddressesFailsForArgs(c, args, expectedError)
   525  }
   526  
   527  func (s *ipAddressesStateSuite) TestSetDevicesAddressesFailsWhenMachineNotAliveOrGone(c *gc.C) {
   528  	s.addNamedDeviceForMachine(c, "eth0", s.otherStateMachine)
   529  	err := s.otherStateMachine.EnsureDead()
   530  	c.Assert(err, jc.ErrorIsNil)
   531  
   532  	args := state.LinkLayerDeviceAddress{
   533  		CIDRAddress:  "10.20.30.40/16",
   534  		DeviceName:   "eth0",
   535  		ConfigMethod: network.ConfigStatic,
   536  	}
   537  	err = s.otherStateMachine.SetDevicesAddresses(args)
   538  	c.Assert(err, gc.ErrorMatches, `.*: machine "0" not alive`)
   539  
   540  	err = s.otherStateMachine.Remove()
   541  	c.Assert(err, jc.ErrorIsNil)
   542  
   543  	// Check it fails with a different error, as eth0 was removed along with
   544  	// otherStateMachine above.
   545  	err = s.otherStateMachine.SetDevicesAddresses(args)
   546  	c.Assert(err, gc.ErrorMatches, `.*: DeviceName "eth0" on machine "0" not found`)
   547  }
   548  
   549  func (s *ipAddressesStateSuite) TestSetDevicesAddressesUpdatesExistingDocs(c *gc.C) {
   550  	device, initialAddresses := s.addNamedDeviceWithAddresses(c, "eth0", "0.1.2.3/24", "10.20.30.42/16")
   551  
   552  	setArgs := []state.LinkLayerDeviceAddress{{
   553  		// All fields that can be set are included below.
   554  		DeviceName:       "eth0",
   555  		ConfigMethod:     network.ConfigManual,
   556  		CIDRAddress:      "0.1.2.3/24",
   557  		ProviderID:       "id-0123",
   558  		DNSServers:       []string{"ns1.example.com", "ns2.example.org"},
   559  		DNSSearchDomains: []string{"example.com", "example.org"},
   560  		GatewayAddress:   "0.1.2.1",
   561  	}, {
   562  		// No changed fields, just the required values are set: CIDRAddress +
   563  		// DeviceName (and s.machine.Id) are used to construct the DocID.
   564  		DeviceName:   "eth0",
   565  		ConfigMethod: network.ConfigStatic,
   566  		CIDRAddress:  "10.20.30.42/16",
   567  	}}
   568  	err := s.machine.SetDevicesAddresses(setArgs...)
   569  	c.Assert(err, jc.ErrorIsNil)
   570  	updatedAddresses, err := device.Addresses()
   571  	c.Assert(err, jc.ErrorIsNil)
   572  	c.Assert(updatedAddresses, gc.HasLen, len(initialAddresses))
   573  	if updatedAddresses[0].Value() != "0.1.2.3" {
   574  		// Swap the results if they arrive in different order.
   575  		updatedAddresses[1], updatedAddresses[0] = updatedAddresses[0], updatedAddresses[1]
   576  	}
   577  
   578  	for i, address := range updatedAddresses {
   579  		s.checkAddressMatchesArgs(c, address, setArgs[i])
   580  	}
   581  }
   582  
   583  func (s *ipAddressesStateSuite) TestRemoveAddressRemovesProviderID(c *gc.C) {
   584  	device := s.addNamedDevice(c, "eth0")
   585  	addrArgs := state.LinkLayerDeviceAddress{
   586  		DeviceName:   "eth0",
   587  		ConfigMethod: network.ConfigManual,
   588  		CIDRAddress:  "0.1.2.3/24",
   589  		ProviderID:   "id-0123",
   590  	}
   591  	err := s.machine.SetDevicesAddresses(addrArgs)
   592  	c.Assert(err, jc.ErrorIsNil)
   593  	addresses, err := device.Addresses()
   594  	c.Assert(err, jc.ErrorIsNil)
   595  	c.Assert(addresses, gc.HasLen, 1)
   596  	addr := addresses[0]
   597  	err = addr.Remove()
   598  	c.Assert(err, jc.ErrorIsNil)
   599  	err = s.machine.SetDevicesAddresses(addrArgs)
   600  	c.Assert(err, jc.ErrorIsNil)
   601  }
   602  
   603  func (s *ipAddressesStateSuite) TestChangeOriginOpsNoProviderID(c *gc.C) {
   604  	dev := s.addNamedDevice(c, "eth0")
   605  
   606  	addrArgs := state.LinkLayerDeviceAddress{
   607  		DeviceName:   "eth0",
   608  		ConfigMethod: network.ConfigManual,
   609  		CIDRAddress:  "0.1.2.3/24",
   610  		Origin:       network.OriginMachine,
   611  	}
   612  	err := s.machine.SetDevicesAddresses(addrArgs)
   613  	c.Assert(err, jc.ErrorIsNil)
   614  
   615  	addrs, err := dev.Addresses()
   616  	c.Assert(err, jc.ErrorIsNil)
   617  	addr := addrs[0]
   618  	c.Assert(addr.Origin(), gc.Equals, network.OriginMachine)
   619  
   620  	// No operations for setting the same origin.
   621  	c.Assert(addr.SetOriginOps(network.OriginMachine), gc.IsNil)
   622  
   623  	state.RunTransaction(c, s.State, addr.SetOriginOps(network.OriginProvider))
   624  
   625  	addrs, err = dev.Addresses()
   626  	c.Assert(err, jc.ErrorIsNil)
   627  	addr = addrs[0]
   628  	c.Assert(addr.Origin(), gc.Equals, network.OriginProvider)
   629  }
   630  
   631  func (s *ipAddressesStateSuite) TestChangeOriginOpsWithProviderID(c *gc.C) {
   632  	dev := s.addNamedDevice(c, "eth0")
   633  
   634  	addrArgs := state.LinkLayerDeviceAddress{
   635  		DeviceName:   "eth0",
   636  		ConfigMethod: network.ConfigManual,
   637  		CIDRAddress:  "0.1.2.3/24",
   638  		Origin:       network.OriginProvider,
   639  		ProviderID:   "p1",
   640  	}
   641  	err := s.machine.SetDevicesAddresses(addrArgs)
   642  	c.Assert(err, jc.ErrorIsNil)
   643  
   644  	addrs, err := dev.Addresses()
   645  	c.Assert(err, jc.ErrorIsNil)
   646  	addr := addrs[0]
   647  	c.Assert(addr.Origin(), gc.Equals, network.OriginProvider)
   648  
   649  	// No operations for setting the same origin.
   650  	c.Assert(addr.SetOriginOps(network.OriginProvider), gc.IsNil)
   651  
   652  	state.RunTransaction(c, s.State, addr.SetOriginOps(network.OriginMachine))
   653  
   654  	addrs, err = dev.Addresses()
   655  	c.Assert(err, jc.ErrorIsNil)
   656  	addr = addrs[0]
   657  	c.Assert(addr.Origin(), gc.Equals, network.OriginMachine)
   658  	c.Assert(addr.ProviderID().String(), gc.Equals, "")
   659  
   660  	// Set the address again with the provider ID.
   661  	// Success means the provider ID was removed from the global collection.
   662  	addrArgs = state.LinkLayerDeviceAddress{
   663  		DeviceName:   "eth0",
   664  		ConfigMethod: network.ConfigManual,
   665  		CIDRAddress:  "0.1.2.3/24",
   666  		Origin:       network.OriginProvider,
   667  		ProviderID:   "p1",
   668  	}
   669  	err = s.machine.SetDevicesAddresses(addrArgs)
   670  	c.Assert(err, jc.ErrorIsNil)
   671  }
   672  
   673  func (s *ipAddressesStateSuite) TestSetProviderIDOps(c *gc.C) {
   674  	dev := s.addNamedDevice(c, "eth0")
   675  
   676  	addrArgs := state.LinkLayerDeviceAddress{
   677  		DeviceName:   "eth0",
   678  		ConfigMethod: network.ConfigManual,
   679  		CIDRAddress:  "0.1.2.3/24",
   680  		Origin:       network.OriginMachine,
   681  	}
   682  	err := s.machine.SetDevicesAddresses(addrArgs)
   683  	c.Assert(err, jc.ErrorIsNil)
   684  
   685  	addrs, err := dev.Addresses()
   686  	c.Assert(err, jc.ErrorIsNil)
   687  	addr := addrs[0]
   688  	c.Assert(addr.Origin(), gc.Equals, network.OriginMachine)
   689  
   690  	ops, err := addr.SetProviderIDOps("p1")
   691  	c.Assert(err, jc.ErrorIsNil)
   692  
   693  	state.RunTransaction(c, s.State, ops)
   694  
   695  	addrs, err = dev.Addresses()
   696  	c.Assert(err, jc.ErrorIsNil)
   697  	addr = addrs[0]
   698  	c.Assert(addr.ProviderID().String(), gc.Equals, "p1")
   699  	c.Assert(addr.Origin(), gc.Equals, network.OriginProvider)
   700  
   701  	// No operations for setting the same ID.
   702  	_, err = dev.Addresses()
   703  	c.Assert(err, jc.ErrorIsNil)
   704  
   705  	ops, err = addr.SetProviderIDOps("p1")
   706  	c.Assert(err, jc.ErrorIsNil)
   707  	c.Assert(ops, gc.HasLen, 0)
   708  }
   709  
   710  func (s *ipAddressesStateSuite) TestSetProviderNetIDsOps(c *gc.C) {
   711  	dev := s.addNamedDevice(c, "eth0")
   712  
   713  	addrArgs := state.LinkLayerDeviceAddress{
   714  		DeviceName:        "eth0",
   715  		ConfigMethod:      network.ConfigManual,
   716  		CIDRAddress:       "0.1.2.3/24",
   717  		Origin:            network.OriginMachine,
   718  		ProviderNetworkID: "p-net-1",
   719  		ProviderSubnetID:  "p-sub-1",
   720  	}
   721  	err := s.machine.SetDevicesAddresses(addrArgs)
   722  	c.Assert(err, jc.ErrorIsNil)
   723  
   724  	addrs, err := dev.Addresses()
   725  	c.Assert(err, jc.ErrorIsNil)
   726  	addr := addrs[0]
   727  
   728  	ops := addr.SetProviderNetIDsOps("p-net-1", "p-sub-1")
   729  	c.Assert(ops, gc.HasLen, 0)
   730  
   731  	ops = addr.SetProviderNetIDsOps("p-net-2", "p-sub-2")
   732  	state.RunTransaction(c, s.State, ops)
   733  
   734  	addrs, err = dev.Addresses()
   735  	c.Assert(err, jc.ErrorIsNil)
   736  	addr = addrs[0]
   737  
   738  	c.Assert(addr.ProviderNetworkID().String(), gc.Equals, "p-net-2")
   739  	c.Assert(addr.ProviderSubnetID().String(), gc.Equals, "p-sub-2")
   740  }
   741  
   742  func (s *ipAddressesStateSuite) TestUpdateOps(c *gc.C) {
   743  	dev := s.addNamedDevice(c, "eth0")
   744  
   745  	addrArgs := state.LinkLayerDeviceAddress{
   746  		DeviceName:   "eth0",
   747  		ConfigMethod: network.ConfigManual,
   748  		CIDRAddress:  "0.1.2.3/24",
   749  		Origin:       network.OriginMachine,
   750  	}
   751  	err := s.machine.SetDevicesAddresses(addrArgs)
   752  	c.Assert(err, jc.ErrorIsNil)
   753  
   754  	addrs, err := dev.Addresses()
   755  	c.Assert(err, jc.ErrorIsNil)
   756  
   757  	ops, err := addrs[0].UpdateOps(state.LinkLayerDeviceAddress{
   758  		DeviceName:     "eth0",
   759  		ConfigMethod:   network.ConfigManual,
   760  		CIDRAddress:    "0.1.2.3/24",
   761  		Origin:         network.OriginMachine,
   762  		GatewayAddress: "0.1.2.0",
   763  		IsSecondary:    true,
   764  	})
   765  	c.Assert(err, jc.ErrorIsNil)
   766  
   767  	state.RunTransaction(c, s.State, ops)
   768  
   769  	addrs, err = dev.Addresses()
   770  	c.Assert(err, jc.ErrorIsNil)
   771  	c.Check(addrs[0].GatewayAddress(), gc.Equals, "0.1.2.0")
   772  	c.Check(addrs[0].IsSecondary(), gc.Equals, true)
   773  }
   774  
   775  func (s *ipAddressesStateSuite) TestUpdateAddressFailsToChangeProviderID(c *gc.C) {
   776  	s.addNamedDevice(c, "eth0")
   777  	addrArgs := state.LinkLayerDeviceAddress{
   778  		DeviceName:   "eth0",
   779  		ConfigMethod: network.ConfigManual,
   780  		CIDRAddress:  "0.1.2.3/24",
   781  		ProviderID:   "id-0123",
   782  	}
   783  	err := s.machine.SetDevicesAddresses(addrArgs)
   784  	c.Assert(err, jc.ErrorIsNil)
   785  	addrArgs.ProviderID = "id-0124"
   786  	err = s.machine.SetDevicesAddresses(addrArgs)
   787  	c.Assert(err, gc.NotNil)
   788  }
   789  
   790  func (s *ipAddressesStateSuite) TestUpdateAddressPreventsDuplicateProviderID(c *gc.C) {
   791  	s.addNamedDevice(c, "eth0")
   792  	addrArgs := state.LinkLayerDeviceAddress{
   793  		DeviceName:   "eth0",
   794  		ConfigMethod: network.ConfigManual,
   795  		CIDRAddress:  "0.1.2.3/24",
   796  	}
   797  	err := s.machine.SetDevicesAddresses(addrArgs)
   798  	c.Assert(err, jc.ErrorIsNil)
   799  
   800  	// Set the provider id through an update.
   801  	addrArgs.ProviderID = "id-0123"
   802  	err = s.machine.SetDevicesAddresses(addrArgs)
   803  	c.Assert(err, jc.ErrorIsNil)
   804  
   805  	// Adding a new address with the same provider id should now fail.
   806  	addrArgs.CIDRAddress = "0.1.2.4/24"
   807  	err = s.machine.SetDevicesAddresses(addrArgs)
   808  	c.Assert(err, gc.NotNil)
   809  }
   810  
   811  func (s *ipAddressesStateSuite) checkAddressMatchesArgs(
   812  	c *gc.C, address *state.Address, args state.LinkLayerDeviceAddress,
   813  ) {
   814  	c.Check(address.DeviceName(), gc.Equals, args.DeviceName)
   815  	c.Check(address.MachineID(), gc.Equals, s.machine.Id())
   816  	c.Check(args.CIDRAddress, jc.HasPrefix, address.Value())
   817  	c.Check(address.ConfigMethod(), gc.Equals, args.ConfigMethod)
   818  	c.Check(address.ProviderID(), gc.Equals, args.ProviderID)
   819  	c.Check(address.DNSServers(), jc.DeepEquals, args.DNSServers)
   820  	c.Check(address.DNSSearchDomains(), jc.DeepEquals, args.DNSSearchDomains)
   821  	c.Check(address.GatewayAddress(), gc.Equals, args.GatewayAddress)
   822  }
   823  
   824  func (s *ipAddressesStateSuite) TestSetDevicesAddressesWithMultipleUpdatesOfSameDocLastUpdateWins(c *gc.C) {
   825  	device, initialAddresses := s.addNamedDeviceWithAddresses(c, "eth0", "0.1.2.3/24")
   826  
   827  	setArgs := []state.LinkLayerDeviceAddress{{
   828  		// No changes - same args as used by addNamedDeviceWithAddresses, so
   829  		// this is testing a no-op case.
   830  		DeviceName:   "eth0",
   831  		ConfigMethod: network.ConfigStatic,
   832  		CIDRAddress:  "0.1.2.3/24",
   833  	}, {
   834  		// Change all fields that can change.
   835  		DeviceName:       "eth0",
   836  		ConfigMethod:     network.ConfigManual,
   837  		CIDRAddress:      "0.1.2.3/24",
   838  		ProviderID:       "id-0123",
   839  		DNSServers:       []string{"ns1.example.com", "ns2.example.org"},
   840  		DNSSearchDomains: []string{"example.com", "example.org"},
   841  		GatewayAddress:   "0.1.2.1",
   842  	}, {
   843  		// Test deletes work for DNS settings, also change method, and gateway.
   844  		DeviceName:       "eth0",
   845  		ConfigMethod:     network.ConfigDHCP,
   846  		CIDRAddress:      "0.1.2.3/24",
   847  		ProviderID:       "id-0123", // not allowed to change ProviderID once set
   848  		DNSServers:       nil,
   849  		DNSSearchDomains: nil,
   850  		GatewayAddress:   "0.1.2.2",
   851  	}}
   852  	for _, arg := range setArgs {
   853  		err := s.machine.SetDevicesAddresses(arg)
   854  		c.Assert(err, jc.ErrorIsNil)
   855  	}
   856  	updatedAddresses, err := device.Addresses()
   857  	c.Assert(err, jc.ErrorIsNil)
   858  	c.Assert(updatedAddresses, gc.HasLen, len(initialAddresses))
   859  
   860  	var lastArgsIndex = len(setArgs) - 1
   861  	s.checkAddressMatchesArgs(c, updatedAddresses[0], state.LinkLayerDeviceAddress{
   862  		DeviceName:       setArgs[lastArgsIndex].DeviceName,
   863  		ConfigMethod:     setArgs[lastArgsIndex].ConfigMethod,
   864  		CIDRAddress:      setArgs[lastArgsIndex].CIDRAddress,
   865  		ProviderID:       setArgs[lastArgsIndex].ProviderID,
   866  		DNSServers:       setArgs[lastArgsIndex].DNSServers,
   867  		DNSSearchDomains: setArgs[lastArgsIndex].DNSSearchDomains,
   868  		GatewayAddress:   setArgs[lastArgsIndex].GatewayAddress,
   869  	})
   870  }
   871  
   872  func (s *ipAddressesStateSuite) TestSetDevicesAddressesMultipleDevicesWithSameAddress(c *gc.C) {
   873  	_ = s.addNamedDeviceForMachine(c, "eth2", s.machine)
   874  	_ = s.addNamedDeviceForMachine(c, "br0", s.machine)
   875  
   876  	// This is a valid scenario that was observed with a MAAS machine.
   877  	// eth2 had an address and provider ID managed by MAAS.
   878  	// eth2 and eth4 were bonded to form bond0.
   879  	// bond0 was bridged by br0.
   880  
   881  	providerID := "42"
   882  	addressArgs := []state.LinkLayerDeviceAddress{
   883  		{
   884  			DeviceName:   "eth2",
   885  			ConfigMethod: network.ConfigStatic,
   886  			CIDRAddress:  "0.1.2.3/24",
   887  			ProviderID:   network.Id(providerID),
   888  		},
   889  		{
   890  			DeviceName:   "br0",
   891  			ConfigMethod: network.ConfigStatic,
   892  			CIDRAddress:  "0.1.2.3/24",
   893  			ProviderID:   network.Id(providerID),
   894  		},
   895  	}
   896  
   897  	err := s.machine.SetDevicesAddresses(addressArgs...)
   898  	c.Assert(err, jc.ErrorIsNil)
   899  
   900  	// Check that we can still change one of the addresses.
   901  	addressArgs[0].ConfigMethod = network.ConfigDHCP
   902  	err = s.machine.SetDevicesAddresses(addressArgs[0])
   903  	c.Assert(err, jc.ErrorIsNil)
   904  }
   905  
   906  func (s *ipAddressesStateSuite) TestSetDevicesAddressesMultipleDevicesWithSameAddressDifferentProviderIDFails(c *gc.C) {
   907  	_ = s.addNamedDeviceForMachine(c, "eth2", s.machine)
   908  	_ = s.addNamedDeviceForMachine(c, "br0", s.machine)
   909  
   910  	providerID := "42"
   911  	addressArgs := []state.LinkLayerDeviceAddress{
   912  		{
   913  			DeviceName:   "eth2",
   914  			ConfigMethod: network.ConfigStatic,
   915  			CIDRAddress:  "0.1.2.3/24",
   916  			ProviderID:   network.Id(providerID),
   917  		},
   918  		{
   919  			DeviceName:   "br0",
   920  			ConfigMethod: network.ConfigStatic,
   921  			CIDRAddress:  "0.1.2.4/24",
   922  			ProviderID:   network.Id(providerID),
   923  		},
   924  	}
   925  
   926  	err := s.machine.SetDevicesAddresses(addressArgs...)
   927  	c.Assert(err, gc.ErrorMatches, `.*multiple addresses "0.1.2.3", "0.1.2.4": provider IDs not unique: 42`)
   928  }
   929  
   930  func (s *ipAddressesStateSuite) TestSetDevicesAddressesWithDuplicateProviderIDFailsInSameModel(c *gc.C) {
   931  	_, firstAddressArgs := s.addDeviceWithAddressAndProviderIDForMachine(c, "42", s.machine)
   932  	secondAddressArgs := firstAddressArgs
   933  	secondAddressArgs.CIDRAddress = "10.20.30.40/16"
   934  
   935  	err := s.machine.SetDevicesAddresses(secondAddressArgs)
   936  	c.Assert(err, gc.NotNil)
   937  }
   938  
   939  func (s *ipAddressesStateSuite) TestSetDevicesAddressesWithDuplicateProviderIDSucceedsInDifferentModel(c *gc.C) {
   940  	_, firstAddressArgs := s.addDeviceWithAddressAndProviderIDForMachine(c, "42", s.otherStateMachine)
   941  	secondAddressArgs := firstAddressArgs
   942  	secondAddressArgs.CIDRAddress = "10.20.30.40/16"
   943  
   944  	s.addNamedDevice(c, firstAddressArgs.DeviceName) // for s.machine
   945  	err := s.machine.SetDevicesAddresses(secondAddressArgs)
   946  	c.Assert(err, jc.ErrorIsNil)
   947  }
   948  
   949  func (s *ipAddressesStateSuite) addDeviceWithAddressAndProviderIDForMachine(
   950  	c *gc.C, providerID string, machine *state.Machine,
   951  ) (*state.LinkLayerDevice, state.LinkLayerDeviceAddress) {
   952  	device := s.addNamedDeviceForMachine(c, "eth0", machine)
   953  	addressArgs := state.LinkLayerDeviceAddress{
   954  		DeviceName:   "eth0",
   955  		ConfigMethod: network.ConfigStatic,
   956  		CIDRAddress:  "0.1.2.3/24",
   957  		ProviderID:   network.Id(providerID),
   958  	}
   959  	err := machine.SetDevicesAddresses(addressArgs)
   960  	c.Assert(err, jc.ErrorIsNil)
   961  	return device, addressArgs
   962  }