1
// Copyright 2016 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
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"
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"
21
type maas2Suite struct {
25
func (suite *maas2Suite) injectController(controller gomaasapi.Controller) {
26
mockGetController := func(maasServer, apiKey string) (gomaasapi.Controller, error) {
27
return controller, nil
29
suite.PatchValue(&GetMAAS2Controller, mockGetController)
32
func (suite *maas2Suite) makeEnviron(c *gc.C, controller gomaasapi.Controller) *maasEnviron {
33
if controller != nil {
34
suite.injectController(controller)
36
testAttrs := coretesting.Attrs{}
37
for k, v := range maasEnvAttrs {
40
testAttrs["agent-version"] = version.Current.String()
42
cred := cloud.NewCredential(cloud.OAuth1AuthType, map[string]string{
43
"maas-oauth": "a:b:c",
45
cloud := environs.CloudSpec{
48
Endpoint: "http://any-old-junk.invalid/",
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)
62
type fakeController struct {
66
bootResources []gomaasapi.BootResource
67
bootResourcesError error
68
machines []gomaasapi.Machine
70
machinesArgsCheck func(gomaasapi.MachinesArgs)
71
zones []gomaasapi.Zone
73
spaces []gomaasapi.Space
76
allocateMachine gomaasapi.Machine
77
allocateMachineMatches gomaasapi.ConstraintMatches
78
allocateMachineError error
79
allocateMachineArgsCheck func(gomaasapi.AllocateMachineArgs)
81
files []gomaasapi.File
83
devices []gomaasapi.Device
86
func newFakeController() *fakeController {
87
return &fakeController{Stub: &testing.Stub{}}
90
func newFakeControllerWithErrors(errors ...error) *fakeController {
91
controller := newFakeController()
92
controller.SetErrors(errors...)
96
func newFakeControllerWithFiles(files ...gomaasapi.File) *fakeController {
97
return &fakeController{Stub: &testing.Stub{}, files: files}
100
func (c *fakeController) Devices(args gomaasapi.DevicesArgs) ([]gomaasapi.Device, error) {
101
c.MethodCall(c, "Devices", args)
102
return c.devices, c.NextErr()
105
func (c *fakeController) Machines(args gomaasapi.MachinesArgs) ([]gomaasapi.Machine, error) {
106
if c.machinesArgsCheck != nil {
107
c.machinesArgsCheck(args)
109
if c.machinesError != nil {
110
return nil, c.machinesError
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)
122
return c.machines, nil
125
func (c *fakeController) AllocateMachine(args gomaasapi.AllocateMachineArgs) (gomaasapi.Machine, gomaasapi.ConstraintMatches, error) {
126
if c.allocateMachineArgsCheck != nil {
127
c.allocateMachineArgsCheck(args)
129
if c.allocateMachineError != nil {
130
return nil, c.allocateMachineMatches, c.allocateMachineError
132
return c.allocateMachine, c.allocateMachineMatches, nil
135
func (c *fakeController) BootResources() ([]gomaasapi.BootResource, error) {
136
if c.bootResourcesError != nil {
137
return nil, c.bootResourcesError
139
return c.bootResources, nil
142
func (c *fakeController) Zones() ([]gomaasapi.Zone, error) {
143
if c.zonesError != nil {
144
return nil, c.zonesError
149
func (c *fakeController) Spaces() ([]gomaasapi.Space, error) {
150
if c.spacesError != nil {
151
return nil, c.spacesError
156
func (c *fakeController) Files(prefix string) ([]gomaasapi.File, error) {
157
c.MethodCall(c, "Files", prefix)
158
return c.files, c.NextErr()
161
func (c *fakeController) GetFile(filename string) (gomaasapi.File, error) {
162
c.MethodCall(c, "GetFile", filename)
167
// Try to find the file by name (needed for testing RemoveAll)
168
for _, file := range c.files {
169
if file.Filename() == filename {
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)
177
func (c *fakeController) AddFile(args gomaasapi.AddFileArgs) error {
178
c.MethodCall(c, "AddFile", args)
182
func (c *fakeController) ReleaseMachines(args gomaasapi.ReleaseMachinesArgs) error {
183
c.MethodCall(c, "ReleaseMachines", args)
187
type fakeBootResource struct {
188
gomaasapi.BootResource
193
func (r *fakeBootResource) Name() string {
197
func (r *fakeBootResource) Architecture() string {
198
return r.architecture
201
type fakeMachine struct {
214
interfaceSet []gomaasapi.Interface
216
createDevice gomaasapi.Device
219
func newFakeMachine(systemID, architecture, statusName string) *fakeMachine {
221
Stub: &testing.Stub{},
223
architecture: architecture,
224
statusName: statusName,
228
func (m *fakeMachine) Tags() []string {
232
func (m *fakeMachine) CPUCount() int {
236
func (m *fakeMachine) Memory() int {
240
func (m *fakeMachine) Architecture() string {
241
return m.architecture
244
func (m *fakeMachine) SystemID() string {
248
func (m *fakeMachine) Hostname() string {
252
func (m *fakeMachine) IPAddresses() []string {
256
func (m *fakeMachine) StatusName() string {
260
func (m *fakeMachine) StatusMessage() string {
261
return m.statusMessage
264
func (m *fakeMachine) Zone() gomaasapi.Zone {
265
return fakeZone{name: m.zoneName}
268
func (m *fakeMachine) InterfaceSet() []gomaasapi.Interface {
269
return m.interfaceSet
272
func (m *fakeMachine) Start(args gomaasapi.StartArgs) error {
273
m.MethodCall(m, "Start", args)
277
func (m *fakeMachine) CreateDevice(args gomaasapi.CreateMachineDeviceArgs) (gomaasapi.Device, error) {
278
m.MethodCall(m, "CreateDevice", args)
279
return m.createDevice, m.NextErr()
282
type fakeZone struct {
287
func (z fakeZone) Name() string {
291
type fakeSpace struct {
295
subnets []gomaasapi.Subnet
298
func (s fakeSpace) Name() string {
302
func (s fakeSpace) ID() int {
306
func (s fakeSpace) Subnets() []gomaasapi.Subnet {
310
type fakeSubnet struct {
320
func (s fakeSubnet) ID() int {
324
func (s fakeSubnet) Space() string {
328
func (s fakeSubnet) VLAN() gomaasapi.VLAN {
332
func (s fakeSubnet) Gateway() string {
336
func (s fakeSubnet) CIDR() string {
340
func (s fakeSubnet) DNSServers() []string {
344
type fakeVLAN struct {
351
func (v fakeVLAN) ID() int {
355
func (v fakeVLAN) VID() int {
359
func (v fakeVLAN) MTU() int {
363
type fakeInterface struct {
374
links []gomaasapi.Link
378
func (v *fakeInterface) ID() int {
382
func (v *fakeInterface) Name() string {
386
func (v *fakeInterface) Parents() []string {
390
func (v *fakeInterface) Children() []string {
394
func (v *fakeInterface) Type() string {
398
func (v *fakeInterface) EffectiveMTU() int {
402
func (v *fakeInterface) Enabled() bool {
406
func (v *fakeInterface) VLAN() gomaasapi.VLAN {
410
func (v *fakeInterface) Links() []gomaasapi.Link {
414
func (v *fakeInterface) MACAddress() string {
418
func (v *fakeInterface) LinkSubnet(args gomaasapi.LinkSubnetArgs) error {
419
v.MethodCall(v, "LinkSubnet", args)
423
type fakeLink struct {
427
subnet gomaasapi.Subnet
431
func (l *fakeLink) ID() int {
435
func (l *fakeLink) Mode() string {
439
func (l *fakeLink) Subnet() gomaasapi.Subnet {
443
func (l *fakeLink) IPAddress() string {
447
type fakeFile struct {
456
func (f *fakeFile) Filename() string {
460
func (f *fakeFile) AnonymousURL() string {
464
func (f *fakeFile) Delete() error {
469
func (f *fakeFile) ReadAll() ([]byte, error) {
473
return f.contents, nil
476
type fakeBlockDevice struct {
477
gomaasapi.BlockDevice
483
func (bd fakeBlockDevice) Name() string {
487
func (bd fakeBlockDevice) Path() string {
491
func (bd fakeBlockDevice) Size() uint64 {
495
type fakeDevice struct {
499
interfaceSet []gomaasapi.Interface
501
interface_ gomaasapi.Interface
504
func (d *fakeDevice) InterfaceSet() []gomaasapi.Interface {
505
return d.interfaceSet
508
func (d *fakeDevice) SystemID() string {
512
func (d *fakeDevice) CreateInterface(args gomaasapi.CreateInterfaceArgs) (gomaasapi.Interface, error) {
513
d.MethodCall(d, "CreateInterface", args)
514
d.interfaceSet = append(d.interfaceSet, d.interface_)
515
return d.interface_, d.NextErr()
518
func (d *fakeDevice) Delete() error {
519
d.MethodCall(d, "Delete")