Пример #1
0
func (S) TestSetOutput(c *gc.C) {
	type test struct {
		kind   cloudinit.OutputKind
		stdout string
		stderr string
	}
	tests := []test{{
		cloudinit.OutAll, "a", "",
	}, {
		cloudinit.OutAll, "", "b",
	}, {
		cloudinit.OutInit, "a", "b",
	}, {
		cloudinit.OutAll, "a", "b",
	}, {
		cloudinit.OutAll, "", "",
	}}

	cfg := cloudinit.New()
	stdout, stderr := cfg.Output(cloudinit.OutAll)
	c.Assert(stdout, gc.Equals, "")
	c.Assert(stderr, gc.Equals, "")
	for i, t := range tests {
		c.Logf("test %d: %+v", i, t)
		cfg.SetOutput(t.kind, t.stdout, t.stderr)
		stdout, stderr = cfg.Output(t.kind)
		c.Assert(stdout, gc.Equals, t.stdout)
		c.Assert(stderr, gc.Equals, t.stderr)
	}
}
Пример #2
0
func (s *provisionerSuite) TestProvisioningScript(c *gc.C) {
	const series = "precise"
	const arch = "amd64"
	defer fakeSSH{
		Series:         series,
		Arch:           arch,
		InitUbuntuUser: true,
	}.install(c).Restore()
	machineId, err := manual.ProvisionMachine(s.getArgs(c))
	c.Assert(err, gc.IsNil)

	mcfg, err := client.MachineConfig(s.State, machineId, state.BootstrapNonce, "/var/lib/juju")
	c.Assert(err, gc.IsNil)
	script, err := manual.ProvisioningScript(mcfg)
	c.Assert(err, gc.IsNil)

	cloudcfg := coreCloudinit.New()
	err = cloudinit.ConfigureJuju(mcfg, cloudcfg)
	c.Assert(err, gc.IsNil)
	cloudcfg.SetAptUpgrade(false)
	sshinitScript, err := sshinit.ConfigureScript(cloudcfg)
	c.Assert(err, gc.IsNil)

	removeLogFile := "rm -f '/var/log/cloud-init-output.log'\n"
	expectedScript := removeLogFile + shell.DumpFileOnErrorScript("/var/log/cloud-init-output.log") + sshinitScript
	c.Assert(script, gc.Equals, expectedScript)
}
Пример #3
0
func (s *cloudinitSuite) TestProxyWritten(c *gc.C) {
	environConfig := minimalConfig(c)
	environConfig, err := environConfig.Apply(map[string]interface{}{
		"http-proxy": "http://[email protected]",
		"no-proxy":   "localhost,10.0.3.1",
	})
	c.Assert(err, gc.IsNil)
	machineCfg := s.createMachineConfig(c, environConfig)
	cloudcfg := coreCloudinit.New()
	err = cloudinit.Configure(machineCfg, cloudcfg)
	c.Assert(err, gc.IsNil)

	cmds := cloudcfg.RunCmds()
	first := `([ ! -e /home/ubuntu/.profile ] || grep -q '.juju-proxy' /home/ubuntu/.profile) || printf '\n# Added by juju\n[ -f "$HOME/.juju-proxy" ] && . "$HOME/.juju-proxy"\n' >> /home/ubuntu/.profile`
	expected := []interface{}{
		`export http_proxy=http://[email protected]`,
		`export HTTP_PROXY=http://[email protected]`,
		`export no_proxy=localhost,10.0.3.1`,
		`export NO_PROXY=localhost,10.0.3.1`,
		`[ -e /home/ubuntu ] && (printf '%s\n' 'export http_proxy=http://[email protected]
export HTTP_PROXY=http://[email protected]
export no_proxy=localhost,10.0.3.1
export NO_PROXY=localhost,10.0.3.1' > /home/ubuntu/.juju-proxy && chown ubuntu:ubuntu /home/ubuntu/.juju-proxy)`,
	}
	found := false
	for i, cmd := range cmds {
		if cmd == first {
			c.Assert(cmds[i+1:i+6], jc.DeepEquals, expected)
			found = true
			break
		}
	}
	c.Assert(found, jc.IsTrue)
}
Пример #4
0
func (*cloudinitSuite) TestCloudInitConfigure(c *gc.C) {
	for i, test := range cloudinitTests {
		test.cfg.Config = minimalConfig(c)
		c.Logf("test %d (Configure)", i)
		cloudcfg := coreCloudinit.New()
		err := cloudinit.Configure(&test.cfg, cloudcfg)
		c.Assert(err, gc.IsNil)
	}
}
Пример #5
0
func (S) TestRunCmds(c *gc.C) {
	cfg := cloudinit.New()
	c.Assert(cfg.RunCmds(), gc.HasLen, 0)
	cfg.AddScripts("a", "b")
	cfg.AddRunCmdArgs("c", "d")
	cfg.AddRunCmd("e")
	c.Assert(cfg.RunCmds(), gc.DeepEquals, []interface{}{
		"a", "b", []string{"c", "d"}, "e",
	})
}
Пример #6
0
func (s *cloudinitSuite) TestAptProxyNotWrittenIfNotSet(c *gc.C) {
	environConfig := minimalConfig(c)
	machineCfg := s.createMachineConfig(c, environConfig)
	cloudcfg := coreCloudinit.New()
	err := cloudinit.Configure(machineCfg, cloudcfg)
	c.Assert(err, gc.IsNil)

	cmds := cloudcfg.BootCmds()
	c.Assert(cmds, jc.DeepEquals, []interface{}{})
}
Пример #7
0
func (s *configureSuite) TestAptUpgrade(c *gc.C) {
	// apt-get upgrade is only run if AptUpgrade is set.
	aptGetUpgradePattern := aptgetRegexp + "upgrade(.|\n)*"
	cfg := cloudinit.New()
	cfg.SetAptUpdate(true)
	cfg.AddAptSource("source", "key", nil)
	assertScriptMatches(c, cfg, aptGetUpgradePattern, false)
	cfg.SetAptUpgrade(true)
	assertScriptMatches(c, cfg, aptGetUpgradePattern, true)
}
Пример #8
0
func (S) TestOutput(c *gc.C) {
	for _, t := range ctests {
		cfg := cloudinit.New()
		t.setOption(cfg)
		data, err := cfg.Render()
		c.Assert(err, gc.IsNil)
		c.Assert(data, gc.NotNil)
		c.Assert(string(data), gc.Equals, header+t.expect, gc.Commentf("test %q output differs", t.name))
	}
}
Пример #9
0
//#cloud-config
//packages:
//- juju
//- ubuntu
func ExampleConfig() {
	cfg := cloudinit.New()
	cfg.AddPackage("juju")
	cfg.AddPackage("ubuntu")
	data, err := cfg.Render()
	if err != nil {
		fmt.Printf("render error: %v", err)
		return
	}
	fmt.Printf("%s", data)
}
Пример #10
0
func (S) TestPackages(c *gc.C) {
	cfg := cloudinit.New()
	c.Assert(cfg.Packages(), gc.HasLen, 0)
	cfg.AddPackage("a b c")
	cfg.AddPackage("d!")
	expectedPackages := []string{"a b c", "d!"}
	c.Assert(cfg.Packages(), gc.DeepEquals, expectedPackages)
	cfg.AddPackageFromTargetRelease("package", "series")
	expectedPackages = append(expectedPackages, "--target-release 'series' 'package'")
	c.Assert(cfg.Packages(), gc.DeepEquals, expectedPackages)
}
Пример #11
0
// ComposeUserData fills out the provided cloudinit configuration structure
// so it is suitable for initialising a machine with the given configuration,
// and then renders it and returns it as a binary (gzipped) blob of user data.
//
// If the provided cloudcfg is nil, a new one will be created internally.
func ComposeUserData(mcfg *cloudinit.MachineConfig, cloudcfg *coreCloudinit.Config) ([]byte, error) {
	if cloudcfg == nil {
		cloudcfg = coreCloudinit.New()
	}
	if err := configureCloudinit(mcfg, cloudcfg); err != nil {
		return nil, err
	}
	data, err := cloudcfg.Render()
	logger.Tracef("Generated cloud init:\n%s", string(data))
	if err != nil {
		return nil, err
	}
	return utils.Gzip(data), nil
}
Пример #12
0
func (s *configureSuite) TestAptUpdate(c *gc.C) {
	// apt-get update is run if either AptUpdate is set,
	// or apt sources are defined.
	aptGetUpdatePattern := aptgetRegexp + "update(.|\n)*"
	cfg := cloudinit.New()
	c.Assert(cfg.AptUpdate(), gc.Equals, false)
	c.Assert(cfg.AptSources(), gc.HasLen, 0)
	assertScriptMatches(c, cfg, aptGetUpdatePattern, false)
	cfg.SetAptUpdate(true)
	assertScriptMatches(c, cfg, aptGetUpdatePattern, true)
	cfg.SetAptUpdate(false)
	cfg.AddAptSource("source", "key", nil)
	assertScriptMatches(c, cfg, aptGetUpdatePattern, true)
}
Пример #13
0
func (s *cloudinitSuite) TestAptProxyWritten(c *gc.C) {
	environConfig := minimalConfig(c)
	environConfig, err := environConfig.Apply(map[string]interface{}{
		"apt-http-proxy": "http://[email protected]",
	})
	c.Assert(err, gc.IsNil)
	machineCfg := s.createMachineConfig(c, environConfig)
	cloudcfg := coreCloudinit.New()
	err = cloudinit.Configure(machineCfg, cloudcfg)
	c.Assert(err, gc.IsNil)

	cmds := cloudcfg.BootCmds()
	expected := "[ -f /etc/apt/apt.conf.d/42-juju-proxy-settings ] || (printf '%s\\n' 'Acquire::http::Proxy \"http://[email protected]\";' > /etc/apt/apt.conf.d/42-juju-proxy-settings)"
	c.Assert(cmds, jc.DeepEquals, []interface{}{expected})
}
Пример #14
0
func cloudInitUserData(machineConfig *cloudinit.MachineConfig) ([]byte, error) {
	cloudConfig := coreCloudinit.New()
	err := cloudinit.Configure(machineConfig, cloudConfig)
	if err != nil {
		return nil, err
	}

	// Run ifconfig to get the addresses of the internal container at least
	// logged in the host.
	cloudConfig.AddRunCmd("ifconfig")

	data, err := cloudConfig.Render()
	if err != nil {
		return nil, err
	}
	return data, nil
}
Пример #15
0
// TestCloudInitVerify checks that required fields are appropriately
// checked for by NewCloudInit.
func (*cloudinitSuite) TestCloudInitVerify(c *gc.C) {
	cfg := &cloudinit.MachineConfig{
		Bootstrap:        true,
		StateServingInfo: stateServingInfo,
		MachineId:        "99",
		Tools:            newSimpleTools("9.9.9-linux-arble"),
		AuthorizedKeys:   "sshkey1",
		AgentEnvironment: map[string]string{agent.ProviderType: "dummy"},
		StateInfo: &state.Info{
			Addrs:    []string{"host:98765"},
			CACert:   testing.CACert,
			Password: "******",
		},
		APIInfo: &api.Info{
			Addrs:  []string{"host:9999"},
			CACert: testing.CACert,
		},
		Config:                  minimalConfig(c),
		DataDir:                 environs.DataDir,
		LogDir:                  agent.DefaultLogDir,
		Jobs:                    normalMachineJobs,
		CloudInitOutputLog:      environs.CloudInitOutputLog,
		InstanceId:              "i-bootstrap",
		MachineNonce:            "FAKE_NONCE",
		SystemPrivateSSHKey:     "private rsa key",
		MachineAgentServiceName: "jujud-machine-99",
	}
	// check that the base configuration does not give an error
	ci := coreCloudinit.New()

	for i, test := range verifyTests {
		// check that the base configuration does not give an error
		// and that a previous test hasn't mutated it accidentially.
		err := cloudinit.Configure(cfg, ci)
		c.Assert(err, gc.IsNil)

		c.Logf("test %d. %s", i, test.err)

		cfg1 := *cfg
		test.mutate(&cfg1)

		err = cloudinit.Configure(&cfg1, ci)
		c.Assert(err, gc.ErrorMatches, "invalid machine configuration: "+test.err)

	}
}
Пример #16
0
func (*cloudinitSuite) TestCloudInitConfigureUsesGivenConfig(c *gc.C) {
	// Create a simple cloudinit config with a 'runcmd' statement.
	cloudcfg := coreCloudinit.New()
	script := "test script"
	cloudcfg.AddRunCmd(script)
	cloudinitTests[0].cfg.Config = minimalConfig(c)
	err := cloudinit.Configure(&cloudinitTests[0].cfg, cloudcfg)
	c.Assert(err, gc.IsNil)
	data, err := cloudcfg.Render()
	c.Assert(err, gc.IsNil)

	ciContent := make(map[interface{}]interface{})
	err = goyaml.Unmarshal(data, &ciContent)
	c.Assert(err, gc.IsNil)
	// The 'runcmd' statement is at the beginning of the list
	// of 'runcmd' statements.
	runCmd := ciContent["runcmd"].([]interface{})
	c.Check(runCmd[0], gc.Equals, script)
}
Пример #17
0
// ProvisioningScript generates a bash script that can be
// executed on a remote host to carry out the cloud-init
// configuration.
func ProvisioningScript(mcfg *cloudinit.MachineConfig) (string, error) {
	cloudcfg := coreCloudinit.New()
	if err := cloudinit.ConfigureJuju(mcfg, cloudcfg); err != nil {
		return "", err
	}
	// Explicitly disabling apt_upgrade so as not to trample
	// the target machine's existing configuration.
	cloudcfg.SetAptUpgrade(false)
	configScript, err := sshinit.ConfigureScript(cloudcfg)
	if err != nil {
		return "", err
	}

	var buf bytes.Buffer
	// Always remove the cloud-init-output.log file first, if it exists.
	fmt.Fprintf(&buf, "rm -f %s\n", utils.ShQuote(mcfg.CloudInitOutputLog))
	// If something goes wrong, dump cloud-init-output.log to stderr.
	buf.WriteString(shell.DumpFileOnErrorScript(mcfg.CloudInitOutputLog))
	buf.WriteString(configScript)
	return buf.String(), nil
}
Пример #18
0
func (s *configureSuite) getCloudConfig(c *gc.C, stateServer bool, vers version.Binary) *cloudinit.Config {
	var mcfg *envcloudinit.MachineConfig
	if stateServer {
		mcfg = environs.NewBootstrapMachineConfig("private-key")
		mcfg.InstanceId = "instance-id"
		mcfg.Jobs = []params.MachineJob{params.JobManageEnviron, params.JobHostUnits}
	} else {
		mcfg = environs.NewMachineConfig("0", "ya", nil, nil, nil, nil)
		mcfg.Jobs = []params.MachineJob{params.JobHostUnits}
	}
	mcfg.Tools = &tools.Tools{
		Version: vers,
		URL:     "file:///var/lib/juju/storage/" + envtools.StorageName(vers),
	}
	environConfig := testConfig(c, stateServer, vers)
	err := environs.FinishMachineConfig(mcfg, environConfig, constraints.Value{})
	c.Assert(err, gc.IsNil)
	cloudcfg := cloudinit.New()
	err = envcloudinit.Configure(mcfg, cloudcfg)
	c.Assert(err, gc.IsNil)
	return cloudcfg
}
Пример #19
0
// TestCloudInit checks that the output from the various tests
// in cloudinitTests is well formed.
func (*cloudinitSuite) TestCloudInit(c *gc.C) {
	for i, test := range cloudinitTests {
		c.Logf("test %d", i)
		if test.setEnvConfig {
			test.cfg.Config = minimalConfig(c)
		}
		ci := coreCloudinit.New()
		err := cloudinit.Configure(&test.cfg, ci)
		c.Assert(err, gc.IsNil)
		c.Check(ci, gc.NotNil)
		// render the cloudinit config to bytes, and then
		// back to a map so we can introspect it without
		// worrying about internal details of the cloudinit
		// package.
		data, err := ci.Render()
		c.Assert(err, gc.IsNil)

		x := make(map[interface{}]interface{})
		err = goyaml.Unmarshal(data, &x)
		c.Assert(err, gc.IsNil)

		c.Check(x["apt_upgrade"], gc.Equals, true)
		c.Check(x["apt_update"], gc.Equals, true)

		scripts := getScripts(x)
		assertScriptMatch(c, scripts, test.expectScripts, !test.inexactMatch)
		if test.cfg.Config != nil {
			checkEnvConfig(c, test.cfg.Config, x, scripts)
		}
		checkPackage(c, x, "git", true)
		tag := names.MachineTag(test.cfg.MachineId)
		acfg := getAgentConfig(c, tag, scripts)
		c.Assert(acfg, jc.Contains, "AGENT_SERVICE_NAME: jujud-"+tag)
		source := "deb http://ubuntu-cloud.archive.canonical.com/ubuntu precise-updates/cloud-tools main"
		needCloudArchive := test.cfg.Tools.Version.Series == "precise"
		checkAptSource(c, x, source, cloudinit.CanonicalCloudArchiveSigningKey, needCloudArchive)
	}
}
Пример #20
0
// templateUserData returns a minimal user data necessary for the template.
// This should have the authorized keys, base packages, the cloud archive if
// necessary,  initial apt proxy config, and it should do the apt-get
// update/upgrade initially.
func templateUserData(
	series string,
	authorizedKeys string,
	aptProxy osenv.ProxySettings,
) ([]byte, error) {
	config := coreCloudinit.New()
	config.AddScripts(
		"set -xe", // ensure we run all the scripts or abort.
	)
	config.AddSSHAuthorizedKeys(authorizedKeys)
	cloudinit.MaybeAddCloudArchiveCloudTools(config, series)
	cloudinit.AddAptCommands(aptProxy, config)
	config.AddScripts(
		fmt.Sprintf(
			"printf '%%s\n' %s > %s",
			utils.ShQuote(templateShutdownUpstartScript),
			templateShutdownUpstartFilename,
		))
	data, err := config.Render()
	if err != nil {
		return nil, err
	}
	return data, nil
}
Пример #21
0
func (*CloudInitSuite) testUserData(c *gc.C, bootstrap bool) {
	testJujuHome := c.MkDir()
	defer osenv.SetJujuHome(osenv.SetJujuHome(testJujuHome))
	tools := &tools.Tools{
		URL:     "http://foo.com/tools/releases/juju1.2.3-linux-amd64.tgz",
		Version: version.MustParseBinary("1.2.3-linux-amd64"),
	}
	envConfig, err := config.New(config.NoDefaults, dummySampleConfig())
	c.Assert(err, gc.IsNil)

	allJobs := []params.MachineJob{
		params.JobManageEnviron,
		params.JobHostUnits,
	}
	cfg := &cloudinit.MachineConfig{
		MachineId:    "10",
		MachineNonce: "5432",
		Tools:        tools,
		StateInfo: &state.Info{
			Addrs:    []string{"127.0.0.1:1234"},
			Password: "******",
			CACert:   "CA CERT\n" + testing.CACert,
			Tag:      "machine-10",
		},
		APIInfo: &api.Info{
			Addrs:    []string{"127.0.0.1:1234"},
			Password: "******",
			CACert:   "CA CERT\n" + testing.CACert,
			Tag:      "machine-10",
		},
		DataDir:                 environs.DataDir,
		LogDir:                  agent.DefaultLogDir,
		Jobs:                    allJobs,
		CloudInitOutputLog:      environs.CloudInitOutputLog,
		Config:                  envConfig,
		AgentEnvironment:        map[string]string{agent.ProviderType: "dummy"},
		AuthorizedKeys:          "wheredidileavemykeys",
		MachineAgentServiceName: "jujud-machine-10",
	}
	if bootstrap {
		cfg.Bootstrap = true
		cfg.StateServingInfo = &params.StateServingInfo{
			StatePort:  envConfig.StatePort(),
			APIPort:    envConfig.APIPort(),
			Cert:       testing.ServerCert,
			PrivateKey: testing.ServerKey,
		}
	}
	script1 := "script1"
	script2 := "script2"
	cloudcfg := coreCloudinit.New()
	cloudcfg.AddRunCmd(script1)
	cloudcfg.AddRunCmd(script2)
	result, err := environs.ComposeUserData(cfg, cloudcfg)
	c.Assert(err, gc.IsNil)

	unzipped, err := utils.Gunzip(result)
	c.Assert(err, gc.IsNil)

	config := make(map[interface{}]interface{})
	err = goyaml.Unmarshal(unzipped, &config)
	c.Assert(err, gc.IsNil)

	// The scripts given to userData where added as the first
	// commands to be run.
	runCmd := config["runcmd"].([]interface{})
	c.Check(runCmd[0], gc.Equals, script1)
	c.Check(runCmd[1], gc.Equals, script2)

	if bootstrap {
		// The cloudinit config should have nothing but the basics:
		// SSH authorized keys, the additional runcmds, and log output.
		//
		// Note: the additional runcmds *do* belong here, at least
		// for MAAS. MAAS needs to configure and then bounce the
		// network interfaces, which would sever the SSH connection
		// in the synchronous bootstrap phase.
		c.Check(config, gc.DeepEquals, map[interface{}]interface{}{
			"output": map[interface{}]interface{}{
				"all": "| tee -a /var/log/cloud-init-output.log",
			},
			"runcmd": []interface{}{
				"script1", "script2",
				"set -xe",
				"install -D -m 644 /dev/null '/var/lib/juju/nonce.txt'",
				"printf '%s\\n' '5432' > '/var/lib/juju/nonce.txt'",
			},
			"ssh_authorized_keys": []interface{}{"wheredidileavemykeys"},
		})
	} else {
		// Just check that the cloudinit config looks good,
		// and that there are more runcmds than the additional
		// ones we passed into ComposeUserData.
		c.Check(config["apt_upgrade"], gc.Equals, true)
		c.Check(len(runCmd) > 2, jc.IsTrue)
	}
}
Пример #22
0
		interrupted,
		client,
		checkNonceCommand,
		inst,
		machineConfig.Config.BootstrapSSHOpts(),
	)
	if err != nil {
		return err
	}
	// Bootstrap is synchronous, and will spawn a subprocess
	// to complete the procedure. If the user hits Ctrl-C,
	// SIGINT is sent to the foreground process attached to
	// the terminal, which will be the ssh subprocess at this
	// point. For that reason, we do not call StopInterruptNotify
	// until this function completes.
	cloudcfg := coreCloudinit.New()
	if err := cloudinit.ConfigureJuju(machineConfig, cloudcfg); err != nil {
		return err
	}
	configScript, err := sshinit.ConfigureScript(cloudcfg)
	if err != nil {
		return err
	}
	script := shell.DumpFileOnErrorScript(machineConfig.CloudInitOutputLog) + configScript
	return sshinit.RunConfigureScript(script, sshinit.ConfigureParams{
		Host:           "ubuntu@" + addr,
		Client:         client,
		Config:         cloudcfg,
		ProgressWriter: ctx.GetStderr(),
	})
}