func (w *MachineEnvironmentWorker) writeEnvironmentFile() error {
	// Writing the environment file is handled by executing the script for two
	// primary reasons:
	//
	// 1: In order to have the local provider specify the environment settings
	// for the machine agent running on the host, this worker needs to run,
	// but it shouldn't be touching any files on the disk.  If however there is
	// an ubuntu user, it will. This shouldn't be a problem.
	//
	// 2: On cloud-instance ubuntu images, the ubuntu user is uid 1000, but in
	// the situation where the ubuntu user has been created as a part of the
	// manual provisioning process, the user will exist, and will not have the
	// same uid/gid as the default cloud image.
	//
	// It is easier to shell out to check both these things, and is also the
	// same way that the file is written in the cloud-init process, so
	// consistency FTW.
	filePath := path.Join(ProxyDirectory, ProxyFile)
	result, err := exec.RunCommands(exec.RunParams{
		Commands: fmt.Sprintf(
			`[ -e %s ] && (printf '%%s\n' %s > %s && chown ubuntu:ubuntu %s)`,
			ProxyDirectory,
			utils.ShQuote(w.proxy.AsScriptEnvironment()),
			filePath, filePath),
		WorkingDir: ProxyDirectory,
	})
	if err != nil {
		return err
	}
	if result.Code != 0 {
		logger.Errorf("failed writing new proxy values: \n%s\n%s", result.Stdout, result.Stderr)
	}
	return nil
}
Example #2
0
// RunCommands executes the commands in an environment which allows it to to
// call back into the hook context to execute jujuc tools.
func (ctx *HookContext) RunCommands(commands, charmDir, toolsDir, socketPath string) (*utilexec.ExecResponse, error) {
	env := ctx.hookVars(charmDir, toolsDir, socketPath)
	result, err := utilexec.RunCommands(
		utilexec.RunParams{
			Commands:    commands,
			WorkingDir:  charmDir,
			Environment: env})
	return result, ctx.finalizeContext("run commands", err)
}
Example #3
0
func (*execSuite) TestExecUnknownCommand(c *gc.C) {
	result, err := exec.RunCommands(
		exec.RunParams{
			Commands: "unknown-command",
		},
	)
	c.Assert(err, gc.IsNil)
	c.Assert(result.Stdout, gc.HasLen, 0)
	c.Assert(string(result.Stderr), jc.Contains, "unknown-command: command not found")
	// 127 is a special bash return code meaning command not found.
	c.Assert(result.Code, gc.Equals, 127)
}
Example #4
0
func (*execSuite) TestRunCommands(c *gc.C) {
	newDir := c.MkDir()

	for i, test := range []struct {
		message     string
		commands    string
		workingDir  string
		environment []string
		stdout      string
		stderr      string
		code        int
	}{
		{
			message:  "test stdout capture",
			commands: "echo testing stdout",
			stdout:   "testing stdout\n",
		}, {
			message:  "test stderr capture",
			commands: "echo testing stderr >&2",
			stderr:   "testing stderr\n",
		}, {
			message:  "test return code",
			commands: "exit 42",
			code:     42,
		}, {
			message:    "test working dir",
			commands:   "pwd",
			workingDir: newDir,
			stdout:     newDir + "\n",
		}, {
			message:     "test environment",
			commands:    "echo $OMG_IT_WORKS",
			environment: []string{"OMG_IT_WORKS=like magic"},
			stdout:      "like magic\n",
		},
	} {
		c.Logf("%v: %s", i, test.message)

		result, err := exec.RunCommands(
			exec.RunParams{
				Commands:    test.commands,
				WorkingDir:  test.workingDir,
				Environment: test.environment,
			})
		c.Assert(err, gc.IsNil)
		c.Assert(string(result.Stdout), gc.Equals, test.stdout)
		c.Assert(string(result.Stderr), gc.Equals, test.stderr)
		c.Assert(result.Code, gc.Equals, test.code)
	}
}
Example #5
0
// Previously the lock directory was created when the uniter started. This
// allows serialization of all of the hook execution across units running on a
// single machine.  This lock directory is now also used but the juju-run
// command on the host machine.  juju-run also gets a lock on the hook
// execution fslock prior to execution.  However, the lock directory was owned
// by root, and the juju-run process was being executed by the ubuntu user, so
// we need to change the ownership of the lock directory to ubuntu:ubuntu.
// Also we need to make sure that this directory exists on machines with no
// units.
func ensureLockDirExistsAndUbuntuWritable(context Context) error {
	lockDir := path.Join(context.AgentConfig().DataDir(), "locks")
	// We only try to change ownership if there is an ubuntu user
	// defined, and we determine this by the existance of the home dir.
	command := fmt.Sprintf(""+
		"mkdir -p %s\n"+
		"[ -e %s ] && chown ubuntu:ubuntu %s\n",
		lockDir, ubuntuHome, lockDir)
	logger.Tracef("command: %s", command)
	result, err := exec.RunCommands(exec.RunParams{
		Commands: command,
	})
	if err != nil {
		return err
	}
	logger.Tracef("stdout: %s", result.Stdout)
	return nil
}
Example #6
0
// As of the middle of the 1.17 cycle, the proxy settings are written out to
// /home/ubuntu/.juju-proxy both by cloud-init and the machine environ worker.
// An older version of juju that has been upgraded will get the proxy settings
// written out to the .juju-proxy file, but the .profile for the ubuntu user
// wouldn't have been updated to source this file.
//
// This upgrade step is to add the line to source the file if it is missing
// from the file.
func ensureUbuntuDotProfileSourcesProxyFile(context Context) error {
	// We look to see if the proxy line is there already as the manual
	// provider may have had it aleady. The ubuntu user may not exist
	// (local provider only).
	command := fmt.Sprintf(""+
		`([ ! -e %s/.profile ] || grep -q '.juju-proxy' %s/.profile) || `+
		`printf '\n# Added by juju\n[ -f "$HOME/.juju-proxy" ] && . "$HOME/.juju-proxy"\n' >> %s/.profile`,
		ubuntuHome, ubuntuHome, ubuntuHome)
	logger.Tracef("command: %s", command)
	result, err := exec.RunCommands(exec.RunParams{
		Commands: command,
	})
	if err != nil {
		return err
	}
	logger.Tracef("stdout: %s", result.Stdout)
	return nil
}
Example #7
0
File: run.go Project: jameinel/core
func (c *RunCommand) executeNoContext() (*exec.ExecResponse, error) {
	// Acquire the uniter hook execution lock to make sure we don't
	// stomp on each other.
	lock, err := getLock()
	if err != nil {
		return nil, err
	}
	err = lock.Lock("juju-run")
	if err != nil {
		return nil, err
	}
	defer lock.Unlock()

	runCmd := `[ -f "/home/ubuntu/.juju-proxy" ] && . "/home/ubuntu/.juju-proxy"` + "\n" + c.commands

	return exec.RunCommands(
		exec.RunParams{
			Commands: runCmd,
		})
}