github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/provider/maas/maas_test.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package maas
     5  
     6  import (
     7  	"bytes"
     8  	"encoding/json"
     9  	"fmt"
    10  	"path/filepath"
    11  	"strconv"
    12  
    13  	"github.com/juju/collections/set"
    14  	"github.com/juju/errors"
    15  	"github.com/juju/gomaasapi"
    16  	"github.com/juju/os/series"
    17  	jc "github.com/juju/testing/checkers"
    18  	"github.com/juju/utils"
    19  	"github.com/juju/utils/arch"
    20  	gc "gopkg.in/check.v1"
    21  
    22  	"github.com/juju/juju/cloud"
    23  	"github.com/juju/juju/core/instance"
    24  	"github.com/juju/juju/environs"
    25  	"github.com/juju/juju/environs/config"
    26  	"github.com/juju/juju/environs/context"
    27  	sstesting "github.com/juju/juju/environs/simplestreams/testing"
    28  	envtesting "github.com/juju/juju/environs/testing"
    29  	envtools "github.com/juju/juju/environs/tools"
    30  	"github.com/juju/juju/juju/keys"
    31  	supportedversion "github.com/juju/juju/juju/version"
    32  	"github.com/juju/juju/network"
    33  	coretesting "github.com/juju/juju/testing"
    34  	jujuversion "github.com/juju/juju/version"
    35  )
    36  
    37  const maas2VersionResponse = `{"version": "unknown", "subversion": "", "capabilities": ["networks-management", "static-ipaddresses", "ipv6-deployment-ubuntu", "devices-management", "storage-deployment-ubuntu", "network-deployment-ubuntu"]}`
    38  
    39  const maas2DomainsResponse = `
    40  [
    41      {
    42          "authoritative": "true",
    43          "resource_uri": "/MAAS/api/2.0/domains/0/",
    44          "name": "maas",
    45          "id": 0,
    46          "ttl": null,
    47          "resource_record_count": 3
    48      }
    49  ]
    50  `
    51  
    52  type baseProviderSuite struct {
    53  	coretesting.FakeJujuXDGDataHomeSuite
    54  	envtesting.ToolsFixture
    55  	controllerUUID string
    56  
    57  	callCtx           *context.CloudCallContext
    58  	invalidCredential bool
    59  }
    60  
    61  func (suite *baseProviderSuite) setupFakeTools(c *gc.C) {
    62  	suite.PatchValue(&keys.JujuPublicKey, sstesting.SignedMetadataPublicKey)
    63  	storageDir := c.MkDir()
    64  	toolsDir := filepath.Join(storageDir, "tools")
    65  	suite.PatchValue(&envtools.DefaultBaseURL, utils.MakeFileURL(toolsDir))
    66  	suite.UploadFakeToolsToDirectory(c, storageDir, "released", "released")
    67  }
    68  
    69  func (s *baseProviderSuite) SetUpSuite(c *gc.C) {
    70  	s.FakeJujuXDGDataHomeSuite.SetUpSuite(c)
    71  	restoreTimeouts := envtesting.PatchAttemptStrategies(&shortAttempt)
    72  	restoreFinishBootstrap := envtesting.DisableFinishBootstrap()
    73  	s.AddCleanup(func(*gc.C) {
    74  		restoreFinishBootstrap()
    75  		restoreTimeouts()
    76  	})
    77  }
    78  
    79  func (s *baseProviderSuite) SetUpTest(c *gc.C) {
    80  	s.FakeJujuXDGDataHomeSuite.SetUpTest(c)
    81  	s.ToolsFixture.SetUpTest(c)
    82  	s.PatchValue(&jujuversion.Current, coretesting.FakeVersionNumber)
    83  	s.PatchValue(&arch.HostArch, func() string { return arch.AMD64 })
    84  	s.PatchValue(&series.MustHostSeries, func() string { return supportedversion.SupportedLTS() })
    85  	s.callCtx = &context.CloudCallContext{
    86  		InvalidateCredentialFunc: func(string) error {
    87  			s.invalidCredential = true
    88  			return nil
    89  		},
    90  	}
    91  }
    92  
    93  func (s *baseProviderSuite) TearDownTest(c *gc.C) {
    94  	s.invalidCredential = false
    95  	s.ToolsFixture.TearDownTest(c)
    96  	s.FakeJujuXDGDataHomeSuite.TearDownTest(c)
    97  }
    98  
    99  func (s *baseProviderSuite) TearDownSuite(c *gc.C) {
   100  	s.FakeJujuXDGDataHomeSuite.TearDownSuite(c)
   101  }
   102  
   103  type providerSuite struct {
   104  	baseProviderSuite
   105  	testMAASObject *gomaasapi.TestMAASObject
   106  }
   107  
   108  func spaceJSON(space gomaasapi.CreateSpace) *bytes.Buffer {
   109  	var out bytes.Buffer
   110  	err := json.NewEncoder(&out).Encode(space)
   111  	if err != nil {
   112  		panic(err)
   113  	}
   114  	return &out
   115  }
   116  
   117  func (s *providerSuite) SetUpSuite(c *gc.C) {
   118  	s.baseProviderSuite.SetUpSuite(c)
   119  	s.testMAASObject = gomaasapi.NewTestMAAS("1.0")
   120  }
   121  
   122  func (s *providerSuite) SetUpTest(c *gc.C) {
   123  	s.baseProviderSuite.SetUpTest(c)
   124  	mockGetController := func(string, string) (gomaasapi.Controller, error) {
   125  		return nil, gomaasapi.NewUnsupportedVersionError("oops")
   126  	}
   127  	s.PatchValue(&GetMAAS2Controller, mockGetController)
   128  	// Creating a space ensures that the spaces endpoint won't 404.
   129  	s.testMAASObject.TestServer.NewSpace(spaceJSON(gomaasapi.CreateSpace{Name: "space-0"}))
   130  }
   131  
   132  func (s *providerSuite) TearDownTest(c *gc.C) {
   133  	s.baseProviderSuite.TearDownTest(c)
   134  	s.testMAASObject.TestServer.Clear()
   135  }
   136  
   137  func (s *providerSuite) TearDownSuite(c *gc.C) {
   138  	s.baseProviderSuite.TearDownSuite(c)
   139  	s.testMAASObject.Close()
   140  }
   141  
   142  var maasEnvAttrs = coretesting.Attrs{
   143  	"name": "test-env",
   144  	"type": "maas",
   145  	config.ResourceTagsKey: map[string]string{
   146  		"claude": "rains",
   147  	},
   148  }
   149  
   150  func (suite *providerSuite) makeEnvironWithURL(url string, getCapabilities MaasCapabilities) (*maasEnviron, error) {
   151  	cred := cloud.NewCredential(cloud.OAuth1AuthType, map[string]string{
   152  		"maas-oauth": "a:b:c",
   153  	})
   154  	cloud := environs.CloudSpec{
   155  		Type:       "maas",
   156  		Name:       "maas",
   157  		Endpoint:   url,
   158  		Credential: &cred,
   159  	}
   160  	attrs := coretesting.FakeConfig().Merge(maasEnvAttrs)
   161  	suite.controllerUUID = coretesting.FakeControllerConfig().ControllerUUID()
   162  	cfg, err := config.New(config.NoDefaults, attrs)
   163  	if err != nil {
   164  		return nil, errors.Trace(err)
   165  	}
   166  	env, err := NewEnviron(cloud, cfg, getCapabilities)
   167  	if err != nil {
   168  		return nil, errors.Trace(err)
   169  	}
   170  	return env, nil
   171  }
   172  
   173  // makeEnviron creates a functional maasEnviron for a test.
   174  func (suite *providerSuite) makeEnviron() *maasEnviron {
   175  	env, err := suite.makeEnvironWithURL(
   176  		suite.testMAASObject.TestServer.URL,
   177  		func(client *gomaasapi.MAASObject, serverURL string) (set.Strings, error) {
   178  			return set.NewStrings("network-deployment-ubuntu"), nil
   179  		},
   180  	)
   181  	if err != nil {
   182  		panic(err)
   183  	}
   184  	return env
   185  }
   186  
   187  func (suite *providerSuite) addNode(jsonText string) instance.Id {
   188  	node := suite.testMAASObject.TestServer.NewNode(jsonText)
   189  	resourceURI, _ := node.GetField("resource_uri")
   190  	return instance.Id(resourceURI)
   191  }
   192  
   193  func createSubnetInfo(subnetID, spaceID, ipRange uint) network.SubnetInfo {
   194  	return network.SubnetInfo{
   195  		CIDR:            fmt.Sprintf("192.168.%d.0/24", ipRange),
   196  		ProviderId:      network.Id(strconv.Itoa(int(subnetID))),
   197  		SpaceProviderId: network.Id(fmt.Sprintf("%d", spaceID)),
   198  	}
   199  }
   200  
   201  func createSubnetWithSpace(ipRange, NICID uint, space string) gomaasapi.CreateSubnet {
   202  	var s gomaasapi.CreateSubnet
   203  	s.DNSServers = []string{"192.168.1.2"}
   204  	s.Name = fmt.Sprintf("maas-eth%d", NICID)
   205  	s.Space = space
   206  	s.GatewayIP = fmt.Sprintf("192.168.%v.1", ipRange)
   207  	s.CIDR = fmt.Sprintf("192.168.%v.0/24", ipRange)
   208  	return s
   209  }
   210  
   211  func (suite *providerSuite) addSubnet(c *gc.C, ipRange, spaceAndNICID uint, systemID string) uint {
   212  	space := fmt.Sprintf("space-%d", spaceAndNICID)
   213  	return suite.addSubnetWithSpace(c, ipRange, spaceAndNICID, space, systemID)
   214  }
   215  
   216  func (suite *providerSuite) addSubnetWithSpace(c *gc.C, ipRange, NICID uint, space string, systemID string) uint {
   217  	out := bytes.Buffer{}
   218  	err := json.NewEncoder(&out).Encode(createSubnetWithSpace(ipRange, NICID, space))
   219  	c.Assert(err, jc.ErrorIsNil)
   220  	subnet := suite.testMAASObject.TestServer.NewSubnet(&out)
   221  	c.Assert(err, jc.ErrorIsNil)
   222  
   223  	other := gomaasapi.AddressRange{}
   224  	other.Start = fmt.Sprintf("192.168.%d.139", ipRange)
   225  	other.End = fmt.Sprintf("192.168.%d.149", ipRange)
   226  	other.Purpose = []string{"not-the-dynamic-range"}
   227  	suite.testMAASObject.TestServer.AddFixedAddressRange(subnet.ID, other)
   228  
   229  	ar := gomaasapi.AddressRange{}
   230  	ar.Start = fmt.Sprintf("192.168.%d.10", ipRange)
   231  	ar.End = fmt.Sprintf("192.168.%d.138", ipRange)
   232  	ar.Purpose = []string{"something", "dynamic-range"}
   233  	suite.testMAASObject.TestServer.AddFixedAddressRange(subnet.ID, ar)
   234  	if systemID != "" {
   235  		var nni gomaasapi.NodeNetworkInterface
   236  		nni.Name = subnet.Name
   237  		nni.Links = append(nni.Links, gomaasapi.NetworkLink{
   238  			ID:     uint(1),
   239  			Mode:   "auto",
   240  			Subnet: subnet,
   241  		})
   242  		suite.testMAASObject.TestServer.SetNodeNetworkLink(systemID, nni)
   243  	}
   244  	return subnet.ID
   245  }