github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/provider/maas/maas2_test.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package maas 5 6 import ( 7 "github.com/juju/errors" 8 "github.com/juju/gomaasapi" 9 "github.com/juju/testing" 10 jc "github.com/juju/testing/checkers" 11 "github.com/juju/utils/set" 12 gc "gopkg.in/check.v1" 13 14 "github.com/juju/juju/cloud" 15 "github.com/juju/juju/environs" 16 "github.com/juju/juju/environs/config" 17 coretesting "github.com/juju/juju/testing" 18 "github.com/juju/juju/version" 19 ) 20 21 type maas2Suite struct { 22 baseProviderSuite 23 } 24 25 func (suite *maas2Suite) injectController(controller gomaasapi.Controller) { 26 mockGetController := func(maasServer, apiKey string) (gomaasapi.Controller, error) { 27 return controller, nil 28 } 29 suite.PatchValue(&GetMAAS2Controller, mockGetController) 30 } 31 32 func (suite *maas2Suite) makeEnviron(c *gc.C, controller gomaasapi.Controller) *maasEnviron { 33 if controller != nil { 34 suite.injectController(controller) 35 } 36 testAttrs := coretesting.Attrs{} 37 for k, v := range maasEnvAttrs { 38 testAttrs[k] = v 39 } 40 testAttrs["agent-version"] = version.Current.String() 41 42 cred := cloud.NewCredential(cloud.OAuth1AuthType, map[string]string{ 43 "maas-oauth": "a:b:c", 44 }) 45 cloud := environs.CloudSpec{ 46 Type: "maas", 47 Name: "maas", 48 Endpoint: "http://any-old-junk.invalid/", 49 Credential: &cred, 50 } 51 52 attrs := coretesting.FakeConfig().Merge(testAttrs) 53 suite.controllerUUID = coretesting.FakeControllerConfig().ControllerUUID() 54 cfg, err := config.New(config.NoDefaults, attrs) 55 c.Assert(err, jc.ErrorIsNil) 56 env, err := NewEnviron(cloud, cfg) 57 c.Assert(err, jc.ErrorIsNil) 58 c.Assert(env, gc.NotNil) 59 return env 60 } 61 62 type fakeController struct { 63 gomaasapi.Controller 64 *testing.Stub 65 66 bootResources []gomaasapi.BootResource 67 bootResourcesError error 68 machines []gomaasapi.Machine 69 machinesError error 70 machinesArgsCheck func(gomaasapi.MachinesArgs) 71 zones []gomaasapi.Zone 72 zonesError error 73 spaces []gomaasapi.Space 74 spacesError error 75 76 allocateMachine gomaasapi.Machine 77 allocateMachineMatches gomaasapi.ConstraintMatches 78 allocateMachineError error 79 allocateMachineArgsCheck func(gomaasapi.AllocateMachineArgs) 80 81 files []gomaasapi.File 82 83 devices []gomaasapi.Device 84 } 85 86 func newFakeController() *fakeController { 87 return &fakeController{Stub: &testing.Stub{}} 88 } 89 90 func newFakeControllerWithErrors(errors ...error) *fakeController { 91 controller := newFakeController() 92 controller.SetErrors(errors...) 93 return controller 94 } 95 96 func newFakeControllerWithFiles(files ...gomaasapi.File) *fakeController { 97 return &fakeController{Stub: &testing.Stub{}, files: files} 98 } 99 100 func (c *fakeController) Devices(args gomaasapi.DevicesArgs) ([]gomaasapi.Device, error) { 101 c.MethodCall(c, "Devices", args) 102 return c.devices, c.NextErr() 103 } 104 105 func (c *fakeController) Machines(args gomaasapi.MachinesArgs) ([]gomaasapi.Machine, error) { 106 if c.machinesArgsCheck != nil { 107 c.machinesArgsCheck(args) 108 } 109 if c.machinesError != nil { 110 return nil, c.machinesError 111 } 112 if len(args.SystemIDs) > 0 { 113 result := []gomaasapi.Machine{} 114 systemIds := set.NewStrings(args.SystemIDs...) 115 for _, machine := range c.machines { 116 if systemIds.Contains(machine.SystemID()) { 117 result = append(result, machine) 118 } 119 } 120 return result, nil 121 } 122 return c.machines, nil 123 } 124 125 func (c *fakeController) AllocateMachine(args gomaasapi.AllocateMachineArgs) (gomaasapi.Machine, gomaasapi.ConstraintMatches, error) { 126 if c.allocateMachineArgsCheck != nil { 127 c.allocateMachineArgsCheck(args) 128 } 129 if c.allocateMachineError != nil { 130 return nil, c.allocateMachineMatches, c.allocateMachineError 131 } 132 return c.allocateMachine, c.allocateMachineMatches, nil 133 } 134 135 func (c *fakeController) BootResources() ([]gomaasapi.BootResource, error) { 136 if c.bootResourcesError != nil { 137 return nil, c.bootResourcesError 138 } 139 return c.bootResources, nil 140 } 141 142 func (c *fakeController) Zones() ([]gomaasapi.Zone, error) { 143 if c.zonesError != nil { 144 return nil, c.zonesError 145 } 146 return c.zones, nil 147 } 148 149 func (c *fakeController) Spaces() ([]gomaasapi.Space, error) { 150 if c.spacesError != nil { 151 return nil, c.spacesError 152 } 153 return c.spaces, nil 154 } 155 156 func (c *fakeController) Files(prefix string) ([]gomaasapi.File, error) { 157 c.MethodCall(c, "Files", prefix) 158 return c.files, c.NextErr() 159 } 160 161 func (c *fakeController) GetFile(filename string) (gomaasapi.File, error) { 162 c.MethodCall(c, "GetFile", filename) 163 err := c.NextErr() 164 if err != nil { 165 return nil, err 166 } 167 // Try to find the file by name (needed for testing RemoveAll) 168 for _, file := range c.files { 169 if file.Filename() == filename { 170 return file, nil 171 } 172 } 173 // The test forgot to set up matching files! 174 return nil, errors.Errorf("no file named %v found - did you set up your test correctly?", filename) 175 } 176 177 func (c *fakeController) AddFile(args gomaasapi.AddFileArgs) error { 178 c.MethodCall(c, "AddFile", args) 179 return c.NextErr() 180 } 181 182 func (c *fakeController) ReleaseMachines(args gomaasapi.ReleaseMachinesArgs) error { 183 c.MethodCall(c, "ReleaseMachines", args) 184 return c.NextErr() 185 } 186 187 type fakeMachineOnlyController struct { 188 machines []gomaasapi.Machine 189 } 190 191 func (f *fakeMachineOnlyController) Machines(gomaasapi.MachinesArgs) ([]gomaasapi.Machine, error) { 192 return f.machines, nil 193 } 194 195 type fakeBootResource struct { 196 gomaasapi.BootResource 197 name string 198 architecture string 199 } 200 201 func (r *fakeBootResource) Name() string { 202 return r.name 203 } 204 205 func (r *fakeBootResource) Architecture() string { 206 return r.architecture 207 } 208 209 type fakeMachine struct { 210 gomaasapi.Machine 211 *testing.Stub 212 213 zoneName string 214 hostname string 215 systemID string 216 ipAddresses []string 217 statusName string 218 statusMessage string 219 cpuCount int 220 memory int 221 architecture string 222 interfaceSet []gomaasapi.Interface 223 tags []string 224 createDevice gomaasapi.Device 225 } 226 227 func newFakeMachine(systemID, architecture, statusName string) *fakeMachine { 228 return &fakeMachine{ 229 Stub: &testing.Stub{}, 230 systemID: systemID, 231 architecture: architecture, 232 statusName: statusName, 233 } 234 } 235 236 func (m *fakeMachine) Tags() []string { 237 return m.tags 238 } 239 240 func (m *fakeMachine) SetOwnerData(data map[string]string) error { 241 m.MethodCall(m, "SetOwnerData", data) 242 return m.NextErr() 243 } 244 245 func (m *fakeMachine) CPUCount() int { 246 return m.cpuCount 247 } 248 249 func (m *fakeMachine) Memory() int { 250 return m.memory 251 } 252 253 func (m *fakeMachine) Architecture() string { 254 return m.architecture 255 } 256 257 func (m *fakeMachine) SystemID() string { 258 return m.systemID 259 } 260 261 func (m *fakeMachine) Hostname() string { 262 return m.hostname 263 } 264 265 func (m *fakeMachine) IPAddresses() []string { 266 return m.ipAddresses 267 } 268 269 func (m *fakeMachine) StatusName() string { 270 return m.statusName 271 } 272 273 func (m *fakeMachine) StatusMessage() string { 274 return m.statusMessage 275 } 276 277 func (m *fakeMachine) Zone() gomaasapi.Zone { 278 return fakeZone{name: m.zoneName} 279 } 280 281 func (m *fakeMachine) InterfaceSet() []gomaasapi.Interface { 282 return m.interfaceSet 283 } 284 285 func (m *fakeMachine) Start(args gomaasapi.StartArgs) error { 286 m.MethodCall(m, "Start", args) 287 return m.NextErr() 288 } 289 290 func (m *fakeMachine) CreateDevice(args gomaasapi.CreateMachineDeviceArgs) (gomaasapi.Device, error) { 291 m.MethodCall(m, "CreateDevice", args) 292 return m.createDevice, m.NextErr() 293 } 294 295 type fakeZone struct { 296 gomaasapi.Zone 297 name string 298 } 299 300 func (z fakeZone) Name() string { 301 return z.name 302 } 303 304 type fakeSpace struct { 305 gomaasapi.Space 306 name string 307 id int 308 subnets []gomaasapi.Subnet 309 } 310 311 func (s fakeSpace) Name() string { 312 return s.name 313 } 314 315 func (s fakeSpace) ID() int { 316 return s.id 317 } 318 319 func (s fakeSpace) Subnets() []gomaasapi.Subnet { 320 return s.subnets 321 } 322 323 type fakeSubnet struct { 324 gomaasapi.Subnet 325 id int 326 space string 327 vlan gomaasapi.VLAN 328 gateway string 329 cidr string 330 dnsServers []string 331 } 332 333 func (s fakeSubnet) ID() int { 334 return s.id 335 } 336 337 func (s fakeSubnet) Space() string { 338 return s.space 339 } 340 341 func (s fakeSubnet) VLAN() gomaasapi.VLAN { 342 return s.vlan 343 } 344 345 func (s fakeSubnet) Gateway() string { 346 return s.gateway 347 } 348 349 func (s fakeSubnet) CIDR() string { 350 return s.cidr 351 } 352 353 func (s fakeSubnet) DNSServers() []string { 354 return s.dnsServers 355 } 356 357 type fakeVLAN struct { 358 gomaasapi.VLAN 359 id int 360 vid int 361 mtu int 362 } 363 364 func (v fakeVLAN) ID() int { 365 return v.id 366 } 367 368 func (v fakeVLAN) VID() int { 369 return v.vid 370 } 371 372 func (v fakeVLAN) MTU() int { 373 return v.mtu 374 } 375 376 type fakeInterface struct { 377 gomaasapi.Interface 378 *testing.Stub 379 380 id int 381 name string 382 parents []string 383 children []string 384 type_ string 385 enabled bool 386 vlan gomaasapi.VLAN 387 links []gomaasapi.Link 388 macAddress string 389 } 390 391 func (v *fakeInterface) ID() int { 392 return v.id 393 } 394 395 func (v *fakeInterface) Name() string { 396 return v.name 397 } 398 399 func (v *fakeInterface) Parents() []string { 400 return v.parents 401 } 402 403 func (v *fakeInterface) Children() []string { 404 return v.children 405 } 406 407 func (v *fakeInterface) Type() string { 408 return v.type_ 409 } 410 411 func (v *fakeInterface) EffectiveMTU() int { 412 return 1500 413 } 414 415 func (v *fakeInterface) Enabled() bool { 416 return v.enabled 417 } 418 419 func (v *fakeInterface) VLAN() gomaasapi.VLAN { 420 return v.vlan 421 } 422 423 func (v *fakeInterface) Links() []gomaasapi.Link { 424 return v.links 425 } 426 427 func (v *fakeInterface) MACAddress() string { 428 return v.macAddress 429 } 430 431 func (v *fakeInterface) LinkSubnet(args gomaasapi.LinkSubnetArgs) error { 432 v.MethodCall(v, "LinkSubnet", args) 433 return v.NextErr() 434 } 435 436 type fakeLink struct { 437 gomaasapi.Link 438 id int 439 mode string 440 subnet gomaasapi.Subnet 441 ipAddress string 442 } 443 444 func (l *fakeLink) ID() int { 445 return l.id 446 } 447 448 func (l *fakeLink) Mode() string { 449 return l.mode 450 } 451 452 func (l *fakeLink) Subnet() gomaasapi.Subnet { 453 return l.subnet 454 } 455 456 func (l *fakeLink) IPAddress() string { 457 return l.ipAddress 458 } 459 460 type fakeFile struct { 461 gomaasapi.File 462 name string 463 url string 464 contents []byte 465 deleted bool 466 error error 467 } 468 469 func (f *fakeFile) Filename() string { 470 return f.name 471 } 472 473 func (f *fakeFile) AnonymousURL() string { 474 return f.url 475 } 476 477 func (f *fakeFile) Delete() error { 478 f.deleted = true 479 return f.error 480 } 481 482 func (f *fakeFile) ReadAll() ([]byte, error) { 483 if f.error != nil { 484 return nil, f.error 485 } 486 return f.contents, nil 487 } 488 489 type fakeBlockDevice struct { 490 gomaasapi.BlockDevice 491 name string 492 path string 493 size uint64 494 } 495 496 func (bd fakeBlockDevice) Name() string { 497 return bd.name 498 } 499 500 func (bd fakeBlockDevice) Path() string { 501 return bd.path 502 } 503 504 func (bd fakeBlockDevice) Size() uint64 { 505 return bd.size 506 } 507 508 type fakeDevice struct { 509 gomaasapi.Device 510 *testing.Stub 511 512 interfaceSet []gomaasapi.Interface 513 systemID string 514 interface_ gomaasapi.Interface 515 } 516 517 func (d *fakeDevice) InterfaceSet() []gomaasapi.Interface { 518 return d.interfaceSet 519 } 520 521 func (d *fakeDevice) SystemID() string { 522 return d.systemID 523 } 524 525 func (d *fakeDevice) CreateInterface(args gomaasapi.CreateInterfaceArgs) (gomaasapi.Interface, error) { 526 d.MethodCall(d, "CreateInterface", args) 527 d.interfaceSet = append(d.interfaceSet, d.interface_) 528 return d.interface_, d.NextErr() 529 } 530 531 func (d *fakeDevice) Delete() error { 532 d.MethodCall(d, "Delete") 533 return d.NextErr() 534 }