github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/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 }