launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/environs/cloudinit_test.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package environs_test 5 6 import ( 7 "time" 8 9 gc "launchpad.net/gocheck" 10 "launchpad.net/goyaml" 11 12 "launchpad.net/juju-core/agent" 13 "launchpad.net/juju-core/cert" 14 "launchpad.net/juju-core/constraints" 15 "launchpad.net/juju-core/environs" 16 "launchpad.net/juju-core/environs/cloudinit" 17 "launchpad.net/juju-core/environs/config" 18 "launchpad.net/juju-core/juju/osenv" 19 "launchpad.net/juju-core/provider/dummy" 20 "launchpad.net/juju-core/state" 21 "launchpad.net/juju-core/state/api" 22 "launchpad.net/juju-core/testing" 23 jc "launchpad.net/juju-core/testing/checkers" 24 "launchpad.net/juju-core/testing/testbase" 25 "launchpad.net/juju-core/tools" 26 "launchpad.net/juju-core/utils" 27 "launchpad.net/juju-core/version" 28 ) 29 30 // dummySampleConfig returns the dummy sample config without 31 // the state server configured. 32 // will not run a state server. 33 func dummySampleConfig() testing.Attrs { 34 return dummy.SampleConfig().Merge(testing.Attrs{ 35 "state-server": false, 36 }) 37 } 38 39 type CloudInitSuite struct { 40 testbase.LoggingSuite 41 } 42 43 var _ = gc.Suite(&CloudInitSuite{}) 44 45 func (s *CloudInitSuite) TestFinishInstanceConfig(c *gc.C) { 46 attrs := dummySampleConfig().Merge(testing.Attrs{ 47 "authorized-keys": "we-are-the-keys", 48 }) 49 cfg, err := config.New(config.NoDefaults, attrs) 50 c.Assert(err, gc.IsNil) 51 mcfg := &cloudinit.MachineConfig{ 52 StateInfo: &state.Info{Tag: "not touched"}, 53 APIInfo: &api.Info{Tag: "not touched"}, 54 } 55 err = environs.FinishMachineConfig(mcfg, cfg, constraints.Value{}) 56 c.Assert(err, gc.IsNil) 57 c.Assert(mcfg, gc.DeepEquals, &cloudinit.MachineConfig{ 58 AuthorizedKeys: "we-are-the-keys", 59 AgentEnvironment: map[string]string{ 60 agent.ProviderType: "dummy", 61 agent.ContainerType: "", 62 }, 63 StateInfo: &state.Info{Tag: "not touched"}, 64 APIInfo: &api.Info{Tag: "not touched"}, 65 DisableSSLHostnameVerification: false, 66 SyslogPort: 2345, 67 }) 68 } 69 70 func (s *CloudInitSuite) TestFinishMachineConfigNonDefault(c *gc.C) { 71 attrs := dummySampleConfig().Merge(testing.Attrs{ 72 "authorized-keys": "we-are-the-keys", 73 "ssl-hostname-verification": false, 74 "syslog-port": 8888, 75 }) 76 cfg, err := config.New(config.NoDefaults, attrs) 77 c.Assert(err, gc.IsNil) 78 mcfg := &cloudinit.MachineConfig{ 79 StateInfo: &state.Info{Tag: "not touched"}, 80 APIInfo: &api.Info{Tag: "not touched"}, 81 } 82 err = environs.FinishMachineConfig(mcfg, cfg, constraints.Value{}) 83 c.Assert(err, gc.IsNil) 84 c.Assert(mcfg, gc.DeepEquals, &cloudinit.MachineConfig{ 85 AuthorizedKeys: "we-are-the-keys", 86 AgentEnvironment: map[string]string{ 87 agent.ProviderType: "dummy", 88 agent.ContainerType: "", 89 }, 90 StateInfo: &state.Info{Tag: "not touched"}, 91 APIInfo: &api.Info{Tag: "not touched"}, 92 DisableSSLHostnameVerification: true, 93 SyslogPort: 8888, 94 }) 95 } 96 97 func (s *CloudInitSuite) TestFinishBootstrapConfig(c *gc.C) { 98 attrs := dummySampleConfig().Merge(testing.Attrs{ 99 "authorized-keys": "we-are-the-keys", 100 "admin-secret": "lisboan-pork", 101 "agent-version": "1.2.3", 102 "state-server": false, 103 }) 104 cfg, err := config.New(config.NoDefaults, attrs) 105 c.Assert(err, gc.IsNil) 106 oldAttrs := cfg.AllAttrs() 107 mcfg := &cloudinit.MachineConfig{ 108 StateServer: true, 109 } 110 cons := constraints.MustParse("mem=1T cpu-power=999999999") 111 err = environs.FinishMachineConfig(mcfg, cfg, cons) 112 c.Assert(err, gc.IsNil) 113 c.Check(mcfg.AuthorizedKeys, gc.Equals, "we-are-the-keys") 114 c.Check(mcfg.DisableSSLHostnameVerification, jc.IsFalse) 115 password := utils.UserPasswordHash("lisboan-pork", utils.CompatSalt) 116 c.Check(mcfg.APIInfo, gc.DeepEquals, &api.Info{ 117 Password: password, CACert: []byte(testing.CACert), 118 }) 119 c.Check(mcfg.StateInfo, gc.DeepEquals, &state.Info{ 120 Password: password, CACert: []byte(testing.CACert), 121 }) 122 c.Check(mcfg.StatePort, gc.Equals, cfg.StatePort()) 123 c.Check(mcfg.APIPort, gc.Equals, cfg.APIPort()) 124 c.Check(mcfg.Constraints, gc.DeepEquals, cons) 125 126 oldAttrs["ca-private-key"] = "" 127 oldAttrs["admin-secret"] = "" 128 c.Check(mcfg.Config.AllAttrs(), gc.DeepEquals, oldAttrs) 129 srvCertPEM := mcfg.StateServerCert 130 srvKeyPEM := mcfg.StateServerKey 131 _, _, err = cert.ParseCertAndKey(srvCertPEM, srvKeyPEM) 132 c.Check(err, gc.IsNil) 133 134 err = cert.Verify(srvCertPEM, []byte(testing.CACert), time.Now()) 135 c.Assert(err, gc.IsNil) 136 err = cert.Verify(srvCertPEM, []byte(testing.CACert), time.Now().AddDate(9, 0, 0)) 137 c.Assert(err, gc.IsNil) 138 err = cert.Verify(srvCertPEM, []byte(testing.CACert), time.Now().AddDate(10, 0, 1)) 139 c.Assert(err, gc.NotNil) 140 } 141 142 func (s *CloudInitSuite) TestUserData(c *gc.C) { 143 s.testUserData(c, false) 144 } 145 146 func (s *CloudInitSuite) TestStateServerUserData(c *gc.C) { 147 s.testUserData(c, true) 148 } 149 150 func (*CloudInitSuite) testUserData(c *gc.C, stateServer bool) { 151 testJujuHome := c.MkDir() 152 defer osenv.SetJujuHome(osenv.SetJujuHome(testJujuHome)) 153 tools := &tools.Tools{ 154 URL: "http://foo.com/tools/releases/juju1.2.3-linux-amd64.tgz", 155 Version: version.MustParseBinary("1.2.3-linux-amd64"), 156 } 157 envConfig, err := config.New(config.NoDefaults, dummySampleConfig()) 158 c.Assert(err, gc.IsNil) 159 160 cfg := &cloudinit.MachineConfig{ 161 MachineId: "10", 162 MachineNonce: "5432", 163 Tools: tools, 164 StateServerCert: []byte(testing.ServerCert), 165 StateServerKey: []byte(testing.ServerKey), 166 StateInfo: &state.Info{ 167 Addrs: []string{"127.0.0.1:1234"}, 168 Password: "pw1", 169 CACert: []byte("CA CERT\n" + testing.CACert), 170 Tag: "machine-10", 171 }, 172 APIInfo: &api.Info{ 173 Addrs: []string{"127.0.0.1:1234"}, 174 Password: "pw2", 175 CACert: []byte("CA CERT\n" + testing.CACert), 176 Tag: "machine-10", 177 }, 178 DataDir: environs.DataDir, 179 LogDir: environs.LogDir, 180 CloudInitOutputLog: environs.CloudInitOutputLog, 181 RsyslogConfPath: environs.RsyslogConfPath, 182 Config: envConfig, 183 StatePort: envConfig.StatePort(), 184 APIPort: envConfig.APIPort(), 185 SyslogPort: envConfig.SyslogPort(), 186 StateServer: stateServer, 187 AgentEnvironment: map[string]string{agent.ProviderType: "dummy"}, 188 AuthorizedKeys: "wheredidileavemykeys", 189 MachineAgentServiceName: "jujud-machine-10", 190 } 191 script1 := "script1" 192 script2 := "script2" 193 scripts := []string{script1, script2} 194 result, err := environs.ComposeUserData(cfg, scripts...) 195 c.Assert(err, gc.IsNil) 196 197 unzipped, err := utils.Gunzip(result) 198 c.Assert(err, gc.IsNil) 199 200 config := make(map[interface{}]interface{}) 201 err = goyaml.Unmarshal(unzipped, &config) 202 c.Assert(err, gc.IsNil) 203 204 // The scripts given to userData where added as the first 205 // commands to be run. 206 runCmd := config["runcmd"].([]interface{}) 207 c.Check(runCmd[0], gc.Equals, script1) 208 c.Check(runCmd[1], gc.Equals, script2) 209 210 if stateServer { 211 // The cloudinit config should have nothing but the basics: 212 // SSH authorized keys, the additional runcmds, and log output. 213 // 214 // Note: the additional runcmds *do* belong here, at least 215 // for MAAS. MAAS needs to configure and then bounce the 216 // network interfaces, which would sever the SSH connection 217 // in the synchronous bootstrap phase. 218 c.Check(config, gc.DeepEquals, map[interface{}]interface{}{ 219 "output": map[interface{}]interface{}{ 220 "all": "| tee -a /var/log/cloud-init-output.log", 221 }, 222 "runcmd": []interface{}{ 223 "script1", "script2", 224 "set -xe", 225 "install -D -m 644 /dev/null '/var/lib/juju/nonce.txt'", 226 "printf '%s\\n' '5432' > '/var/lib/juju/nonce.txt'", 227 }, 228 "ssh_authorized_keys": []interface{}{"wheredidileavemykeys"}, 229 }) 230 } else { 231 // Just check that the cloudinit config looks good, 232 // and that there are more runcmds than the additional 233 // ones we passed into ComposeUserData. 234 c.Check(config["apt_upgrade"], gc.Equals, true) 235 c.Check(len(runCmd) > 2, jc.IsTrue) 236 } 237 }