github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/apiserver/spaces/spaces_test.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package spaces_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 "gopkg.in/juju/names.v2" 13 14 "github.com/juju/juju/apiserver/common" 15 "github.com/juju/juju/apiserver/params" 16 "github.com/juju/juju/apiserver/spaces" 17 apiservertesting "github.com/juju/juju/apiserver/testing" 18 "github.com/juju/juju/network" 19 coretesting "github.com/juju/juju/testing" 20 ) 21 22 type SpacesSuite struct { 23 coretesting.BaseSuite 24 apiservertesting.StubNetwork 25 26 resources *common.Resources 27 authorizer apiservertesting.FakeAuthorizer 28 facade spaces.API 29 } 30 31 var _ = gc.Suite(&SpacesSuite{}) 32 33 func (s *SpacesSuite) SetUpSuite(c *gc.C) { 34 s.StubNetwork.SetUpSuite(c) 35 s.BaseSuite.SetUpSuite(c) 36 } 37 38 func (s *SpacesSuite) TearDownSuite(c *gc.C) { 39 s.BaseSuite.TearDownSuite(c) 40 } 41 42 func (s *SpacesSuite) SetUpTest(c *gc.C) { 43 s.BaseSuite.SetUpTest(c) 44 apiservertesting.BackingInstance.SetUp(c, apiservertesting.StubZonedNetworkingEnvironName, apiservertesting.WithZones, apiservertesting.WithSpaces, apiservertesting.WithSubnets) 45 46 s.resources = common.NewResources() 47 s.authorizer = apiservertesting.FakeAuthorizer{ 48 Tag: names.NewUserTag("admin"), 49 EnvironManager: false, 50 } 51 52 var err error 53 s.facade, err = spaces.NewAPIWithBacking( 54 apiservertesting.BackingInstance, s.resources, s.authorizer, 55 ) 56 c.Assert(err, jc.ErrorIsNil) 57 c.Assert(s.facade, gc.NotNil) 58 } 59 60 func (s *SpacesSuite) TearDownTest(c *gc.C) { 61 if s.resources != nil { 62 s.resources.StopAll() 63 } 64 s.BaseSuite.TearDownTest(c) 65 } 66 67 func (s *SpacesSuite) TestNewAPIWithBacking(c *gc.C) { 68 // Clients are allowed. 69 facade, err := spaces.NewAPIWithBacking( 70 apiservertesting.BackingInstance, s.resources, s.authorizer, 71 ) 72 c.Assert(err, jc.ErrorIsNil) 73 c.Assert(facade, gc.NotNil) 74 // No calls so far. 75 apiservertesting.CheckMethodCalls(c, apiservertesting.SharedStub) 76 77 // Agents are not allowed 78 agentAuthorizer := s.authorizer 79 agentAuthorizer.Tag = names.NewMachineTag("42") 80 facade, err = spaces.NewAPIWithBacking( 81 apiservertesting.BackingInstance, s.resources, agentAuthorizer, 82 ) 83 c.Assert(err, jc.DeepEquals, common.ErrPerm) 84 c.Assert(facade, gc.IsNil) 85 // No calls so far. 86 apiservertesting.CheckMethodCalls(c, apiservertesting.SharedStub) 87 } 88 89 type checkAddSpacesParams struct { 90 Name string 91 Subnets []string 92 Error string 93 MakesCall bool 94 Public bool 95 } 96 97 func (s *SpacesSuite) checkAddSpaces(c *gc.C, p checkAddSpacesParams) { 98 args := params.CreateSpaceParams{} 99 if p.Name != "" { 100 args.SpaceTag = "space-" + p.Name 101 } 102 if len(p.Subnets) > 0 { 103 for _, cidr := range p.Subnets { 104 args.SubnetTags = append(args.SubnetTags, "subnet-"+cidr) 105 } 106 } 107 args.Public = p.Public 108 109 spaces := params.CreateSpacesParams{} 110 spaces.Spaces = append(spaces.Spaces, args) 111 results, err := s.facade.CreateSpaces(spaces) 112 113 c.Assert(len(results.Results), gc.Equals, 1) 114 c.Assert(err, gc.IsNil) 115 if p.Error == "" { 116 c.Assert(results.Results[0].Error, gc.IsNil) 117 } else { 118 c.Assert(results.Results[0].Error, gc.NotNil) 119 c.Assert(results.Results[0].Error, gc.ErrorMatches, p.Error) 120 } 121 122 baseCalls := []apiservertesting.StubMethodCall{ 123 apiservertesting.BackingCall("ModelConfig"), 124 apiservertesting.BackingCall("CloudSpec"), 125 apiservertesting.ProviderCall("Open", apiservertesting.BackingInstance.EnvConfig), 126 apiservertesting.ZonedNetworkingEnvironCall("SupportsSpaces"), 127 } 128 129 // AddSpace from the api always uses an empty ProviderId. 130 addSpaceCalls := append(baseCalls, apiservertesting.BackingCall("AddSpace", p.Name, network.Id(""), p.Subnets, p.Public)) 131 132 if p.Error == "" || p.MakesCall { 133 apiservertesting.CheckMethodCalls(c, apiservertesting.SharedStub, addSpaceCalls...) 134 } else { 135 apiservertesting.CheckMethodCalls(c, apiservertesting.SharedStub, baseCalls...) 136 } 137 } 138 139 func (s *SpacesSuite) TestAddSpacesOneSubnet(c *gc.C) { 140 p := checkAddSpacesParams{ 141 Name: "foo", 142 Subnets: []string{"10.0.0.0/24"}, 143 } 144 s.checkAddSpaces(c, p) 145 } 146 147 func (s *SpacesSuite) TestAddSpacesTwoSubnets(c *gc.C) { 148 p := checkAddSpacesParams{ 149 Name: "foo", 150 Subnets: []string{"10.0.0.0/24", "10.0.1.0/24"}, 151 } 152 s.checkAddSpaces(c, p) 153 } 154 155 func (s *SpacesSuite) TestAddSpacesManySubnets(c *gc.C) { 156 p := checkAddSpacesParams{ 157 Name: "foo", 158 Subnets: []string{"10.0.0.0/24", "10.0.1.0/24", "10.0.2.0/24", 159 "10.0.3.0/24", "10.0.4.0/24", "10.0.5.0/24", "10.0.6.0/24"}, 160 } 161 s.checkAddSpaces(c, p) 162 } 163 164 func (s *SpacesSuite) TestAddSpacesAPIError(c *gc.C) { 165 apiservertesting.SharedStub.SetErrors( 166 nil, // Backing.ModelConfig() 167 nil, // Backing.CloudSpec() 168 nil, // Provider.Open() 169 nil, // ZonedNetworkingEnviron.SupportsSpaces() 170 errors.AlreadyExistsf("space-foo"), // Backing.AddSpace() 171 ) 172 p := checkAddSpacesParams{ 173 Name: "foo", 174 Subnets: []string{"10.0.0.0/24"}, 175 MakesCall: true, 176 Error: "space-foo already exists", 177 } 178 s.checkAddSpaces(c, p) 179 } 180 181 func (s *SpacesSuite) TestCreateInvalidSpace(c *gc.C) { 182 p := checkAddSpacesParams{ 183 Name: "-", 184 Subnets: []string{"10.0.0.0/24"}, 185 Error: `"space--" is not a valid space tag`, 186 } 187 s.checkAddSpaces(c, p) 188 } 189 190 func (s *SpacesSuite) TestCreateInvalidSubnet(c *gc.C) { 191 p := checkAddSpacesParams{ 192 Name: "foo", 193 Subnets: []string{"bar"}, 194 Error: `"subnet-bar" is not a valid subnet tag`, 195 } 196 s.checkAddSpaces(c, p) 197 } 198 199 func (s *SpacesSuite) TestPublic(c *gc.C) { 200 p := checkAddSpacesParams{ 201 Name: "foo", 202 Subnets: []string{"10.0.0.0/24"}, 203 Public: true, 204 } 205 s.checkAddSpaces(c, p) 206 } 207 208 func (s *SpacesSuite) TestEmptySpaceName(c *gc.C) { 209 p := checkAddSpacesParams{ 210 Subnets: []string{"10.0.0.0/24"}, 211 Error: `"" is not a valid tag`, 212 } 213 s.checkAddSpaces(c, p) 214 } 215 216 func (s *SpacesSuite) TestNoSubnets(c *gc.C) { 217 p := checkAddSpacesParams{ 218 Name: "foo", 219 Subnets: nil, 220 } 221 s.checkAddSpaces(c, p) 222 } 223 224 func (s *SpacesSuite) TestListSpacesDefault(c *gc.C) { 225 expected := []params.Space{{ 226 Name: "default", 227 Subnets: []params.Subnet{{ 228 CIDR: "192.168.0.0/24", 229 ProviderId: "provider-192.168.0.0/24", 230 Zones: []string{"foo"}, 231 Status: "in-use", 232 SpaceTag: "space-default", 233 }, { 234 CIDR: "192.168.3.0/24", 235 ProviderId: "provider-192.168.3.0/24", 236 VLANTag: 23, 237 Zones: []string{"bar", "bam"}, 238 SpaceTag: "space-default", 239 }}, 240 }, { 241 Name: "dmz", 242 Subnets: []params.Subnet{{ 243 CIDR: "192.168.1.0/24", 244 ProviderId: "provider-192.168.1.0/24", 245 VLANTag: 23, 246 Zones: []string{"bar", "bam"}, 247 SpaceTag: "space-dmz", 248 }}, 249 }, { 250 Name: "private", 251 Subnets: []params.Subnet{{ 252 CIDR: "192.168.2.0/24", 253 ProviderId: "provider-192.168.2.0/24", 254 Zones: []string{"foo"}, 255 Status: "in-use", 256 SpaceTag: "space-private", 257 }}, 258 }} 259 spaces, err := s.facade.ListSpaces() 260 c.Assert(err, jc.ErrorIsNil) 261 c.Assert(spaces.Results, jc.DeepEquals, expected) 262 } 263 264 func (s *SpacesSuite) TestListSpacesAllSpacesError(c *gc.C) { 265 boom := errors.New("backing boom") 266 apiservertesting.BackingInstance.SetErrors(boom) 267 _, err := s.facade.ListSpaces() 268 c.Assert(err, gc.ErrorMatches, "getting environ: backing boom") 269 } 270 271 func (s *SpacesSuite) TestListSpacesSubnetsError(c *gc.C) { 272 apiservertesting.SharedStub.SetErrors( 273 nil, // Backing.ModelConfig() 274 nil, // Backing.CloudSpec() 275 nil, // Provider.Open() 276 nil, // ZonedNetworkingEnviron.SupportsSpaces() 277 nil, // Backing.AllSpaces() 278 errors.New("space0 subnets failed"), // Space.Subnets() 279 errors.New("space1 subnets failed"), // Space.Subnets() 280 errors.New("space2 subnets failed"), // Space.Subnets() 281 ) 282 283 results, err := s.facade.ListSpaces() 284 for i, space := range results.Results { 285 errmsg := fmt.Sprintf("fetching subnets: space%d subnets failed", i) 286 c.Assert(space.Error, gc.ErrorMatches, errmsg) 287 } 288 c.Assert(err, jc.ErrorIsNil) 289 } 290 291 func (s *SpacesSuite) TestListSpacesSubnetsSingleSubnetError(c *gc.C) { 292 boom := errors.New("boom") 293 apiservertesting.SharedStub.SetErrors( 294 nil, // Backing.ModelConfig() 295 nil, // Backing.CloudSpec() 296 nil, // Provider.Open() 297 nil, // ZonedNetworkingEnviron.SupportsSpaces() 298 nil, // Backing.AllSpaces() 299 nil, // Space.Subnets() (1st no error) 300 boom, // Space.Subnets() (2nd with error) 301 ) 302 303 results, err := s.facade.ListSpaces() 304 for i, space := range results.Results { 305 if i == 1 { 306 c.Assert(space.Error, gc.ErrorMatches, "fetching subnets: boom") 307 } else { 308 c.Assert(space.Error, gc.IsNil) 309 } 310 } 311 c.Assert(err, jc.ErrorIsNil) 312 } 313 314 func (s *SpacesSuite) TestCreateSpacesModelConfigError(c *gc.C) { 315 apiservertesting.SharedStub.SetErrors( 316 errors.New("boom"), // Backing.ModelConfig() 317 ) 318 319 spaces := params.CreateSpacesParams{} 320 _, err := s.facade.CreateSpaces(spaces) 321 c.Assert(err, gc.ErrorMatches, "getting environ: boom") 322 } 323 324 func (s *SpacesSuite) TestCreateSpacesProviderOpenError(c *gc.C) { 325 apiservertesting.SharedStub.SetErrors( 326 nil, // Backing.ModelConfig() 327 nil, // Backing.CloudSpec() 328 errors.New("boom"), // Provider.Open() 329 ) 330 331 spaces := params.CreateSpacesParams{} 332 _, err := s.facade.CreateSpaces(spaces) 333 c.Assert(err, gc.ErrorMatches, "getting environ: boom") 334 } 335 336 func (s *SpacesSuite) TestCreateSpacesNotSupportedError(c *gc.C) { 337 apiservertesting.SharedStub.SetErrors( 338 nil, // Backing.ModelConfig() 339 nil, // Backing.CloudSpec() 340 nil, // Provider.Open() 341 errors.NotSupportedf("spaces"), // ZonedNetworkingEnviron.SupportsSpaces() 342 ) 343 344 spaces := params.CreateSpacesParams{} 345 _, err := s.facade.CreateSpaces(spaces) 346 c.Assert(err, gc.ErrorMatches, "spaces not supported") 347 } 348 349 func (s *SpacesSuite) TestListSpacesNotSupportedError(c *gc.C) { 350 apiservertesting.SharedStub.SetErrors( 351 nil, // Backing.ModelConfig() 352 nil, // Backing.CloudSpec() 353 nil, // Provider.Open 354 errors.NotSupportedf("spaces"), // ZonedNetworkingEnviron.SupportsSpaces() 355 ) 356 357 _, err := s.facade.ListSpaces() 358 c.Assert(err, gc.ErrorMatches, "spaces not supported") 359 }