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  }