github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/state/subnets_test.go (about)

     1  // Copyright 2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package state_test
     5  
     6  import (
     7  	"fmt"
     8  
     9  	"github.com/juju/errors"
    10  	jc "github.com/juju/testing/checkers"
    11  	gc "gopkg.in/check.v1"
    12  
    13  	"github.com/juju/juju/state"
    14  )
    15  
    16  type SubnetSuite struct {
    17  	ConnSuite
    18  }
    19  
    20  var _ = gc.Suite(&SubnetSuite{})
    21  
    22  func (s *SubnetSuite) TestAddSubnetSucceedsWithFullyPopulatedInfo(c *gc.C) {
    23  	subnetInfo := state.SubnetInfo{
    24  		ProviderId:       "foo",
    25  		CIDR:             "192.168.1.0/24",
    26  		VLANTag:          79,
    27  		AvailabilityZone: "Timbuktu",
    28  		SpaceName:        "foo",
    29  	}
    30  
    31  	subnet, err := s.State.AddSubnet(subnetInfo)
    32  	c.Assert(err, jc.ErrorIsNil)
    33  	s.assertSubnetMatchesInfo(c, subnet, subnetInfo)
    34  
    35  	// check it's been stored in state by fetching it back again
    36  	subnetFromDB, err := s.State.Subnet("192.168.1.0/24")
    37  	c.Assert(err, jc.ErrorIsNil)
    38  	s.assertSubnetMatchesInfo(c, subnetFromDB, subnetInfo)
    39  }
    40  
    41  func (s *SubnetSuite) assertSubnetMatchesInfo(c *gc.C, subnet *state.Subnet, info state.SubnetInfo) {
    42  	c.Assert(subnet.ProviderId(), gc.Equals, info.ProviderId)
    43  	c.Assert(subnet.CIDR(), gc.Equals, info.CIDR)
    44  	c.Assert(subnet.VLANTag(), gc.Equals, info.VLANTag)
    45  	c.Assert(subnet.AvailabilityZone(), gc.Equals, info.AvailabilityZone)
    46  	c.Assert(subnet.String(), gc.Equals, info.CIDR)
    47  	c.Assert(subnet.GoString(), gc.Equals, info.CIDR)
    48  	c.Assert(subnet.SpaceName(), gc.Equals, info.SpaceName)
    49  }
    50  
    51  func (s *SubnetSuite) TestAddSubnetFailsWithEmptyCIDR(c *gc.C) {
    52  	subnetInfo := state.SubnetInfo{}
    53  	s.assertAddSubnetForInfoFailsWithSuffix(c, subnetInfo, "missing CIDR")
    54  }
    55  
    56  func (s *SubnetSuite) assertAddSubnetForInfoFailsWithSuffix(c *gc.C, subnetInfo state.SubnetInfo, errorSuffix string) error {
    57  	subnet, err := s.State.AddSubnet(subnetInfo)
    58  	errorMessage := fmt.Sprintf("adding subnet %q: %s", subnetInfo.CIDR, errorSuffix)
    59  	c.Assert(err, gc.ErrorMatches, errorMessage)
    60  	c.Assert(subnet, gc.IsNil)
    61  	return err
    62  }
    63  
    64  func (s *SubnetSuite) TestAddSubnetFailsWithInvalidCIDR(c *gc.C) {
    65  	subnetInfo := state.SubnetInfo{CIDR: "foobar"}
    66  	s.assertAddSubnetForInfoFailsWithSuffix(c, subnetInfo, "invalid CIDR address: foobar")
    67  }
    68  
    69  func (s *SubnetSuite) TestAddSubnetFailsWithOutOfRangeVLANTag(c *gc.C) {
    70  	subnetInfo := state.SubnetInfo{CIDR: "192.168.0.1/24", VLANTag: 4095}
    71  	s.assertAddSubnetForInfoFailsWithSuffix(c, subnetInfo, "invalid VLAN tag 4095: must be between 0 and 4094")
    72  }
    73  
    74  func (s *SubnetSuite) TestAddSubnetFailsWithAlreadyExistsForDuplicateCIDRInSameModel(c *gc.C) {
    75  	subnetInfo := state.SubnetInfo{CIDR: "192.168.0.1/24"}
    76  	subnet, err := s.State.AddSubnet(subnetInfo)
    77  	c.Assert(err, jc.ErrorIsNil)
    78  	s.assertSubnetMatchesInfo(c, subnet, subnetInfo)
    79  
    80  	err = s.assertAddSubnetForInfoFailsWithSuffix(c, subnetInfo, `subnet "192.168.0.1/24" already exists`)
    81  	c.Assert(err, jc.Satisfies, errors.IsAlreadyExists)
    82  }
    83  
    84  func (s *SubnetSuite) TestAddSubnetSucceedsForDuplicateCIDRInDifferentModels(c *gc.C) {
    85  	subnetInfo1 := state.SubnetInfo{CIDR: "192.168.0.1/24"}
    86  	subnetInfo2 := state.SubnetInfo{CIDR: "10.0.0.0/24"}
    87  	subnet1State := s.NewStateForModelNamed(c, "other-model")
    88  
    89  	subnet1, subnet2 := s.addTwoSubnetsInDifferentModelsAssertSuccessAndReturnBoth(c, subnetInfo1, subnetInfo2, subnet1State)
    90  	s.assertSubnetMatchesInfo(c, subnet1, subnetInfo1)
    91  	s.assertSubnetMatchesInfo(c, subnet2, subnetInfo2)
    92  }
    93  
    94  func (s *SubnetSuite) addTwoSubnetsInDifferentModelsAssertSuccessAndReturnBoth(c *gc.C, info1, info2 state.SubnetInfo, otherState *state.State) (*state.Subnet, *state.Subnet) {
    95  	subnet1, err := otherState.AddSubnet(info1)
    96  	c.Assert(err, jc.ErrorIsNil)
    97  	subnet2, err := s.State.AddSubnet(info2)
    98  	c.Assert(err, jc.ErrorIsNil)
    99  
   100  	return subnet1, subnet2
   101  }
   102  
   103  func (s *SubnetSuite) TestAddSubnetFailsWhenProviderIdNotUniqueInSameModel(c *gc.C) {
   104  	subnetInfo1 := state.SubnetInfo{CIDR: "192.168.0.1/24", ProviderId: "foo"}
   105  	subnetInfo2 := state.SubnetInfo{CIDR: "10.0.0.0/24", ProviderId: "foo"}
   106  
   107  	s.addTwoSubnetsAndAssertSecondFailsWithSuffix(c, subnetInfo1, subnetInfo2, `ProviderId "foo" not unique`)
   108  }
   109  
   110  func (s *SubnetSuite) addTwoSubnetsAndAssertSecondFailsWithSuffix(c *gc.C, info1, info2 state.SubnetInfo, errorSuffix string) {
   111  	s.addTwoSubnetsInDifferentModelsAndAssertSecondFailsWithSuffix(c, info1, info2, s.State, errorSuffix)
   112  }
   113  
   114  func (s *SubnetSuite) addTwoSubnetsInDifferentModelsAndAssertSecondFailsWithSuffix(c *gc.C, info1, info2 state.SubnetInfo, otherState *state.State, errorSuffix string) {
   115  	_, err := otherState.AddSubnet(info1)
   116  	c.Assert(err, jc.ErrorIsNil)
   117  
   118  	s.assertAddSubnetForInfoFailsWithSuffix(c, info2, errorSuffix)
   119  }
   120  
   121  func (s *SubnetSuite) TestAddSubnetSucceedsWhenProviderIdNotUniqueInDifferentModels(c *gc.C) {
   122  	subnetInfo1 := state.SubnetInfo{CIDR: "192.168.0.1/24", ProviderId: "foo"}
   123  	subnetInfo2 := state.SubnetInfo{CIDR: "10.0.0.0/24", ProviderId: "foo"}
   124  	subnet1State := s.NewStateForModelNamed(c, "other-model")
   125  
   126  	subnet1, subnet2 := s.addTwoSubnetsInDifferentModelsAssertSuccessAndReturnBoth(c, subnetInfo1, subnetInfo2, subnet1State)
   127  	s.assertSubnetMatchesInfo(c, subnet1, subnetInfo1)
   128  	s.assertSubnetMatchesInfo(c, subnet2, subnetInfo2)
   129  }
   130  
   131  func (s *SubnetSuite) TestAddSubnetSucceedsForDifferentCIDRsAndEmptyProviderIdInSameModel(c *gc.C) {
   132  	subnetInfo1 := state.SubnetInfo{CIDR: "192.168.0.1/24", ProviderId: ""}
   133  	subnetInfo2 := state.SubnetInfo{CIDR: "10.0.0.0/24", ProviderId: ""}
   134  
   135  	subnet1, subnet2 := s.addTwoSubnetsAssertSuccessAndReturnBoth(c, subnetInfo1, subnetInfo2)
   136  	s.assertSubnetMatchesInfo(c, subnet1, subnetInfo1)
   137  	s.assertSubnetMatchesInfo(c, subnet2, subnetInfo2)
   138  }
   139  
   140  func (s *SubnetSuite) addTwoSubnetsAssertSuccessAndReturnBoth(c *gc.C, info1, info2 state.SubnetInfo) (*state.Subnet, *state.Subnet) {
   141  	return s.addTwoSubnetsInDifferentModelsAssertSuccessAndReturnBoth(c, info1, info2, s.State)
   142  }
   143  
   144  func (s *SubnetSuite) TestAddSubnetSucceedsForDifferentCIDRsAndEmptyProviderIdInDifferentModels(c *gc.C) {
   145  	subnetInfo1 := state.SubnetInfo{CIDR: "192.168.0.1/24", ProviderId: ""}
   146  	subnetInfo2 := state.SubnetInfo{CIDR: "10.0.0.0/24", ProviderId: ""}
   147  	subnet1State := s.NewStateForModelNamed(c, "other-model")
   148  
   149  	subnet1, subnet2 := s.addTwoSubnetsInDifferentModelsAssertSuccessAndReturnBoth(c, subnetInfo1, subnetInfo2, subnet1State)
   150  	s.assertSubnetMatchesInfo(c, subnet1, subnetInfo1)
   151  	s.assertSubnetMatchesInfo(c, subnet2, subnetInfo2)
   152  }
   153  
   154  func (s *SubnetSuite) TestEnsureDeadSetsLifeToDeadWhenAlive(c *gc.C) {
   155  	subnet := s.addAliveSubnet(c, "192.168.0.1/24")
   156  
   157  	s.ensureDeadAndAssertLifeIsDead(c, subnet)
   158  	s.refreshAndAssertSubnetLifeIs(c, subnet, state.Dead)
   159  }
   160  
   161  func (s *SubnetSuite) addAliveSubnet(c *gc.C, cidr string) *state.Subnet {
   162  	subnetInfo := state.SubnetInfo{CIDR: cidr}
   163  	subnet, err := s.State.AddSubnet(subnetInfo)
   164  	c.Assert(err, jc.ErrorIsNil)
   165  	c.Assert(subnet.Life(), gc.Equals, state.Alive)
   166  
   167  	return subnet
   168  }
   169  
   170  func (s *SubnetSuite) ensureDeadAndAssertLifeIsDead(c *gc.C, subnet *state.Subnet) {
   171  	err := subnet.EnsureDead()
   172  	c.Assert(err, jc.ErrorIsNil)
   173  	c.Assert(subnet.Life(), gc.Equals, state.Dead)
   174  }
   175  
   176  func (s *SubnetSuite) refreshAndAssertSubnetLifeIs(c *gc.C, subnet *state.Subnet, expectedLife state.Life) {
   177  	err := subnet.Refresh()
   178  	c.Assert(err, jc.ErrorIsNil)
   179  	c.Assert(subnet.Life(), gc.Equals, expectedLife)
   180  }
   181  
   182  func (s *SubnetSuite) TestEnsureDeadSetsLifeToDeadWhenNotAlive(c *gc.C) {
   183  	subnet := s.addAliveSubnet(c, "192.168.0.1/24")
   184  	s.ensureDeadAndAssertLifeIsDead(c, subnet)
   185  
   186  	s.ensureDeadAndAssertLifeIsDead(c, subnet)
   187  }
   188  
   189  func (s *SubnetSuite) TestRemoveFailsIfStillAlive(c *gc.C) {
   190  	subnet := s.addAliveSubnet(c, "192.168.0.1/24")
   191  
   192  	err := subnet.Remove()
   193  	c.Assert(err, gc.ErrorMatches, `cannot remove subnet "192.168.0.1/24": subnet is not dead`)
   194  	s.refreshAndAssertSubnetLifeIs(c, subnet, state.Alive)
   195  }
   196  
   197  func (s *SubnetSuite) TestRemoveSucceedsWhenSubnetIsNotAlive(c *gc.C) {
   198  	subnet := s.addAliveSubnet(c, "192.168.0.1/24")
   199  	s.ensureDeadAndAssertLifeIsDead(c, subnet)
   200  
   201  	s.removeSubnetAndAssertNotFound(c, subnet)
   202  }
   203  
   204  func (s *SubnetSuite) removeSubnetAndAssertNotFound(c *gc.C, subnet *state.Subnet) {
   205  	err := subnet.Remove()
   206  	c.Assert(err, jc.ErrorIsNil)
   207  	s.assertSubnetWithCIDRNotFound(c, subnet.CIDR())
   208  }
   209  
   210  func (s *SubnetSuite) assertSubnetWithCIDRNotFound(c *gc.C, cidr string) {
   211  	_, err := s.State.Subnet(cidr)
   212  	s.assertSubnetNotFoundError(c, err)
   213  }
   214  
   215  func (s *SubnetSuite) assertSubnetNotFoundError(c *gc.C, err error) {
   216  	c.Assert(err, gc.ErrorMatches, "subnet .* not found")
   217  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   218  }
   219  
   220  func (s *SubnetSuite) TestRemoveSucceedsWhenCalledTwice(c *gc.C) {
   221  	subnet := s.addAliveSubnet(c, "192.168.0.1/24")
   222  	s.ensureDeadAndAssertLifeIsDead(c, subnet)
   223  	s.removeSubnetAndAssertNotFound(c, subnet)
   224  
   225  	err := subnet.Remove()
   226  	c.Assert(err, gc.ErrorMatches, `cannot remove subnet "192.168.0.1/24": not found or not dead`)
   227  }
   228  
   229  func (s *SubnetSuite) TestRefreshUpdatesStaleDocData(c *gc.C) {
   230  	subnet := s.addAliveSubnet(c, "fc00::/64")
   231  	subnetCopy, err := s.State.Subnet("fc00::/64")
   232  	c.Assert(err, jc.ErrorIsNil)
   233  
   234  	s.ensureDeadAndAssertLifeIsDead(c, subnet)
   235  	c.Assert(subnetCopy.Life(), gc.Equals, state.Alive)
   236  
   237  	err = subnetCopy.Refresh()
   238  	c.Assert(err, jc.ErrorIsNil)
   239  	c.Assert(subnetCopy.Life(), gc.Equals, state.Dead)
   240  }
   241  
   242  func (s *SubnetSuite) TestRefreshFailsWithNotFoundWhenRemoved(c *gc.C) {
   243  	subnet := s.addAliveSubnet(c, "192.168.1.0/24")
   244  	s.ensureDeadAndAssertLifeIsDead(c, subnet)
   245  	s.removeSubnetAndAssertNotFound(c, subnet)
   246  
   247  	err := subnet.Refresh()
   248  	s.assertSubnetNotFoundError(c, err)
   249  }
   250  
   251  func (s *SubnetSuite) TestAllSubnets(c *gc.C) {
   252  	subnetInfos := []state.SubnetInfo{
   253  		{CIDR: "192.168.1.0/24"},
   254  		{CIDR: "8.8.8.0/24", SpaceName: "bar"},
   255  		{CIDR: "10.0.2.0/24", ProviderId: "foo"},
   256  		{CIDR: "2001:db8::/64", AvailabilityZone: "zone1"},
   257  	}
   258  
   259  	for _, info := range subnetInfos {
   260  		_, err := s.State.AddSubnet(info)
   261  		c.Assert(err, jc.ErrorIsNil)
   262  	}
   263  
   264  	subnets, err := s.State.AllSubnets()
   265  	c.Assert(err, jc.ErrorIsNil)
   266  	c.Assert(subnets, gc.HasLen, len(subnetInfos))
   267  
   268  	for i, subnet := range subnets {
   269  		c.Assert(subnet.CIDR(), gc.Equals, subnetInfos[i].CIDR)
   270  		c.Assert(subnet.ProviderId(), gc.Equals, subnetInfos[i].ProviderId)
   271  		c.Assert(subnet.SpaceName(), gc.Equals, subnetInfos[i].SpaceName)
   272  		c.Assert(subnet.AvailabilityZone(), gc.Equals, subnetInfos[i].AvailabilityZone)
   273  	}
   274  }