github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/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 fakeBootResource struct { 188 gomaasapi.BootResource 189 name string 190 architecture string 191 } 192 193 func (r *fakeBootResource) Name() string { 194 return r.name 195 } 196 197 func (r *fakeBootResource) Architecture() string { 198 return r.architecture 199 } 200 201 type fakeMachine struct { 202 gomaasapi.Machine 203 *testing.Stub 204 205 zoneName string 206 hostname string 207 systemID string 208 ipAddresses []string 209 statusName string 210 statusMessage string 211 cpuCount int 212 memory int 213 architecture string 214 interfaceSet []gomaasapi.Interface 215 tags []string 216 createDevice gomaasapi.Device 217 } 218 219 func newFakeMachine(systemID, architecture, statusName string) *fakeMachine { 220 return &fakeMachine{ 221 Stub: &testing.Stub{}, 222 systemID: systemID, 223 architecture: architecture, 224 statusName: statusName, 225 } 226 } 227 228 func (m *fakeMachine) Tags() []string { 229 return m.tags 230 } 231 232 func (m *fakeMachine) SetOwnerData(data map[string]string) error { 233 m.MethodCall(m, "SetOwnerData", data) 234 return m.NextErr() 235 } 236 237 func (m *fakeMachine) CPUCount() int { 238 return m.cpuCount 239 } 240 241 func (m *fakeMachine) Memory() int { 242 return m.memory 243 } 244 245 func (m *fakeMachine) Architecture() string { 246 return m.architecture 247 } 248 249 func (m *fakeMachine) SystemID() string { 250 return m.systemID 251 } 252 253 func (m *fakeMachine) Hostname() string { 254 return m.hostname 255 } 256 257 func (m *fakeMachine) IPAddresses() []string { 258 return m.ipAddresses 259 } 260 261 func (m *fakeMachine) StatusName() string { 262 return m.statusName 263 } 264 265 func (m *fakeMachine) StatusMessage() string { 266 return m.statusMessage 267 } 268 269 func (m *fakeMachine) Zone() gomaasapi.Zone { 270 return fakeZone{name: m.zoneName} 271 } 272 273 func (m *fakeMachine) InterfaceSet() []gomaasapi.Interface { 274 return m.interfaceSet 275 } 276 277 func (m *fakeMachine) Start(args gomaasapi.StartArgs) error { 278 m.MethodCall(m, "Start", args) 279 return m.NextErr() 280 } 281 282 func (m *fakeMachine) CreateDevice(args gomaasapi.CreateMachineDeviceArgs) (gomaasapi.Device, error) { 283 m.MethodCall(m, "CreateDevice", args) 284 return m.createDevice, m.NextErr() 285 } 286 287 type fakeZone struct { 288 gomaasapi.Zone 289 name string 290 } 291 292 func (z fakeZone) Name() string { 293 return z.name 294 } 295 296 type fakeSpace struct { 297 gomaasapi.Space 298 name string 299 id int 300 subnets []gomaasapi.Subnet 301 } 302 303 func (s fakeSpace) Name() string { 304 return s.name 305 } 306 307 func (s fakeSpace) ID() int { 308 return s.id 309 } 310 311 func (s fakeSpace) Subnets() []gomaasapi.Subnet { 312 return s.subnets 313 } 314 315 type fakeSubnet struct { 316 gomaasapi.Subnet 317 id int 318 space string 319 vlan gomaasapi.VLAN 320 gateway string 321 cidr string 322 dnsServers []string 323 } 324 325 func (s fakeSubnet) ID() int { 326 return s.id 327 } 328 329 func (s fakeSubnet) Space() string { 330 return s.space 331 } 332 333 func (s fakeSubnet) VLAN() gomaasapi.VLAN { 334 return s.vlan 335 } 336 337 func (s fakeSubnet) Gateway() string { 338 return s.gateway 339 } 340 341 func (s fakeSubnet) CIDR() string { 342 return s.cidr 343 } 344 345 func (s fakeSubnet) DNSServers() []string { 346 return s.dnsServers 347 } 348 349 type fakeVLAN struct { 350 gomaasapi.VLAN 351 id int 352 vid int 353 mtu int 354 } 355 356 func (v fakeVLAN) ID() int { 357 return v.id 358 } 359 360 func (v fakeVLAN) VID() int { 361 return v.vid 362 } 363 364 func (v fakeVLAN) MTU() int { 365 return v.mtu 366 } 367 368 type fakeInterface struct { 369 gomaasapi.Interface 370 *testing.Stub 371 372 id int 373 name string 374 parents []string 375 children []string 376 type_ string 377 enabled bool 378 vlan gomaasapi.VLAN 379 links []gomaasapi.Link 380 macAddress string 381 } 382 383 func (v *fakeInterface) ID() int { 384 return v.id 385 } 386 387 func (v *fakeInterface) Name() string { 388 return v.name 389 } 390 391 func (v *fakeInterface) Parents() []string { 392 return v.parents 393 } 394 395 func (v *fakeInterface) Children() []string { 396 return v.children 397 } 398 399 func (v *fakeInterface) Type() string { 400 return v.type_ 401 } 402 403 func (v *fakeInterface) EffectiveMTU() int { 404 return 1500 405 } 406 407 func (v *fakeInterface) Enabled() bool { 408 return v.enabled 409 } 410 411 func (v *fakeInterface) VLAN() gomaasapi.VLAN { 412 return v.vlan 413 } 414 415 func (v *fakeInterface) Links() []gomaasapi.Link { 416 return v.links 417 } 418 419 func (v *fakeInterface) MACAddress() string { 420 return v.macAddress 421 } 422 423 func (v *fakeInterface) LinkSubnet(args gomaasapi.LinkSubnetArgs) error { 424 v.MethodCall(v, "LinkSubnet", args) 425 return v.NextErr() 426 } 427 428 type fakeLink struct { 429 gomaasapi.Link 430 id int 431 mode string 432 subnet gomaasapi.Subnet 433 ipAddress string 434 } 435 436 func (l *fakeLink) ID() int { 437 return l.id 438 } 439 440 func (l *fakeLink) Mode() string { 441 return l.mode 442 } 443 444 func (l *fakeLink) Subnet() gomaasapi.Subnet { 445 return l.subnet 446 } 447 448 func (l *fakeLink) IPAddress() string { 449 return l.ipAddress 450 } 451 452 type fakeFile struct { 453 gomaasapi.File 454 name string 455 url string 456 contents []byte 457 deleted bool 458 error error 459 } 460 461 func (f *fakeFile) Filename() string { 462 return f.name 463 } 464 465 func (f *fakeFile) AnonymousURL() string { 466 return f.url 467 } 468 469 func (f *fakeFile) Delete() error { 470 f.deleted = true 471 return f.error 472 } 473 474 func (f *fakeFile) ReadAll() ([]byte, error) { 475 if f.error != nil { 476 return nil, f.error 477 } 478 return f.contents, nil 479 } 480 481 type fakeBlockDevice struct { 482 gomaasapi.BlockDevice 483 name string 484 path string 485 size uint64 486 } 487 488 func (bd fakeBlockDevice) Name() string { 489 return bd.name 490 } 491 492 func (bd fakeBlockDevice) Path() string { 493 return bd.path 494 } 495 496 func (bd fakeBlockDevice) Size() uint64 { 497 return bd.size 498 } 499 500 type fakeDevice struct { 501 gomaasapi.Device 502 *testing.Stub 503 504 interfaceSet []gomaasapi.Interface 505 systemID string 506 interface_ gomaasapi.Interface 507 } 508 509 func (d *fakeDevice) InterfaceSet() []gomaasapi.Interface { 510 return d.interfaceSet 511 } 512 513 func (d *fakeDevice) SystemID() string { 514 return d.systemID 515 } 516 517 func (d *fakeDevice) CreateInterface(args gomaasapi.CreateInterfaceArgs) (gomaasapi.Interface, error) { 518 d.MethodCall(d, "CreateInterface", args) 519 d.interfaceSet = append(d.interfaceSet, d.interface_) 520 return d.interface_, d.NextErr() 521 } 522 523 func (d *fakeDevice) Delete() error { 524 d.MethodCall(d, "Delete") 525 return d.NextErr() 526 }