github.com/mattyw/juju@v0.0.0-20140610034352-732aecd63861/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  	jc "github.com/juju/testing/checkers"
    10  	gc "launchpad.net/gocheck"
    11  	"launchpad.net/gomaasapi"
    12  
    13  	"github.com/juju/juju/environs/config"
    14  	"github.com/juju/juju/environs/network"
    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  
    48  func (s *environSuite) TearDownTest(c *gc.C) {
    49  	s.testMAASObject.TestServer.Clear()
    50  	s.ToolsFixture.TearDownTest(c)
    51  	s.BaseSuite.TearDownTest(c)
    52  }
    53  
    54  func (s *environSuite) TearDownSuite(c *gc.C) {
    55  	s.testMAASObject.Close()
    56  	s.restoreTimeouts()
    57  	s.BaseSuite.TearDownSuite(c)
    58  }
    59  
    60  func getSimpleTestConfig(c *gc.C, extraAttrs coretesting.Attrs) *config.Config {
    61  	attrs := coretesting.FakeConfig()
    62  	attrs["type"] = "maas"
    63  	attrs["maas-server"] = "http://maas.testing.invalid"
    64  	attrs["maas-oauth"] = "a:b:c"
    65  	for k, v := range extraAttrs {
    66  		attrs[k] = v
    67  	}
    68  	cfg, err := config.New(config.NoDefaults, attrs)
    69  	c.Assert(err, gc.IsNil)
    70  	return cfg
    71  }
    72  
    73  func (*environSuite) TestSetConfigValidatesFirst(c *gc.C) {
    74  	// SetConfig() validates the config change and disallows, for example,
    75  	// changes in the environment name.
    76  	oldCfg := getSimpleTestConfig(c, coretesting.Attrs{"name": "old-name"})
    77  	newCfg := getSimpleTestConfig(c, coretesting.Attrs{"name": "new-name"})
    78  	env, err := maas.NewEnviron(oldCfg)
    79  	c.Assert(err, gc.IsNil)
    80  
    81  	// SetConfig() fails, even though both the old and the new config are
    82  	// individually valid.
    83  	err = env.SetConfig(newCfg)
    84  	c.Assert(err, gc.NotNil)
    85  	c.Check(err, gc.ErrorMatches, ".*cannot change name.*")
    86  
    87  	// The old config is still in place.  The new config never took effect.
    88  	c.Check(env.Name(), gc.Equals, "old-name")
    89  }
    90  
    91  func (*environSuite) TestSetConfigRefusesChangingAgentName(c *gc.C) {
    92  	oldCfg := getSimpleTestConfig(c, coretesting.Attrs{"maas-agent-name": "agent-one"})
    93  	newCfgTwo := getSimpleTestConfig(c, coretesting.Attrs{"maas-agent-name": "agent-two"})
    94  	env, err := maas.NewEnviron(oldCfg)
    95  	c.Assert(err, gc.IsNil)
    96  
    97  	// SetConfig() fails, even though both the old and the new config are
    98  	// individually valid.
    99  	err = env.SetConfig(newCfgTwo)
   100  	c.Assert(err, gc.NotNil)
   101  	c.Check(err, gc.ErrorMatches, ".*cannot change maas-agent-name.*")
   102  
   103  	// The old config is still in place.  The new config never took effect.
   104  	c.Check(maas.MAASAgentName(env), gc.Equals, "agent-one")
   105  
   106  	// It also refuses to set it to the empty string:
   107  	err = env.SetConfig(getSimpleTestConfig(c, coretesting.Attrs{"maas-agent-name": ""}))
   108  	c.Check(err, gc.ErrorMatches, ".*cannot change maas-agent-name.*")
   109  
   110  	// And to nil
   111  	err = env.SetConfig(getSimpleTestConfig(c, nil))
   112  	c.Check(err, gc.ErrorMatches, ".*cannot change maas-agent-name.*")
   113  }
   114  
   115  func (*environSuite) TestSetConfigAllowsEmptyFromNilAgentName(c *gc.C) {
   116  	// bug #1256179 is that when using an older version of Juju (<1.16.2)
   117  	// we didn't include maas-agent-name in the database, so it was 'nil'
   118  	// in the OldConfig. However, when setting an environment, we would set
   119  	// it to "" (because maasEnvironConfig.Validate ensures it is a 'valid'
   120  	// string). We can't create that from NewEnviron or newConfig because
   121  	// both of them Validate the contents. 'cmd/juju/environment
   122  	// SetEnvironmentCommand' instead uses conn.State.EnvironConfig() which
   123  	// just reads the content of the database into a map, so we just create
   124  	// the map ourselves.
   125  
   126  	// Even though we use 'nil' here, it actually stores it as "" because
   127  	// 1.16.2 already validates the value
   128  	baseCfg := getSimpleTestConfig(c, coretesting.Attrs{"maas-agent-name": ""})
   129  	c.Check(baseCfg.UnknownAttrs()["maas-agent-name"], gc.Equals, "")
   130  	env, err := maas.NewEnviron(baseCfg)
   131  	c.Assert(err, gc.IsNil)
   132  	provider := env.Provider()
   133  
   134  	attrs := coretesting.FakeConfig()
   135  	// These are attrs we need to make it a valid Config, but would usually
   136  	// be set by other infrastructure
   137  	attrs["type"] = "maas"
   138  	nilCfg, err := config.New(config.NoDefaults, attrs)
   139  	c.Assert(err, gc.IsNil)
   140  	validatedConfig, err := provider.Validate(baseCfg, nilCfg)
   141  	c.Assert(err, gc.IsNil)
   142  	c.Check(validatedConfig.UnknownAttrs()["maas-agent-name"], gc.Equals, "")
   143  	// However, you can't set it to an actual value if you haven't been using a value
   144  	valueCfg := getSimpleTestConfig(c, coretesting.Attrs{"maas-agent-name": "agent-name"})
   145  	_, err = provider.Validate(valueCfg, nilCfg)
   146  	c.Check(err, gc.ErrorMatches, ".*cannot change maas-agent-name.*")
   147  }
   148  
   149  func (*environSuite) TestSetConfigAllowsChangingNilAgentNameToEmptyString(c *gc.C) {
   150  	oldCfg := getSimpleTestConfig(c, nil)
   151  	newCfgTwo := getSimpleTestConfig(c, coretesting.Attrs{"maas-agent-name": ""})
   152  	env, err := maas.NewEnviron(oldCfg)
   153  	c.Assert(err, gc.IsNil)
   154  
   155  	err = env.SetConfig(newCfgTwo)
   156  	c.Assert(err, gc.IsNil)
   157  	c.Check(maas.MAASAgentName(env), gc.Equals, "")
   158  }
   159  
   160  func (*environSuite) TestSetConfigUpdatesConfig(c *gc.C) {
   161  	origAttrs := coretesting.Attrs{
   162  		"server-name":  "http://maas2.testing.invalid",
   163  		"maas-oauth":   "a:b:c",
   164  		"admin-secret": "secret",
   165  	}
   166  	cfg := getSimpleTestConfig(c, origAttrs)
   167  	env, err := maas.NewEnviron(cfg)
   168  	c.Check(err, gc.IsNil)
   169  	c.Check(env.Name(), gc.Equals, "testenv")
   170  
   171  	anotherServer := "http://maas.testing.invalid"
   172  	anotherOauth := "c:d:e"
   173  	anotherSecret := "secret2"
   174  	newAttrs := coretesting.Attrs{
   175  		"server-name":  anotherServer,
   176  		"maas-oauth":   anotherOauth,
   177  		"admin-secret": anotherSecret,
   178  	}
   179  	cfg2 := getSimpleTestConfig(c, newAttrs)
   180  	errSetConfig := env.SetConfig(cfg2)
   181  	c.Check(errSetConfig, gc.IsNil)
   182  	c.Check(env.Name(), gc.Equals, "testenv")
   183  	authClient, _ := gomaasapi.NewAuthenticatedClient(anotherServer, anotherOauth, maas.APIVersion)
   184  	maasClient := gomaasapi.NewMAAS(*authClient)
   185  	MAASServer := maas.GetMAASClient(env)
   186  	c.Check(MAASServer, gc.DeepEquals, maasClient)
   187  }
   188  
   189  func (*environSuite) TestNewEnvironSetsConfig(c *gc.C) {
   190  	cfg := getSimpleTestConfig(c, nil)
   191  
   192  	env, err := maas.NewEnviron(cfg)
   193  
   194  	c.Check(err, gc.IsNil)
   195  	c.Check(env.Name(), gc.Equals, "testenv")
   196  }
   197  
   198  func (*environSuite) TestNewCloudinitConfig(c *gc.C) {
   199  	nwInfo := []network.Info{
   200  		// physical eth0 won't be touched, but it can have VLANs on it.
   201  		{InterfaceName: "eth0", VLANTag: 0, Disabled: false},
   202  		{InterfaceName: "eth0", VLANTag: 99, Disabled: false},
   203  		// physical NIC given explicitly, then a couple of virtual ones using it.
   204  		{InterfaceName: "eth1", VLANTag: 0, Disabled: false},
   205  		{InterfaceName: "eth1", VLANTag: 42, Disabled: false},
   206  		{InterfaceName: "eth1", VLANTag: 69, Disabled: false},
   207  		{InterfaceName: "eth2", VLANTag: 0, Disabled: false},
   208  		// physical NIC not given, ensure it gets brought up first, before the virtual one.
   209  		{InterfaceName: "eth3", VLANTag: 123, Disabled: false},
   210  		// disabled NICs should still be configured (for now)
   211  		{InterfaceName: "eth4", VLANTag: 0, Disabled: true},
   212  		{InterfaceName: "eth4", VLANTag: 12, Disabled: true},
   213  		{InterfaceName: "eth5", VLANTag: 66, Disabled: true},
   214  	}
   215  	cloudcfg, err := maas.NewCloudinitConfig("testing.invalid", nwInfo)
   216  	c.Assert(err, gc.IsNil)
   217  	c.Assert(cloudcfg.AptUpdate(), jc.IsTrue)
   218  	c.Assert(cloudcfg.RunCmds(), jc.DeepEquals, []interface{}{
   219  		"set -xe",
   220  		"mkdir -p '/var/lib/juju'; echo -n 'hostname: testing.invalid\n' > '/var/lib/juju/MAASmachine.txt'",
   221  		"ifdown eth0",
   222  		"cat > /etc/network/eth0.config << EOF\niface eth0 inet manual\n\nauto br0\niface br0 inet dhcp\n  bridge_ports eth0\nEOF\n",
   223  		`sed -i "s/iface eth0 inet dhcp/source \/etc\/network\/eth0.config/" /etc/network/interfaces`,
   224  		"ifup br0",
   225  		// Networking/VLAN stuff.
   226  		"sh -c 'lsmod | grep -q 8021q || modprobe 8021q'",
   227  		"sh -c 'grep -q 8021q /etc/modules || echo 8021q >> /etc/modules'",
   228  		"vconfig set_name_type DEV_PLUS_VID_NO_PAD",
   229  		"vconfig add eth0 99",
   230  		"cat >> /etc/network/interfaces << EOF\n\nauto eth0.99\niface eth0.99 inet dhcp\nEOF\n",
   231  		"ifup eth0.99",
   232  		"cat >> /etc/network/interfaces << EOF\n\nauto eth1\niface eth1 inet dhcp\nEOF\n",
   233  		"ifup eth1",
   234  		"vconfig add eth1 42",
   235  		"cat >> /etc/network/interfaces << EOF\n\nauto eth1.42\niface eth1.42 inet dhcp\nEOF\n",
   236  		"ifup eth1.42",
   237  		"vconfig add eth1 69",
   238  		"cat >> /etc/network/interfaces << EOF\n\nauto eth1.69\niface eth1.69 inet dhcp\nEOF\n",
   239  		"ifup eth1.69",
   240  		"cat >> /etc/network/interfaces << EOF\n\nauto eth2\niface eth2 inet dhcp\nEOF\n",
   241  		"ifup eth2",
   242  		"cat >> /etc/network/interfaces << EOF\n\nauto eth3\niface eth3 inet dhcp\nEOF\n",
   243  		"ifup eth3",
   244  		"vconfig add eth3 123",
   245  		"cat >> /etc/network/interfaces << EOF\n\nauto eth3.123\niface eth3.123 inet dhcp\nEOF\n",
   246  		"ifup eth3.123",
   247  		"cat >> /etc/network/interfaces << EOF\n\nauto eth4\niface eth4 inet dhcp\nEOF\n",
   248  		"ifup eth4",
   249  		"vconfig add eth4 12",
   250  		"cat >> /etc/network/interfaces << EOF\n\nauto eth4.12\niface eth4.12 inet dhcp\nEOF\n",
   251  		"ifup eth4.12",
   252  		"cat >> /etc/network/interfaces << EOF\n\nauto eth5\niface eth5 inet dhcp\nEOF\n",
   253  		"ifup eth5",
   254  		"vconfig add eth5 66",
   255  		"cat >> /etc/network/interfaces << EOF\n\nauto eth5.66\niface eth5.66 inet dhcp\nEOF\n",
   256  		"ifup eth5.66",
   257  	})
   258  }