github.com/mwhudson/juju@v0.0.0-20160512215208-90ff01f3497f/provider/maas/environ_test.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package maas_test
     5  
     6  import (
     7  	stdtesting "testing"
     8  
     9  	"github.com/juju/gomaasapi"
    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  	envtesting "github.com/juju/juju/environs/testing"
    16  	"github.com/juju/juju/provider/maas"
    17  	coretesting "github.com/juju/juju/testing"
    18  )
    19  
    20  type environSuite struct {
    21  	coretesting.BaseSuite
    22  	envtesting.ToolsFixture
    23  	testMAASObject  *gomaasapi.TestMAASObject
    24  	restoreTimeouts func()
    25  }
    26  
    27  var _ = gc.Suite(&environSuite{})
    28  
    29  func TestMAAS(t *stdtesting.T) {
    30  	gc.TestingT(t)
    31  }
    32  
    33  // TDOO: jam 2013-12-06 This is copied from the providerSuite which is in a
    34  // whitebox package maas. Either move that into a whitebox test so it can be
    35  // shared, or into a 'testing' package so we can use it here.
    36  func (s *environSuite) SetUpSuite(c *gc.C) {
    37  	s.restoreTimeouts = envtesting.PatchAttemptStrategies(maas.ShortAttempt)
    38  	s.BaseSuite.SetUpSuite(c)
    39  	TestMAASObject := gomaasapi.NewTestMAAS("1.0")
    40  	s.testMAASObject = TestMAASObject
    41  }
    42  
    43  func (s *environSuite) SetUpTest(c *gc.C) {
    44  	s.BaseSuite.SetUpTest(c)
    45  	s.ToolsFixture.SetUpTest(c)
    46  
    47  	mockCapabilities := func(client *gomaasapi.MAASObject) (set.Strings, error) {
    48  		return set.NewStrings("network-deployment-ubuntu"), nil
    49  	}
    50  	mockGetController := func(maasServer, apiKey string) (gomaasapi.Controller, error) {
    51  		return nil, gomaasapi.NewUnsupportedVersionError("oops")
    52  	}
    53  	s.PatchValue(&maas.GetCapabilities, mockCapabilities)
    54  	s.PatchValue(&maas.GetMAAS2Controller, mockGetController)
    55  }
    56  
    57  func (s *environSuite) TearDownTest(c *gc.C) {
    58  	s.testMAASObject.TestServer.Clear()
    59  	s.ToolsFixture.TearDownTest(c)
    60  	s.BaseSuite.TearDownTest(c)
    61  }
    62  
    63  func (s *environSuite) TearDownSuite(c *gc.C) {
    64  	s.testMAASObject.Close()
    65  	s.restoreTimeouts()
    66  	s.BaseSuite.TearDownSuite(c)
    67  }
    68  
    69  func getSimpleTestConfig(c *gc.C, extraAttrs coretesting.Attrs) *config.Config {
    70  	attrs := coretesting.FakeConfig()
    71  	attrs["type"] = "maas"
    72  	attrs["maas-server"] = "http://maas.testing.invalid"
    73  	attrs["maas-oauth"] = "a:b:c"
    74  	for k, v := range extraAttrs {
    75  		attrs[k] = v
    76  	}
    77  	cfg, err := config.New(config.NoDefaults, attrs)
    78  	c.Assert(err, jc.ErrorIsNil)
    79  	return cfg
    80  }
    81  
    82  func (*environSuite) TestSetConfigValidatesFirst(c *gc.C) {
    83  	// SetConfig() validates the config change and disallows, for example,
    84  	// changes in the environment name.
    85  	oldCfg := getSimpleTestConfig(c, coretesting.Attrs{"name": "old-name"})
    86  	newCfg := getSimpleTestConfig(c, coretesting.Attrs{"name": "new-name"})
    87  	env, err := maas.NewEnviron(oldCfg)
    88  	c.Assert(err, jc.ErrorIsNil)
    89  
    90  	// SetConfig() fails, even though both the old and the new config are
    91  	// individually valid.
    92  	err = env.SetConfig(newCfg)
    93  	c.Assert(err, gc.NotNil)
    94  	c.Check(err, gc.ErrorMatches, ".*cannot change name.*")
    95  
    96  	// The old config is still in place.  The new config never took effect.
    97  	c.Check(env.Config().Name(), gc.Equals, "old-name")
    98  }
    99  
   100  func (*environSuite) TestSetConfigRefusesChangingAgentName(c *gc.C) {
   101  	oldCfg := getSimpleTestConfig(c, coretesting.Attrs{"maas-agent-name": "agent-one"})
   102  	newCfgTwo := getSimpleTestConfig(c, coretesting.Attrs{"maas-agent-name": "agent-two"})
   103  	env, err := maas.NewEnviron(oldCfg)
   104  	c.Assert(err, jc.ErrorIsNil)
   105  
   106  	// SetConfig() fails, even though both the old and the new config are
   107  	// individually valid.
   108  	err = env.SetConfig(newCfgTwo)
   109  	c.Assert(err, gc.NotNil)
   110  	c.Check(err, gc.ErrorMatches, ".*cannot change maas-agent-name.*")
   111  
   112  	// The old config is still in place.  The new config never took effect.
   113  	c.Check(maas.MAASAgentName(env), gc.Equals, "agent-one")
   114  
   115  	// It also refuses to set it to the empty string:
   116  	err = env.SetConfig(getSimpleTestConfig(c, coretesting.Attrs{"maas-agent-name": ""}))
   117  	c.Check(err, gc.ErrorMatches, ".*cannot change maas-agent-name.*")
   118  
   119  	// And to nil
   120  	err = env.SetConfig(getSimpleTestConfig(c, nil))
   121  	c.Check(err, gc.ErrorMatches, ".*cannot change maas-agent-name.*")
   122  }
   123  
   124  func (*environSuite) TestSetConfigAllowsEmptyFromNilAgentName(c *gc.C) {
   125  	// bug #1256179 is that when using an older version of Juju (<1.16.2)
   126  	// we didn't include maas-agent-name in the database, so it was 'nil'
   127  	// in the OldConfig. However, when setting an environment, we would set
   128  	// it to "" (because maasModelConfig.Validate ensures it is a 'valid'
   129  	// string). We can't create that from NewEnviron or newConfig because
   130  	// both of them Validate the contents. 'cmd/juju/model
   131  	// SetEnvironmentCommand' instead uses conn.State.ModelConfig() which
   132  	// just reads the content of the database into a map, so we just create
   133  	// the map ourselves.
   134  
   135  	// Even though we use 'nil' here, it actually stores it as "" because
   136  	// 1.16.2 already validates the value
   137  	baseCfg := getSimpleTestConfig(c, coretesting.Attrs{"maas-agent-name": ""})
   138  	c.Check(baseCfg.UnknownAttrs()["maas-agent-name"], gc.Equals, "")
   139  	env, err := maas.NewEnviron(baseCfg)
   140  	c.Assert(err, jc.ErrorIsNil)
   141  	provider := env.Provider()
   142  
   143  	attrs := coretesting.FakeConfig()
   144  	// These are attrs we need to make it a valid Config, but would usually
   145  	// be set by other infrastructure
   146  	attrs["type"] = "maas"
   147  	nilCfg, err := config.New(config.NoDefaults, attrs)
   148  	c.Assert(err, jc.ErrorIsNil)
   149  	validatedConfig, err := provider.Validate(baseCfg, nilCfg)
   150  	c.Assert(err, jc.ErrorIsNil)
   151  	c.Check(validatedConfig.UnknownAttrs()["maas-agent-name"], gc.Equals, "")
   152  	// However, you can't set it to an actual value if you haven't been using a value
   153  	valueCfg := getSimpleTestConfig(c, coretesting.Attrs{"maas-agent-name": "agent-name"})
   154  	_, err = provider.Validate(valueCfg, nilCfg)
   155  	c.Check(err, gc.ErrorMatches, ".*cannot change maas-agent-name.*")
   156  }
   157  
   158  func (*environSuite) TestDestroyWithEmptyAgentName(c *gc.C) {
   159  	// Related bug #1256179, comment as above.
   160  	baseCfg := getSimpleTestConfig(c, coretesting.Attrs{"maas-agent-name": ""})
   161  	env, err := maas.NewEnviron(baseCfg)
   162  	c.Assert(err, jc.ErrorIsNil)
   163  
   164  	err = env.Destroy()
   165  	c.Assert(err, gc.ErrorMatches, "unsafe destruction")
   166  }
   167  
   168  func (*environSuite) TestSetConfigAllowsChangingNilAgentNameToEmptyString(c *gc.C) {
   169  	oldCfg := getSimpleTestConfig(c, nil)
   170  	newCfgTwo := getSimpleTestConfig(c, coretesting.Attrs{"maas-agent-name": ""})
   171  	env, err := maas.NewEnviron(oldCfg)
   172  	c.Assert(err, jc.ErrorIsNil)
   173  
   174  	err = env.SetConfig(newCfgTwo)
   175  	c.Assert(err, jc.ErrorIsNil)
   176  	c.Check(maas.MAASAgentName(env), gc.Equals, "")
   177  }
   178  
   179  func (*environSuite) TestSetConfigUpdatesConfig(c *gc.C) {
   180  	origAttrs := coretesting.Attrs{
   181  		"server-name":  "http://maas2.testing.invalid",
   182  		"maas-oauth":   "a:b:c",
   183  		"admin-secret": "secret",
   184  	}
   185  	cfg := getSimpleTestConfig(c, origAttrs)
   186  	env, err := maas.NewEnviron(cfg)
   187  	c.Check(err, jc.ErrorIsNil)
   188  	c.Check(env.Config().Name(), gc.Equals, "testenv")
   189  
   190  	anotherServer := "http://maas.testing.invalid"
   191  	anotherOauth := "c:d:e"
   192  	anotherSecret := "secret2"
   193  	newAttrs := coretesting.Attrs{
   194  		"server-name":  anotherServer,
   195  		"maas-oauth":   anotherOauth,
   196  		"admin-secret": anotherSecret,
   197  	}
   198  	cfg2 := getSimpleTestConfig(c, newAttrs)
   199  	errSetConfig := env.SetConfig(cfg2)
   200  	c.Check(errSetConfig, gc.IsNil)
   201  	c.Check(env.Config().Name(), gc.Equals, "testenv")
   202  	authClient, _ := gomaasapi.NewAuthenticatedClient(anotherServer, anotherOauth, "1.0")
   203  	maasClient := gomaasapi.NewMAAS(*authClient)
   204  	MAASServer := maas.GetMAASClient(env)
   205  	c.Check(MAASServer, gc.DeepEquals, maasClient)
   206  }
   207  
   208  func (*environSuite) TestNewEnvironSetsConfig(c *gc.C) {
   209  	cfg := getSimpleTestConfig(c, nil)
   210  
   211  	env, err := maas.NewEnviron(cfg)
   212  
   213  	c.Check(err, jc.ErrorIsNil)
   214  	c.Check(env.Config().Name(), gc.Equals, "testenv")
   215  }
   216  
   217  var expectedCloudinitConfig = []string{
   218  	"set -xe",
   219  	"mkdir -p '/var/lib/juju'\ncat > '/var/lib/juju/MAASmachine.txt' << 'EOF'\n'hostname: testing.invalid\n'\nEOF\nchmod 0755 '/var/lib/juju/MAASmachine.txt'",
   220  }
   221  
   222  func (*environSuite) TestNewCloudinitConfig(c *gc.C) {
   223  	cfg := getSimpleTestConfig(c, nil)
   224  	env, err := maas.NewEnviron(cfg)
   225  	c.Assert(err, jc.ErrorIsNil)
   226  	modifyNetworkScript := maas.RenderEtcNetworkInterfacesScript()
   227  	script := expectedCloudinitConfig
   228  	script = append(script, modifyNetworkScript)
   229  	cloudcfg, err := maas.NewCloudinitConfig(env, "testing.invalid", "quantal")
   230  	c.Assert(err, jc.ErrorIsNil)
   231  	c.Assert(cloudcfg.SystemUpdate(), jc.IsTrue)
   232  	c.Assert(cloudcfg.RunCmds(), jc.DeepEquals, script)
   233  }
   234  
   235  func (*environSuite) TestNewCloudinitConfigWithDisabledNetworkManagement(c *gc.C) {
   236  	attrs := coretesting.Attrs{
   237  		"disable-network-management": true,
   238  	}
   239  	cfg := getSimpleTestConfig(c, attrs)
   240  	env, err := maas.NewEnviron(cfg)
   241  	c.Assert(err, jc.ErrorIsNil)
   242  	cloudcfg, err := maas.NewCloudinitConfig(env, "testing.invalid", "quantal")
   243  	c.Assert(err, jc.ErrorIsNil)
   244  	c.Assert(cloudcfg.SystemUpdate(), jc.IsTrue)
   245  	c.Assert(cloudcfg.RunCmds(), jc.DeepEquals, expectedCloudinitConfig)
   246  }