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 }