1
// Copyright 2014 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
9
"github.com/juju/errors"
10
jc "github.com/juju/testing/checkers"
11
gc "gopkg.in/check.v1"
13
"github.com/juju/juju/state"
16
type SubnetSuite struct {
20
var _ = gc.Suite(&SubnetSuite{})
22
func (s *SubnetSuite) TestAddSubnetSucceedsWithFullyPopulatedInfo(c *gc.C) {
23
subnetInfo := state.SubnetInfo{
25
CIDR: "192.168.1.0/24",
27
AvailabilityZone: "Timbuktu",
31
subnet, err := s.State.AddSubnet(subnetInfo)
32
c.Assert(err, jc.ErrorIsNil)
33
s.assertSubnetMatchesInfo(c, subnet, subnetInfo)
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)
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)
51
func (s *SubnetSuite) TestAddSubnetFailsWithEmptyCIDR(c *gc.C) {
52
subnetInfo := state.SubnetInfo{}
53
s.assertAddSubnetForInfoFailsWithSuffix(c, subnetInfo, "missing CIDR")
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)
64
func (s *SubnetSuite) TestAddSubnetFailsWithInvalidCIDR(c *gc.C) {
65
subnetInfo := state.SubnetInfo{CIDR: "foobar"}
66
s.assertAddSubnetForInfoFailsWithSuffix(c, subnetInfo, "invalid CIDR address: foobar")
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")
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)
80
err = s.assertAddSubnetForInfoFailsWithSuffix(c, subnetInfo, `subnet "192.168.0.1/24" already exists`)
81
c.Assert(err, jc.Satisfies, errors.IsAlreadyExists)
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")
89
subnet1, subnet2 := s.addTwoSubnetsInDifferentModelsAssertSuccessAndReturnBoth(c, subnetInfo1, subnetInfo2, subnet1State)
90
s.assertSubnetMatchesInfo(c, subnet1, subnetInfo1)
91
s.assertSubnetMatchesInfo(c, subnet2, subnetInfo2)
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)
100
return subnet1, subnet2
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"}
107
s.addTwoSubnetsAndAssertSecondFailsWithSuffix(c, subnetInfo1, subnetInfo2, `ProviderId "foo" not unique`)
110
func (s *SubnetSuite) addTwoSubnetsAndAssertSecondFailsWithSuffix(c *gc.C, info1, info2 state.SubnetInfo, errorSuffix string) {
111
s.addTwoSubnetsInDifferentModelsAndAssertSecondFailsWithSuffix(c, info1, info2, s.State, errorSuffix)
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)
118
s.assertAddSubnetForInfoFailsWithSuffix(c, info2, errorSuffix)
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")
126
subnet1, subnet2 := s.addTwoSubnetsInDifferentModelsAssertSuccessAndReturnBoth(c, subnetInfo1, subnetInfo2, subnet1State)
127
s.assertSubnetMatchesInfo(c, subnet1, subnetInfo1)
128
s.assertSubnetMatchesInfo(c, subnet2, subnetInfo2)
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: ""}
135
subnet1, subnet2 := s.addTwoSubnetsAssertSuccessAndReturnBoth(c, subnetInfo1, subnetInfo2)
136
s.assertSubnetMatchesInfo(c, subnet1, subnetInfo1)
137
s.assertSubnetMatchesInfo(c, subnet2, subnetInfo2)
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)
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")
149
subnet1, subnet2 := s.addTwoSubnetsInDifferentModelsAssertSuccessAndReturnBoth(c, subnetInfo1, subnetInfo2, subnet1State)
150
s.assertSubnetMatchesInfo(c, subnet1, subnetInfo1)
151
s.assertSubnetMatchesInfo(c, subnet2, subnetInfo2)
154
func (s *SubnetSuite) TestEnsureDeadSetsLifeToDeadWhenAlive(c *gc.C) {
155
subnet := s.addAliveSubnet(c, "192.168.0.1/24")
157
s.ensureDeadAndAssertLifeIsDead(c, subnet)
158
s.refreshAndAssertSubnetLifeIs(c, subnet, state.Dead)
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)
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)
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)
182
func (s *SubnetSuite) TestEnsureDeadSetsLifeToDeadWhenNotAlive(c *gc.C) {
183
subnet := s.addAliveSubnet(c, "192.168.0.1/24")
184
s.ensureDeadAndAssertLifeIsDead(c, subnet)
186
s.ensureDeadAndAssertLifeIsDead(c, subnet)
189
func (s *SubnetSuite) TestRemoveFailsIfStillAlive(c *gc.C) {
190
subnet := s.addAliveSubnet(c, "192.168.0.1/24")
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)
197
func (s *SubnetSuite) TestRemoveSucceedsWhenSubnetIsNotAlive(c *gc.C) {
198
subnet := s.addAliveSubnet(c, "192.168.0.1/24")
199
s.ensureDeadAndAssertLifeIsDead(c, subnet)
201
s.removeSubnetAndAssertNotFound(c, subnet)
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())
210
func (s *SubnetSuite) assertSubnetWithCIDRNotFound(c *gc.C, cidr string) {
211
_, err := s.State.Subnet(cidr)
212
s.assertSubnetNotFoundError(c, err)
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)
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)
225
err := subnet.Remove()
226
c.Assert(err, gc.ErrorMatches, `cannot remove subnet "192.168.0.1/24": not found or not dead`)
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)
234
s.ensureDeadAndAssertLifeIsDead(c, subnet)
235
c.Assert(subnetCopy.Life(), gc.Equals, state.Alive)
237
err = subnetCopy.Refresh()
238
c.Assert(err, jc.ErrorIsNil)
239
c.Assert(subnetCopy.Life(), gc.Equals, state.Dead)
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)
247
err := subnet.Refresh()
248
s.assertSubnetNotFoundError(c, err)
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"},
259
for _, info := range subnetInfos {
260
_, err := s.State.AddSubnet(info)
261
c.Assert(err, jc.ErrorIsNil)
264
subnets, err := s.State.AllSubnets()
265
c.Assert(err, jc.ErrorIsNil)
266
c.Assert(subnets, gc.HasLen, len(subnetInfos))
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)