github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/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/collections/set" 8 "github.com/juju/errors" 9 "github.com/juju/gomaasapi" 10 "github.com/juju/testing" 11 jc "github.com/juju/testing/checkers" 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, nil) 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 domains []gomaasapi.Domain 67 bootResources []gomaasapi.BootResource 68 bootResourcesError error 69 machines []gomaasapi.Machine 70 machinesError error 71 machinesArgsCheck func(gomaasapi.MachinesArgs) 72 zones []gomaasapi.Zone 73 zonesError error 74 spaces []gomaasapi.Space 75 spacesError error 76 staticRoutes []gomaasapi.StaticRoute 77 staticRoutesError error 78 79 allocateMachine gomaasapi.Machine 80 allocateMachineMatches gomaasapi.ConstraintMatches 81 allocateMachineError error 82 allocateMachineArgsCheck func(gomaasapi.AllocateMachineArgs) 83 84 files []gomaasapi.File 85 86 devices []gomaasapi.Device 87 domainsError error 88 } 89 90 func newFakeController() *fakeController { 91 return &fakeController{ 92 Stub: &testing.Stub{}, 93 zones: []gomaasapi.Zone{ 94 &fakeZone{name: "mossack"}, 95 &fakeZone{name: "fonseca"}, 96 }, 97 domains: []gomaasapi.Domain{ 98 &fakeDomain{}, 99 }, 100 } 101 } 102 103 func newFakeControllerWithErrors(errors ...error) *fakeController { 104 controller := newFakeController() 105 controller.SetErrors(errors...) 106 return controller 107 } 108 109 func newFakeControllerWithFiles(files ...gomaasapi.File) *fakeController { 110 controller := newFakeController() 111 controller.files = files 112 return controller 113 } 114 115 func (c *fakeController) Devices(args gomaasapi.DevicesArgs) ([]gomaasapi.Device, error) { 116 c.MethodCall(c, "Devices", args) 117 return c.devices, c.NextErr() 118 } 119 120 func (c *fakeController) Machines(args gomaasapi.MachinesArgs) ([]gomaasapi.Machine, error) { 121 if c.machinesArgsCheck != nil { 122 c.machinesArgsCheck(args) 123 } 124 if c.machinesError != nil { 125 return nil, c.machinesError 126 } 127 if len(args.SystemIDs) > 0 { 128 result := []gomaasapi.Machine{} 129 systemIds := set.NewStrings(args.SystemIDs...) 130 for _, machine := range c.machines { 131 if systemIds.Contains(machine.SystemID()) { 132 result = append(result, machine) 133 } 134 } 135 return result, nil 136 } 137 return c.machines, nil 138 } 139 140 func (c *fakeController) Domains() ([]gomaasapi.Domain, error) { 141 return c.domains, c.domainsError 142 } 143 144 func (c *fakeController) AllocateMachine(args gomaasapi.AllocateMachineArgs) (gomaasapi.Machine, gomaasapi.ConstraintMatches, error) { 145 if c.allocateMachineArgsCheck != nil { 146 c.allocateMachineArgsCheck(args) 147 } 148 if c.allocateMachineError != nil { 149 return nil, c.allocateMachineMatches, c.allocateMachineError 150 } 151 return c.allocateMachine, c.allocateMachineMatches, nil 152 } 153 154 func (c *fakeController) BootResources() ([]gomaasapi.BootResource, error) { 155 if c.bootResourcesError != nil { 156 return nil, c.bootResourcesError 157 } 158 return c.bootResources, nil 159 } 160 161 func (c *fakeController) Zones() ([]gomaasapi.Zone, error) { 162 if c.zonesError != nil { 163 return nil, c.zonesError 164 } 165 return c.zones, nil 166 } 167 168 func (c *fakeController) Spaces() ([]gomaasapi.Space, error) { 169 if c.spacesError != nil { 170 return nil, c.spacesError 171 } 172 return c.spaces, nil 173 } 174 175 func (c *fakeController) StaticRoutes() ([]gomaasapi.StaticRoute, error) { 176 if c.staticRoutesError != nil { 177 return nil, c.staticRoutesError 178 } 179 return c.staticRoutes, nil 180 } 181 func (c *fakeController) Files(prefix string) ([]gomaasapi.File, error) { 182 c.MethodCall(c, "Files", prefix) 183 return c.files, c.NextErr() 184 } 185 186 func (c *fakeController) GetFile(filename string) (gomaasapi.File, error) { 187 c.MethodCall(c, "GetFile", filename) 188 err := c.NextErr() 189 if err != nil { 190 return nil, err 191 } 192 // Try to find the file by name (needed for testing RemoveAll) 193 for _, file := range c.files { 194 if file.Filename() == filename { 195 return file, nil 196 } 197 } 198 // The test forgot to set up matching files! 199 return nil, errors.Errorf("no file named %v found - did you set up your test correctly?", filename) 200 } 201 202 func (c *fakeController) AddFile(args gomaasapi.AddFileArgs) error { 203 c.MethodCall(c, "AddFile", args) 204 return c.NextErr() 205 } 206 207 func (c *fakeController) ReleaseMachines(args gomaasapi.ReleaseMachinesArgs) error { 208 c.MethodCall(c, "ReleaseMachines", args) 209 return c.NextErr() 210 } 211 212 type fakeMachineOnlyController struct { 213 machines []gomaasapi.Machine 214 } 215 216 func (f *fakeMachineOnlyController) Machines(gomaasapi.MachinesArgs) ([]gomaasapi.Machine, error) { 217 return f.machines, nil 218 } 219 220 type fakeBootResource struct { 221 gomaasapi.BootResource 222 name string 223 architecture string 224 } 225 226 func (r *fakeBootResource) Name() string { 227 return r.name 228 } 229 230 func (r *fakeBootResource) Architecture() string { 231 return r.architecture 232 } 233 234 type fakeMachine struct { 235 gomaasapi.Machine 236 *testing.Stub 237 238 zoneName string 239 hostname string 240 systemID string 241 ipAddresses []string 242 statusName string 243 statusMessage string 244 cpuCount int 245 memory int 246 architecture string 247 interfaceSet []gomaasapi.Interface 248 tags []string 249 createDevice gomaasapi.Device 250 devices []gomaasapi.Device 251 } 252 253 func newFakeMachine(systemID, architecture, statusName string) *fakeMachine { 254 return &fakeMachine{ 255 Stub: &testing.Stub{}, 256 systemID: systemID, 257 architecture: architecture, 258 statusName: statusName, 259 } 260 } 261 262 func (m *fakeMachine) Tags() []string { 263 return m.tags 264 } 265 266 func (m *fakeMachine) SetOwnerData(data map[string]string) error { 267 m.MethodCall(m, "SetOwnerData", data) 268 return m.NextErr() 269 } 270 271 func (m *fakeMachine) CPUCount() int { 272 return m.cpuCount 273 } 274 275 func (m *fakeMachine) Memory() int { 276 return m.memory 277 } 278 279 func (m *fakeMachine) Architecture() string { 280 return m.architecture 281 } 282 283 func (m *fakeMachine) SystemID() string { 284 return m.systemID 285 } 286 287 func (m *fakeMachine) Hostname() string { 288 return m.hostname 289 } 290 291 func (m *fakeMachine) IPAddresses() []string { 292 return m.ipAddresses 293 } 294 295 func (m *fakeMachine) StatusName() string { 296 return m.statusName 297 } 298 299 func (m *fakeMachine) StatusMessage() string { 300 return m.statusMessage 301 } 302 303 func (m *fakeMachine) Zone() gomaasapi.Zone { 304 return fakeZone{name: m.zoneName} 305 } 306 307 func (m *fakeMachine) InterfaceSet() []gomaasapi.Interface { 308 return m.interfaceSet 309 } 310 311 func (m *fakeMachine) Start(args gomaasapi.StartArgs) error { 312 m.MethodCall(m, "Start", args) 313 return m.NextErr() 314 } 315 316 func (m *fakeMachine) CreateDevice(args gomaasapi.CreateMachineDeviceArgs) (gomaasapi.Device, error) { 317 m.MethodCall(m, "CreateDevice", args) 318 err := m.NextErr() 319 if err != nil { 320 return nil, err 321 } 322 m.devices = append(m.devices, m.createDevice) 323 return m.createDevice, nil 324 } 325 326 func (m *fakeMachine) Devices(args gomaasapi.DevicesArgs) ([]gomaasapi.Device, error) { 327 m.MethodCall(m, "Devices", args) 328 err := m.NextErr() 329 if err != nil { 330 return nil, err 331 } 332 return m.devices, nil 333 } 334 335 type fakeZone struct { 336 gomaasapi.Zone 337 name string 338 } 339 340 func (z fakeZone) Name() string { 341 return z.name 342 } 343 344 type fakeSpace struct { 345 gomaasapi.Space 346 name string 347 id int 348 subnets []gomaasapi.Subnet 349 } 350 351 func (s fakeSpace) Name() string { 352 return s.name 353 } 354 355 func (s fakeSpace) ID() int { 356 return s.id 357 } 358 359 func (s fakeSpace) Subnets() []gomaasapi.Subnet { 360 return s.subnets 361 } 362 363 type fakeSubnet struct { 364 gomaasapi.Subnet 365 id int 366 space string 367 vlan gomaasapi.VLAN 368 gateway string 369 cidr string 370 dnsServers []string 371 } 372 373 func (s fakeSubnet) ID() int { 374 return s.id 375 } 376 377 func (s fakeSubnet) Space() string { 378 return s.space 379 } 380 381 func (s fakeSubnet) VLAN() gomaasapi.VLAN { 382 return s.vlan 383 } 384 385 func (s fakeSubnet) Gateway() string { 386 return s.gateway 387 } 388 389 func (s fakeSubnet) CIDR() string { 390 return s.cidr 391 } 392 393 func (s fakeSubnet) DNSServers() []string { 394 return s.dnsServers 395 } 396 397 type fakeStaticRoute struct { 398 id int 399 source fakeSubnet 400 destination fakeSubnet 401 gatewayIP string 402 metric int 403 } 404 405 var _ gomaasapi.StaticRoute = (*fakeStaticRoute)(nil) 406 407 func (r fakeStaticRoute) ID() int { 408 return r.id 409 } 410 411 func (r fakeStaticRoute) Source() gomaasapi.Subnet { 412 return r.source 413 } 414 415 func (r fakeStaticRoute) Destination() gomaasapi.Subnet { 416 return r.destination 417 } 418 419 func (r fakeStaticRoute) GatewayIP() string { 420 return r.gatewayIP 421 } 422 423 func (r fakeStaticRoute) Metric() int { 424 return r.metric 425 } 426 427 type fakeVLAN struct { 428 gomaasapi.VLAN 429 id int 430 vid int 431 mtu int 432 } 433 434 func (v fakeVLAN) ID() int { 435 return v.id 436 } 437 438 func (v fakeVLAN) VID() int { 439 return v.vid 440 } 441 442 func (v fakeVLAN) MTU() int { 443 return v.mtu 444 } 445 446 type fakeInterface struct { 447 *testing.Stub 448 449 id int 450 name string 451 parents []string 452 children []string 453 type_ string 454 enabled bool 455 vlan gomaasapi.VLAN 456 links []gomaasapi.Link 457 macAddress string 458 } 459 460 var _ gomaasapi.Interface = (*fakeInterface)(nil) 461 462 func (v *fakeInterface) ID() int { 463 return v.id 464 } 465 466 func (v *fakeInterface) Name() string { 467 return v.name 468 } 469 470 func (v *fakeInterface) Parents() []string { 471 return v.parents 472 } 473 474 func (v *fakeInterface) Children() []string { 475 return v.children 476 } 477 478 func (v *fakeInterface) Type() string { 479 return v.type_ 480 } 481 482 func (v *fakeInterface) EffectiveMTU() int { 483 return 1500 484 } 485 486 func (v *fakeInterface) Enabled() bool { 487 return v.enabled 488 } 489 490 func (v *fakeInterface) VLAN() gomaasapi.VLAN { 491 return v.vlan 492 } 493 494 func (v *fakeInterface) Links() []gomaasapi.Link { 495 return v.links 496 } 497 498 func (v *fakeInterface) MACAddress() string { 499 return v.macAddress 500 } 501 502 func (v *fakeInterface) LinkSubnet(args gomaasapi.LinkSubnetArgs) error { 503 v.MethodCall(v, "LinkSubnet", args) 504 return v.NextErr() 505 } 506 507 func (v *fakeInterface) Delete() error { 508 v.MethodCall(v, "Delete") 509 return v.NextErr() 510 } 511 512 func (v *fakeInterface) Tags() []string { 513 return nil 514 } 515 516 func (v *fakeInterface) UnlinkSubnet(gomaasapi.Subnet) error { 517 return errors.NotImplementedf("UnlinkSubnet") 518 } 519 520 func (v *fakeInterface) Update(gomaasapi.UpdateInterfaceArgs) error { 521 return errors.NotImplementedf("Update") 522 } 523 524 type fakeLink struct { 525 gomaasapi.Link 526 id int 527 mode string 528 subnet gomaasapi.Subnet 529 ipAddress string 530 } 531 532 func (l *fakeLink) ID() int { 533 return l.id 534 } 535 536 func (l *fakeLink) Mode() string { 537 return l.mode 538 } 539 540 func (l *fakeLink) Subnet() gomaasapi.Subnet { 541 return l.subnet 542 } 543 544 func (l *fakeLink) IPAddress() string { 545 return l.ipAddress 546 } 547 548 type fakeFile struct { 549 gomaasapi.File 550 name string 551 url string 552 contents []byte 553 deleted bool 554 error error 555 } 556 557 func (f *fakeFile) Filename() string { 558 return f.name 559 } 560 561 func (f *fakeFile) AnonymousURL() string { 562 return f.url 563 } 564 565 func (f *fakeFile) Delete() error { 566 f.deleted = true 567 return f.error 568 } 569 570 func (f *fakeFile) ReadAll() ([]byte, error) { 571 if f.error != nil { 572 return nil, f.error 573 } 574 return f.contents, nil 575 } 576 577 type fakeBlockDevice struct { 578 gomaasapi.BlockDevice 579 580 name string 581 idPath string 582 size uint64 583 } 584 585 func (bd fakeBlockDevice) Name() string { 586 return bd.name 587 } 588 589 func (bd fakeBlockDevice) IDPath() string { 590 return bd.idPath 591 } 592 593 func (bd fakeBlockDevice) Size() uint64 { 594 return bd.size 595 } 596 597 type fakePartition struct { 598 gomaasapi.Partition 599 600 name string 601 path string 602 size uint64 603 } 604 605 func (part fakePartition) Name() string { 606 return part.name 607 } 608 609 func (part fakePartition) Path() string { 610 return part.path 611 } 612 613 func (part fakePartition) Size() uint64 { 614 return part.size 615 } 616 617 type fakeDevice struct { 618 *testing.Stub 619 620 interfaceSet []gomaasapi.Interface 621 systemID string 622 interface_ gomaasapi.Interface 623 deleteCB func() 624 } 625 626 var _ gomaasapi.Device = (*fakeDevice)(nil) 627 628 func (d *fakeDevice) FQDN() string { 629 return "" 630 } 631 632 func (d *fakeDevice) Hostname() string { 633 return "" 634 } 635 636 func (d *fakeDevice) IPAddresses() []string { 637 addrs := make([]string, 0, len(d.interfaceSet)) 638 for _, iface := range d.interfaceSet { 639 for _, link := range iface.Links() { 640 addrs = append(addrs, link.IPAddress()) 641 } 642 } 643 return addrs 644 } 645 646 func (d *fakeDevice) Owner() string { 647 return "" 648 } 649 650 func (d *fakeDevice) Parent() string { 651 return "" 652 } 653 654 func (d *fakeDevice) Zone() gomaasapi.Zone { 655 return &fakeZone{} 656 } 657 658 func (d *fakeDevice) InterfaceSet() []gomaasapi.Interface { 659 return d.interfaceSet 660 } 661 662 func (d *fakeDevice) SystemID() string { 663 return d.systemID 664 } 665 666 func (d *fakeDevice) CreateInterface(args gomaasapi.CreateInterfaceArgs) (gomaasapi.Interface, error) { 667 d.MethodCall(d, "CreateInterface", args) 668 d.interfaceSet = append(d.interfaceSet, d.interface_) 669 return d.interface_, d.NextErr() 670 } 671 672 func (d *fakeDevice) Delete() error { 673 d.MethodCall(d, "Delete") 674 if d.deleteCB != nil { 675 d.deleteCB() 676 } 677 return d.NextErr() 678 } 679 680 type fakeDomain struct{} 681 682 func (*fakeDomain) Name() string { 683 return "maas" 684 }