github.com/Pankov404/juju@v0.0.0-20150703034450-be266991dceb/cloudconfig/providerinit/providerinit_test.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Copyright 2015 Cloudbase Solutions SRL 3 // Licensed under the AGPLv3, see LICENCE file for details. 4 5 package providerinit_test 6 7 import ( 8 "path" 9 "time" 10 11 "github.com/juju/names" 12 jc "github.com/juju/testing/checkers" 13 "github.com/juju/utils" 14 gc "gopkg.in/check.v1" 15 goyaml "gopkg.in/yaml.v1" 16 17 "github.com/juju/juju/agent" 18 "github.com/juju/juju/api" 19 "github.com/juju/juju/apiserver/params" 20 "github.com/juju/juju/cert" 21 "github.com/juju/juju/cloudconfig/cloudinit" 22 "github.com/juju/juju/cloudconfig/instancecfg" 23 "github.com/juju/juju/cloudconfig/providerinit" 24 "github.com/juju/juju/environs/config" 25 "github.com/juju/juju/juju/osenv" 26 "github.com/juju/juju/juju/paths" 27 "github.com/juju/juju/mongo" 28 "github.com/juju/juju/provider/dummy" 29 "github.com/juju/juju/state/multiwatcher" 30 "github.com/juju/juju/testing" 31 "github.com/juju/juju/tools" 32 "github.com/juju/juju/version" 33 ) 34 35 // dummySampleConfig returns the dummy sample config without 36 // the state server configured. 37 // This function also exists in environs/config_test 38 // Maybe place it in dummy and export it? 39 func dummySampleConfig() testing.Attrs { 40 return dummy.SampleConfig().Merge(testing.Attrs{ 41 "state-server": false, 42 }) 43 } 44 45 type CloudInitSuite struct { 46 testing.BaseSuite 47 } 48 49 var _ = gc.Suite(&CloudInitSuite{}) 50 51 // TODO: add this to the utils package 52 func must(s string, err error) string { 53 if err != nil { 54 panic(err) 55 } 56 return s 57 } 58 59 func (s *CloudInitSuite) TestFinishInstanceConfig(c *gc.C) { 60 61 userTag := names.NewLocalUserTag("not-touched") 62 63 expectedMcfg := &instancecfg.InstanceConfig{ 64 AuthorizedKeys: "we-are-the-keys", 65 AgentEnvironment: map[string]string{ 66 agent.ProviderType: "dummy", 67 agent.ContainerType: "", 68 }, 69 MongoInfo: &mongo.MongoInfo{Tag: userTag}, 70 APIInfo: &api.Info{Tag: userTag}, 71 DisableSSLHostnameVerification: false, 72 PreferIPv6: true, 73 EnableOSRefreshUpdate: true, 74 EnableOSUpgrade: true, 75 } 76 77 cfg, err := config.New(config.NoDefaults, dummySampleConfig().Merge(testing.Attrs{ 78 "authorized-keys": "we-are-the-keys", 79 })) 80 c.Assert(err, jc.ErrorIsNil) 81 82 icfg := &instancecfg.InstanceConfig{ 83 MongoInfo: &mongo.MongoInfo{Tag: userTag}, 84 APIInfo: &api.Info{Tag: userTag}, 85 } 86 err = instancecfg.FinishInstanceConfig(icfg, cfg) 87 88 c.Assert(err, jc.ErrorIsNil) 89 c.Assert(icfg, jc.DeepEquals, expectedMcfg) 90 91 // Test when updates/upgrades are set to false. 92 cfg, err = config.New(config.NoDefaults, dummySampleConfig().Merge(testing.Attrs{ 93 "authorized-keys": "we-are-the-keys", 94 "enable-os-refresh-update": false, 95 "enable-os-upgrade": false, 96 })) 97 c.Assert(err, jc.ErrorIsNil) 98 err = instancecfg.FinishInstanceConfig(icfg, cfg) 99 c.Assert(err, jc.ErrorIsNil) 100 expectedMcfg.EnableOSRefreshUpdate = false 101 expectedMcfg.EnableOSUpgrade = false 102 c.Assert(icfg, jc.DeepEquals, expectedMcfg) 103 } 104 105 func (s *CloudInitSuite) TestFinishInstanceConfigNonDefault(c *gc.C) { 106 userTag := names.NewLocalUserTag("not-touched") 107 attrs := dummySampleConfig().Merge(testing.Attrs{ 108 "authorized-keys": "we-are-the-keys", 109 "ssl-hostname-verification": false, 110 }) 111 cfg, err := config.New(config.NoDefaults, attrs) 112 c.Assert(err, jc.ErrorIsNil) 113 icfg := &instancecfg.InstanceConfig{ 114 MongoInfo: &mongo.MongoInfo{Tag: userTag}, 115 APIInfo: &api.Info{Tag: userTag}, 116 } 117 err = instancecfg.FinishInstanceConfig(icfg, cfg) 118 c.Assert(err, jc.ErrorIsNil) 119 c.Assert(icfg, jc.DeepEquals, &instancecfg.InstanceConfig{ 120 AuthorizedKeys: "we-are-the-keys", 121 AgentEnvironment: map[string]string{ 122 agent.ProviderType: "dummy", 123 agent.ContainerType: "", 124 }, 125 MongoInfo: &mongo.MongoInfo{Tag: userTag}, 126 APIInfo: &api.Info{Tag: userTag}, 127 DisableSSLHostnameVerification: true, 128 PreferIPv6: true, 129 EnableOSRefreshUpdate: true, 130 EnableOSUpgrade: true, 131 }) 132 } 133 134 func (s *CloudInitSuite) TestFinishBootstrapConfig(c *gc.C) { 135 attrs := dummySampleConfig().Merge(testing.Attrs{ 136 "authorized-keys": "we-are-the-keys", 137 "admin-secret": "lisboan-pork", 138 "agent-version": "1.2.3", 139 "state-server": false, 140 }) 141 cfg, err := config.New(config.NoDefaults, attrs) 142 c.Assert(err, jc.ErrorIsNil) 143 oldAttrs := cfg.AllAttrs() 144 icfg := &instancecfg.InstanceConfig{ 145 Bootstrap: true, 146 } 147 err = instancecfg.FinishInstanceConfig(icfg, cfg) 148 c.Assert(err, jc.ErrorIsNil) 149 c.Check(icfg.AuthorizedKeys, gc.Equals, "we-are-the-keys") 150 c.Check(icfg.DisableSSLHostnameVerification, jc.IsFalse) 151 password := utils.UserPasswordHash("lisboan-pork", utils.CompatSalt) 152 c.Check(icfg.APIInfo, gc.DeepEquals, &api.Info{ 153 Password: password, CACert: testing.CACert, 154 EnvironTag: testing.EnvironmentTag, 155 }) 156 c.Check(icfg.MongoInfo, gc.DeepEquals, &mongo.MongoInfo{ 157 Password: password, Info: mongo.Info{CACert: testing.CACert}, 158 }) 159 c.Check(icfg.StateServingInfo.StatePort, gc.Equals, cfg.StatePort()) 160 c.Check(icfg.StateServingInfo.APIPort, gc.Equals, cfg.APIPort()) 161 c.Check(icfg.StateServingInfo.CAPrivateKey, gc.Equals, oldAttrs["ca-private-key"]) 162 163 oldAttrs["ca-private-key"] = "" 164 oldAttrs["admin-secret"] = "" 165 c.Check(icfg.Config.AllAttrs(), gc.DeepEquals, oldAttrs) 166 srvCertPEM := icfg.StateServingInfo.Cert 167 srvKeyPEM := icfg.StateServingInfo.PrivateKey 168 _, _, err = cert.ParseCertAndKey(srvCertPEM, srvKeyPEM) 169 c.Check(err, jc.ErrorIsNil) 170 171 err = cert.Verify(srvCertPEM, testing.CACert, time.Now()) 172 c.Assert(err, jc.ErrorIsNil) 173 err = cert.Verify(srvCertPEM, testing.CACert, time.Now().AddDate(9, 0, 0)) 174 c.Assert(err, jc.ErrorIsNil) 175 err = cert.Verify(srvCertPEM, testing.CACert, time.Now().AddDate(10, 0, 1)) 176 c.Assert(err, gc.NotNil) 177 } 178 179 func (s *CloudInitSuite) TestUserData(c *gc.C) { 180 s.testUserData(c, false) 181 } 182 183 func (s *CloudInitSuite) TestStateServerUserData(c *gc.C) { 184 s.testUserData(c, true) 185 } 186 187 func (*CloudInitSuite) testUserData(c *gc.C, bootstrap bool) { 188 testJujuHome := c.MkDir() 189 defer osenv.SetJujuHome(osenv.SetJujuHome(testJujuHome)) 190 // Use actual series paths instead of local defaults 191 logDir := must(paths.LogDir("quantal")) 192 dataDir := must(paths.DataDir("quantal")) 193 tools := &tools.Tools{ 194 URL: "http://foo.com/tools/released/juju1.2.3-quantal-amd64.tgz", 195 Version: version.MustParseBinary("1.2.3-quantal-amd64"), 196 } 197 envConfig, err := config.New(config.NoDefaults, dummySampleConfig()) 198 c.Assert(err, jc.ErrorIsNil) 199 200 series := "quantal" 201 allJobs := []multiwatcher.MachineJob{ 202 multiwatcher.JobManageEnviron, 203 multiwatcher.JobHostUnits, 204 multiwatcher.JobManageNetworking, 205 } 206 cfg := &instancecfg.InstanceConfig{ 207 MachineId: "10", 208 MachineNonce: "5432", 209 Tools: tools, 210 Series: series, 211 MongoInfo: &mongo.MongoInfo{ 212 Info: mongo.Info{ 213 Addrs: []string{"127.0.0.1:1234"}, 214 CACert: "CA CERT\n" + testing.CACert, 215 }, 216 Password: "pw1", 217 Tag: names.NewMachineTag("10"), 218 }, 219 APIInfo: &api.Info{ 220 Addrs: []string{"127.0.0.1:1234"}, 221 Password: "pw2", 222 CACert: "CA CERT\n" + testing.CACert, 223 Tag: names.NewMachineTag("10"), 224 EnvironTag: testing.EnvironmentTag, 225 }, 226 DataDir: dataDir, 227 LogDir: path.Join(logDir, "juju"), 228 Jobs: allJobs, 229 CloudInitOutputLog: path.Join(logDir, "cloud-init-output.log"), 230 Config: envConfig, 231 AgentEnvironment: map[string]string{agent.ProviderType: "dummy"}, 232 AuthorizedKeys: "wheredidileavemykeys", 233 MachineAgentServiceName: "jujud-machine-10", 234 EnableOSUpgrade: true, 235 } 236 if bootstrap { 237 cfg.Bootstrap = true 238 cfg.StateServingInfo = ¶ms.StateServingInfo{ 239 StatePort: envConfig.StatePort(), 240 APIPort: envConfig.APIPort(), 241 Cert: testing.ServerCert, 242 PrivateKey: testing.ServerKey, 243 CAPrivateKey: testing.CAKey, 244 } 245 } 246 script1 := "script1" 247 script2 := "script2" 248 cloudcfg, err := cloudinit.New(series) 249 c.Assert(err, jc.ErrorIsNil) 250 cloudcfg.AddRunCmd(script1) 251 cloudcfg.AddRunCmd(script2) 252 result, err := providerinit.ComposeUserData(cfg, cloudcfg) 253 c.Assert(err, jc.ErrorIsNil) 254 255 unzipped, err := utils.Gunzip(result) 256 c.Assert(err, jc.ErrorIsNil) 257 258 config := make(map[interface{}]interface{}) 259 err = goyaml.Unmarshal(unzipped, &config) 260 c.Assert(err, jc.ErrorIsNil) 261 262 // The scripts given to userData where added as the first 263 // commands to be run. 264 runCmd := config["runcmd"].([]interface{}) 265 c.Check(runCmd[0], gc.Equals, script1) 266 c.Check(runCmd[1], gc.Equals, script2) 267 268 if bootstrap { 269 // The cloudinit config should have nothing but the basics: 270 // SSH authorized keys, the additional runcmds, and log output. 271 // 272 // Note: the additional runcmds *do* belong here, at least 273 // for MAAS. MAAS needs to configure and then bounce the 274 // network interfaces, which would sever the SSH connection 275 // in the synchronous bootstrap phase. 276 c.Check(config, jc.DeepEquals, map[interface{}]interface{}{ 277 "output": map[interface{}]interface{}{ 278 "all": "| tee -a /var/log/cloud-init-output.log", 279 }, 280 "runcmd": []interface{}{ 281 "script1", "script2", 282 "set -xe", 283 "install -D -m 644 /dev/null '/etc/init/juju-clean-shutdown.conf'", 284 "printf '%s\\n' '\nauthor \"Juju Team <juju@lists.ubuntu.com>\"\ndescription \"Stop all network interfaces on shutdown\"\nstart on runlevel [016]\ntask\nconsole output\n\nexec /sbin/ifdown -a -v --force\n' > '/etc/init/juju-clean-shutdown.conf'", 285 "install -D -m 644 /dev/null '/var/lib/juju/nonce.txt'", 286 "printf '%s\\n' '5432' > '/var/lib/juju/nonce.txt'", 287 }, 288 "ssh_authorized_keys": []interface{}{"wheredidileavemykeys"}, 289 }) 290 } else { 291 // Just check that the cloudinit config looks good, 292 // and that there are more runcmds than the additional 293 // ones we passed into ComposeUserData. 294 c.Check(config["package_upgrade"], jc.IsTrue) 295 c.Check(len(runCmd) > 2, jc.IsTrue) 296 } 297 }