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