github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/core/network/space_test.go (about) 1 // Copyright 2019 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package network_test 5 6 import ( 7 "github.com/juju/collections/set" 8 "github.com/juju/errors" 9 "github.com/juju/testing" 10 jc "github.com/juju/testing/checkers" 11 gc "gopkg.in/check.v1" 12 13 "github.com/juju/juju/core/network" 14 ) 15 16 type spaceSuite struct { 17 testing.IsolationSuite 18 19 spaces network.SpaceInfos 20 } 21 22 var _ = gc.Suite(&spaceSuite{}) 23 24 func (s *spaceSuite) SetUpTest(c *gc.C) { 25 s.spaces = network.SpaceInfos{ 26 {ID: "1", Name: "space1", Subnets: []network.SubnetInfo{{ID: "11", CIDR: "10.0.0.0/24"}}}, 27 {ID: "2", Name: "space2", Subnets: []network.SubnetInfo{{ID: "12", CIDR: "10.0.1.0/24"}}}, 28 {ID: "3", Name: "space3", Subnets: []network.SubnetInfo{{ID: "13", CIDR: "10.0.2.0/24"}}}, 29 } 30 } 31 32 func (s *spaceSuite) TestString(c *gc.C) { 33 result := s.spaces.String() 34 c.Assert(result, gc.Equals, `"space1", "space2", "space3"`) 35 } 36 37 func (s *spaceSuite) TestGetByName(c *gc.C) { 38 c.Assert(s.spaces.GetByName("space1"), gc.NotNil) 39 c.Assert(s.spaces.GetByName("space666"), gc.IsNil) 40 } 41 42 func (s *spaceSuite) TestGetByID(c *gc.C) { 43 c.Assert(s.spaces.GetByID("1"), gc.NotNil) 44 c.Assert(s.spaces.GetByID("999"), gc.IsNil) 45 } 46 47 func (s *spaceSuite) TestContainsName(c *gc.C) { 48 c.Assert(s.spaces.ContainsName("space3"), jc.IsTrue) 49 c.Assert(s.spaces.ContainsName("space666"), jc.IsFalse) 50 } 51 52 func (s *spaceSuite) TestMinus(c *gc.C) { 53 infos := network.SpaceInfos{ 54 {ID: "2", Name: "space2"}, 55 {ID: "3", Name: "space3"}, 56 } 57 result := s.spaces.Minus(infos) 58 c.Assert(result, gc.DeepEquals, network.SpaceInfos{s.spaces[0]}) 59 } 60 61 func (s *spaceSuite) TestMinusNoDiff(c *gc.C) { 62 infos := network.SpaceInfos{ 63 {ID: "1", Name: "space1"}, 64 {ID: "2", Name: "space2"}, 65 {ID: "3", Name: "space3"}, 66 } 67 result := s.spaces.Minus(infos) 68 c.Assert(result, gc.DeepEquals, network.SpaceInfos{}) 69 } 70 71 func (s *spaceSuite) TestInferSpaceFromAddress(c *gc.C) { 72 queries := map[string]network.SpaceName{ 73 "10.0.0.42": "space1", 74 "10.0.1.1": "space2", 75 "10.0.2.99": "space3", 76 } 77 78 for addr, expSpaceName := range queries { 79 si, err := s.spaces.InferSpaceFromAddress(addr) 80 c.Assert(err, jc.ErrorIsNil, gc.Commentf("infer space for address %q", addr)) 81 c.Assert(si.Name, gc.Equals, expSpaceName, gc.Commentf("infer space for address %q", addr)) 82 } 83 84 // Check that CIDR collisions are detected 85 s.spaces = append( 86 s.spaces, 87 network.SpaceInfo{ID: "-3", Name: "inverse", Subnets: []network.SubnetInfo{{CIDR: "10.0.2.0/24"}}}, 88 ) 89 90 _, err := s.spaces.InferSpaceFromAddress("10.0.2.255") 91 c.Assert(err, gc.ErrorMatches, ".*address matches the same CIDR in multiple spaces") 92 93 // Check for no-match-found 94 _, err = s.spaces.InferSpaceFromAddress("99.99.99.99") 95 c.Assert(err, gc.ErrorMatches, ".*unable to infer space for address.*") 96 } 97 98 func (s *spaceSuite) TestInferSpaceFromCIDRAndSubnetID(c *gc.C) { 99 infos := network.SpaceInfos{ 100 {ID: "1", Name: "space1", Subnets: []network.SubnetInfo{{CIDR: "10.0.0.0/24", ProviderId: "1"}}}, 101 {ID: "2", Name: "space2", Subnets: []network.SubnetInfo{{CIDR: "10.0.1.0/24", ProviderId: "2"}}}, 102 } 103 104 si, err := infos.InferSpaceFromCIDRAndSubnetID("10.0.0.0/24", "1") 105 c.Assert(err, jc.ErrorIsNil) 106 c.Assert(si.Name, gc.Equals, network.SpaceName("space1")) 107 108 // Check for same CIDR/different provider 109 infos = append( 110 infos, 111 network.SpaceInfo{ 112 ID: "-2", 113 Name: "inverse", 114 Subnets: []network.SubnetInfo{{CIDR: "10.0.1.0/24", ProviderId: "3"}}, 115 }, 116 ) 117 118 si, err = infos.InferSpaceFromCIDRAndSubnetID("10.0.1.0/24", "2") 119 c.Assert(err, jc.ErrorIsNil) 120 c.Assert(si.Name, gc.Equals, network.SpaceName("space2")) 121 122 si, err = infos.InferSpaceFromCIDRAndSubnetID("10.0.1.0/24", "3") 123 c.Assert(err, jc.ErrorIsNil) 124 c.Assert(si.Name, gc.Equals, network.SpaceName("inverse")) 125 126 // Check for no-match-found 127 _, err = infos.InferSpaceFromCIDRAndSubnetID("10.0.1.0/24", "42") 128 c.Assert(err, gc.ErrorMatches, ".*unable to infer space.*") 129 } 130 131 func (s *spaceSuite) TestAllSubnetInfos(c *gc.C) { 132 subnets, err := s.spaces.AllSubnetInfos() 133 c.Assert(err, jc.ErrorIsNil) 134 135 c.Assert(subnets, gc.DeepEquals, network.SubnetInfos{ 136 {ID: "11", CIDR: "10.0.0.0/24"}, 137 {ID: "12", CIDR: "10.0.1.0/24"}, 138 {ID: "13", CIDR: "10.0.2.0/24"}, 139 }) 140 } 141 142 func (s *spaceSuite) TestFanOverlaysFor(c *gc.C) { 143 overlay := network.SubnetInfo{ 144 ID: "15", 145 CIDR: "10.1.1.0/16", 146 FanInfo: &network.FanCIDRs{ 147 FanLocalUnderlay: "10.0.3.0/24", 148 FanOverlay: "10.1.0.0/8", 149 }, 150 } 151 152 s.spaces = append(s.spaces, network.SpaceInfo{ 153 ID: "4", 154 Name: "space4", 155 Subnets: network.SubnetInfos{ 156 { 157 ID: "14", 158 CIDR: "10.0.3.0/24", 159 }, 160 overlay, 161 }, 162 }) 163 164 overlays, err := s.spaces.FanOverlaysFor(network.MakeIDSet("11")) 165 c.Assert(err, jc.ErrorIsNil) 166 c.Assert(overlays, gc.HasLen, 0) 167 168 overlays, err = s.spaces.FanOverlaysFor(network.MakeIDSet("14")) 169 c.Assert(err, jc.ErrorIsNil) 170 c.Assert(overlays, gc.DeepEquals, network.SubnetInfos{overlay}) 171 } 172 173 func (s *spaceSuite) TestMoveSubnets(c *gc.C) { 174 _, err := s.spaces.MoveSubnets(network.MakeIDSet("11", "12"), "space4") 175 c.Check(err, jc.Satisfies, errors.IsNotFound) 176 177 _, err = s.spaces.MoveSubnets(network.MakeIDSet("666"), "space3") 178 c.Check(err, jc.Satisfies, errors.IsNotFound) 179 180 spaces, err := s.spaces.MoveSubnets(network.MakeIDSet("11", "12"), "space3") 181 c.Assert(err, jc.ErrorIsNil) 182 c.Assert(spaces, gc.DeepEquals, network.SpaceInfos{ 183 {ID: "1", Name: "space1", Subnets: nil}, 184 {ID: "2", Name: "space2", Subnets: nil}, 185 { 186 ID: "3", 187 Name: "space3", 188 Subnets: network.SubnetInfos{ 189 {ID: "13", CIDR: "10.0.2.0/24"}, 190 {ID: "11", CIDR: "10.0.0.0/24", SpaceID: "3", SpaceName: "space3"}, 191 {ID: "12", CIDR: "10.0.1.0/24", SpaceID: "3", SpaceName: "space3"}, 192 }, 193 }, 194 }) 195 196 // Ensure the original was not mutated. 197 c.Assert(s.spaces, gc.DeepEquals, network.SpaceInfos{ 198 {ID: "1", Name: "space1", Subnets: []network.SubnetInfo{{ID: "11", CIDR: "10.0.0.0/24"}}}, 199 {ID: "2", Name: "space2", Subnets: []network.SubnetInfo{{ID: "12", CIDR: "10.0.1.0/24"}}}, 200 {ID: "3", Name: "space3", Subnets: []network.SubnetInfo{{ID: "13", CIDR: "10.0.2.0/24"}}}, 201 }) 202 } 203 204 func (s *spaceSuite) TestSubnetCIDRsBySpaceID(c *gc.C) { 205 res := s.spaces.SubnetCIDRsBySpaceID() 206 c.Assert(res, gc.DeepEquals, map[string][]string{ 207 "1": {"10.0.0.0/24"}, 208 "2": {"10.0.1.0/24"}, 209 "3": {"10.0.2.0/24"}, 210 }) 211 } 212 213 func (s *spaceSuite) TestConvertSpaceName(c *gc.C) { 214 empty := set.Strings{} 215 nameTests := []struct { 216 name string 217 existing set.Strings 218 expected string 219 }{ 220 {"foo", empty, "foo"}, 221 {"foo1", empty, "foo1"}, 222 {"Foo Thing", empty, "foo-thing"}, 223 {"foo^9*//++!!!!", empty, "foo9"}, 224 {"--Foo", empty, "foo"}, 225 {"---^^&*()!", empty, "empty"}, 226 {" ", empty, "empty"}, 227 {"", empty, "empty"}, 228 {"foo\u2318", empty, "foo"}, 229 {"foo--", empty, "foo"}, 230 {"-foo--foo----bar-", empty, "foo-foo-bar"}, 231 {"foo-", set.NewStrings("foo", "bar", "baz"), "foo-2"}, 232 {"foo", set.NewStrings("foo", "foo-2"), "foo-3"}, 233 {"---", set.NewStrings("empty"), "empty-2"}, 234 } 235 for _, test := range nameTests { 236 result := network.ConvertSpaceName(test.name, test.existing) 237 c.Check(result, gc.Equals, test.expected) 238 } 239 }