Merge lp:~thumper/juju-core/run-cmd-refactor into lp:~go-bot/juju-core/trunk

Proposed by Tim Penhey
Status: Merged
Approved by: Tim Penhey
Approved revision: no longer in the source branch.
Merged at revision: 2202
Proposed branch: lp:~thumper/juju-core/run-cmd-refactor
Merge into: lp:~go-bot/juju-core/trunk
Diff against target: 683 lines (+235/-91)
19 files modified
cmd/juju/run_test.go (+3/-2)
cmd/jujud/main.go (+2/-1)
cmd/jujud/run.go (+2/-1)
cmd/jujud/run_test.go (+3/-2)
cmd/remote.go (+0/-12)
state/api/params/internal.go (+2/-2)
state/apiserver/client/run.go (+3/-3)
state/apiserver/client/run_test.go (+15/-15)
utils/exec/exec.go (+73/-0)
utils/exec/exec_test.go (+82/-0)
utils/exec/package_test.go (+24/-0)
utils/ssh/run.go (+2/-2)
worker/uniter/context.go (+7/-37)
worker/uniter/jujuc/server.go (+2/-1)
worker/uniter/jujuc/server_test.go (+3/-2)
worker/uniter/runlistener.go (+4/-4)
worker/uniter/runlistener_test.go (+4/-4)
worker/uniter/uniter.go (+2/-1)
worker/uniter/uniter_test.go (+2/-2)
To merge this branch: bzr merge lp:~thumper/juju-core/run-cmd-refactor
Reviewer Review Type Date Requested Status
Juju Engineering Pending
Review via email: mp+201680@code.launchpad.net

Commit message

Refactor RunCommands function into a util package

As part of this work, the return structure has been
moved into the utils/exec package along with the
RunCommands function.

I didn't really like the return structure being in
the cmd package, but I didn't see a better place at
the time of making it.

The biggest part of this restructing is the renaming
of the call sites. A benefit is reduced package
dependencies by the users.

https://codereview.appspot.com/52300043/

Description of the change

Refactor RunCommands function into a util package

As part of this work, the return structure has been
moved into the utils/exec package along with the
RunCommands function.

I didn't really like the return structure being in
the cmd package, but I didn't see a better place at
the time of making it.

The biggest part of this restructing is the renaming
of the call sites. A benefit is reduced package
dependencies by the users.

https://codereview.appspot.com/52300043/

To post a comment you must log in.
Revision history for this message
Tim Penhey (thumper) wrote :

Reviewers: mp+201680_code.launchpad.net,

Message:
Please take a look.

Description:
Refactor RunCommands function into a util package

As part of this work, the return structure has been
moved into the utils/exec package along with the
RunCommands function.

I didn't really like the return structure being in
the cmd package, but I didn't see a better place at
the time of making it.

The biggest part of this restructing is the renaming
of the call sites. A benefit is reduced package
dependencies by the users.

https://code.launchpad.net/~thumper/juju-core/run-cmd-refactor/+merge/201680

(do not edit description out of merge proposal)

Please review this at https://codereview.appspot.com/52300043/

Affected files (+237, -91 lines):
   A [revision details]
   M cmd/juju/run_test.go
   M cmd/jujud/main.go
   M cmd/jujud/run.go
   M cmd/jujud/run_test.go
   D cmd/remote.go
   M state/api/params/internal.go
   M state/apiserver/client/run.go
   M state/apiserver/client/run_test.go
   A utils/exec/exec.go
   A utils/exec/exec_test.go
   A utils/exec/package_test.go
   M utils/ssh/run.go
   M worker/uniter/context.go
   M worker/uniter/jujuc/server.go
   M worker/uniter/jujuc/server_test.go
   M worker/uniter/runlistener.go
   M worker/uniter/runlistener_test.go
   M worker/uniter/uniter.go
   M worker/uniter/uniter_test.go

Revision history for this message
Ian Booth (wallyworld) wrote :
Revision history for this message
Go Bot (go-bot) wrote :
Download full text (8.5 KiB)

The attempt to merge lp:~thumper/juju-core/run-cmd-refactor into lp:juju-core failed. Below is the output from the failed tests.

ok launchpad.net/juju-core/agent 1.265s
ok launchpad.net/juju-core/agent/tools 0.249s
ok launchpad.net/juju-core/bzr 7.326s
ok launchpad.net/juju-core/cert 3.417s
ok launchpad.net/juju-core/charm 0.566s
? launchpad.net/juju-core/charm/hooks [no test files]
ok launchpad.net/juju-core/cloudinit 0.037s
ok launchpad.net/juju-core/cloudinit/sshinit 1.049s
ok launchpad.net/juju-core/cmd 0.253s
ok launchpad.net/juju-core/cmd/charm-admin 0.807s
? launchpad.net/juju-core/cmd/charmd [no test files]
? launchpad.net/juju-core/cmd/charmload [no test files]
ok launchpad.net/juju-core/cmd/juju 190.068s
ok launchpad.net/juju-core/cmd/jujud 60.586s
ok launchpad.net/juju-core/cmd/plugins/juju-metadata 3.131s
? launchpad.net/juju-core/cmd/plugins/juju-restore [no test files]
ok launchpad.net/juju-core/constraints 0.028s
ok launchpad.net/juju-core/container 0.040s
ok launchpad.net/juju-core/container/factory 0.074s
ok launchpad.net/juju-core/container/kvm 0.289s
ok launchpad.net/juju-core/container/kvm/mock 0.048s
? launchpad.net/juju-core/container/kvm/testing [no test files]
ok launchpad.net/juju-core/container/lxc 0.403s
? launchpad.net/juju-core/container/lxc/mock [no test files]
? launchpad.net/juju-core/container/lxc/testing [no test files]
? launchpad.net/juju-core/container/testing [no test files]
ok launchpad.net/juju-core/downloader 5.313s
ok launchpad.net/juju-core/environs 3.072s
ok launchpad.net/juju-core/environs/bootstrap 4.542s
ok launchpad.net/juju-core/environs/cloudinit 0.575s
ok launchpad.net/juju-core/environs/config 1.072s
ok launchpad.net/juju-core/environs/configstore 0.061s
ok launchpad.net/juju-core/environs/filestorage 0.033s
ok launchpad.net/juju-core/environs/httpstorage 1.070s
ok launchpad.net/juju-core/environs/imagemetadata 0.531s
? launchpad.net/juju-core/environs/imagemetadata/testing [no test files]
ok launchpad.net/juju-core/environs/instances 0.055s
ok launchpad.net/juju-core/environs/jujutest 0.210s
ok launchpad.net/juju-core/environs/manual 12.561s
ok launchpad.net/juju-core/environs/simplestreams 0.337s
? launchpad.net/juju-core/environs/simplestreams/testing [no test files]
ok launchpad.net/juju-core/environs/sshstorage 1.257s
ok launchpad.net/juju-core/environs/storage 1.163s
ok launchpad.net/juju-core/environs/sync 32.002s
ok launchpad.net/juju-core/environs/testing 0.203s
ok launchpad.net/juju-core/environs/tools 6.948s
? launchpad.net/juju-core/environs/tools/testing [no test files]
ok launchpad.net/juju-core/errors 0.016s
ok launchpad.net/juju-core/instance 0.022s
? launchpad.net/juju-core/instance/testing [no test files]
ok launchpad.net/juju-core/juju 16.194s
ok launchpad.net/juju-core/juju/osenv 0.017s
? launchpad.net/juju-core/juju/testing [no test files]
ok launchpad.net/juju-core/log 0.016s
ok launchpad.net/juju-core/log/syslog 0.022s
ok launchpad.net/juju-core/names 0.026s
? launchpad.net/juju-core/provider [no test files]
? launchpad.net/juju-core/provi...

Read more...

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'cmd/juju/run_test.go'
--- cmd/juju/run_test.go 2014-01-12 20:38:39 +0000
+++ cmd/juju/run_test.go 2014-01-14 21:31:32 +0000
@@ -13,6 +13,7 @@
13 "launchpad.net/juju-core/state/api/params"13 "launchpad.net/juju-core/state/api/params"
14 "launchpad.net/juju-core/testing"14 "launchpad.net/juju-core/testing"
15 jc "launchpad.net/juju-core/testing/checkers"15 jc "launchpad.net/juju-core/testing/checkers"
16 "launchpad.net/juju-core/utils/exec"
16)17)
1718
18type RunSuite struct {19type RunSuite struct {
@@ -191,7 +192,7 @@
191 message: "stdout and stderr are base64 encoded if not valid utf8",192 message: "stdout and stderr are base64 encoded if not valid utf8",
192 results: []params.RunResult{193 results: []params.RunResult{
193 params.RunResult{194 params.RunResult{
194 RemoteResponse: cmd.RemoteResponse{195 ExecResponse: exec.ExecResponse{
195 Stdout: []byte{0xff},196 Stdout: []byte{0xff},
196 Stderr: []byte{0xfe},197 Stderr: []byte{0xfe},
197 },198 },
@@ -386,7 +387,7 @@
386387
387func makeRunResult(mock mockResponse) params.RunResult {388func makeRunResult(mock mockResponse) params.RunResult {
388 return params.RunResult{389 return params.RunResult{
389 RemoteResponse: cmd.RemoteResponse{390 ExecResponse: exec.ExecResponse{
390 Stdout: []byte(mock.stdout),391 Stdout: []byte(mock.stdout),
391 Stderr: []byte(mock.stderr),392 Stderr: []byte(mock.stderr),
392 Code: mock.code,393 Code: mock.code,
393394
=== modified file 'cmd/jujud/main.go'
--- cmd/jujud/main.go 2013-12-12 22:54:02 +0000
+++ cmd/jujud/main.go 2014-01-14 21:31:32 +0000
@@ -10,6 +10,7 @@
10 "path/filepath"10 "path/filepath"
1111
12 "launchpad.net/juju-core/cmd"12 "launchpad.net/juju-core/cmd"
13 "launchpad.net/juju-core/utils/exec"
13 "launchpad.net/juju-core/worker/uniter/jujuc"14 "launchpad.net/juju-core/worker/uniter/jujuc"
1415
15 // Import the providers.16 // Import the providers.
@@ -76,7 +77,7 @@
76 return77 return
77 }78 }
78 defer client.Close()79 defer client.Close()
79 var resp cmd.RemoteResponse80 var resp exec.ExecResponse
80 err = client.Call("Jujuc.Main", req, &resp)81 err = client.Call("Jujuc.Main", req, &resp)
81 if err != nil {82 if err != nil {
82 return83 return
8384
=== modified file 'cmd/jujud/run.go'
--- cmd/jujud/run.go 2013-12-13 04:40:41 +0000
+++ cmd/jujud/run.go 2014-01-14 21:31:32 +0000
@@ -13,6 +13,7 @@
1313
14 "launchpad.net/juju-core/cmd"14 "launchpad.net/juju-core/cmd"
15 "launchpad.net/juju-core/names"15 "launchpad.net/juju-core/names"
16 "launchpad.net/juju-core/utils/exec"
16 "launchpad.net/juju-core/worker/uniter"17 "launchpad.net/juju-core/worker/uniter"
17)18)
1819
@@ -96,7 +97,7 @@
96 }97 }
97 defer client.Close()98 defer client.Close()
9899
99 var result cmd.RemoteResponse100 var result exec.ExecResponse
100 err = client.Call(uniter.JujuRunEndpoint, c.commands, &result)101 err = client.Call(uniter.JujuRunEndpoint, c.commands, &result)
101 if err != nil {102 if err != nil {
102 return err103 return err
103104
=== modified file 'cmd/jujud/run_test.go'
--- cmd/jujud/run_test.go 2013-12-13 03:37:01 +0000
+++ cmd/jujud/run_test.go 2014-01-14 21:31:32 +0000
@@ -15,6 +15,7 @@
15 "launchpad.net/juju-core/testing"15 "launchpad.net/juju-core/testing"
16 jc "launchpad.net/juju-core/testing/checkers"16 jc "launchpad.net/juju-core/testing/checkers"
17 "launchpad.net/juju-core/testing/testbase"17 "launchpad.net/juju-core/testing/testbase"
18 "launchpad.net/juju-core/utils/exec"
18 "launchpad.net/juju-core/worker/uniter"19 "launchpad.net/juju-core/worker/uniter"
19)20)
2021
@@ -125,9 +126,9 @@
125126
126var _ uniter.CommandRunner = (*mockRunner)(nil)127var _ uniter.CommandRunner = (*mockRunner)(nil)
127128
128func (r *mockRunner) RunCommands(commands string) (results *cmd.RemoteResponse, err error) {129func (r *mockRunner) RunCommands(commands string) (results *exec.ExecResponse, err error) {
129 r.c.Log("mock runner: " + commands)130 r.c.Log("mock runner: " + commands)
130 return &cmd.RemoteResponse{131 return &exec.ExecResponse{
131 Code: 42,132 Code: 42,
132 Stdout: []byte(commands + " stdout"),133 Stdout: []byte(commands + " stdout"),
133 Stderr: []byte(commands + " stderr"),134 Stderr: []byte(commands + " stderr"),
134135
=== removed file 'cmd/remote.go'
--- cmd/remote.go 2013-12-12 04:31:01 +0000
+++ cmd/remote.go 1970-01-01 00:00:00 +0000
@@ -1,12 +0,0 @@
1// Copyright 2013 Canonical Ltd.
2// Licensed under the AGPLv3, see LICENCE file for details.
3
4package cmd
5
6// RemoteResponse contains the return code and output generated by a remote
7// request.
8type RemoteResponse struct {
9 Code int
10 Stdout []byte
11 Stderr []byte
12}
130
=== modified file 'state/api/params/internal.go'
--- state/api/params/internal.go 2014-01-12 20:07:40 +0000
+++ state/api/params/internal.go 2014-01-14 21:31:32 +0000
@@ -6,10 +6,10 @@
6import (6import (
7 "time"7 "time"
88
9 "launchpad.net/juju-core/cmd"
10 "launchpad.net/juju-core/constraints"9 "launchpad.net/juju-core/constraints"
11 "launchpad.net/juju-core/instance"10 "launchpad.net/juju-core/instance"
12 "launchpad.net/juju-core/tools"11 "launchpad.net/juju-core/tools"
12 "launchpad.net/juju-core/utils/exec"
13 "launchpad.net/juju-core/version"13 "launchpad.net/juju-core/version"
14)14)
1515
@@ -527,7 +527,7 @@
527// RunResult contains the result from an individual run call on a machine.527// RunResult contains the result from an individual run call on a machine.
528// UnitId is populated if the command was run inside the unit context.528// UnitId is populated if the command was run inside the unit context.
529type RunResult struct {529type RunResult struct {
530 cmd.RemoteResponse530 exec.ExecResponse
531 MachineId string531 MachineId string
532 UnitId string532 UnitId string
533 Error string533 Error string
534534
=== modified file 'state/apiserver/client/run.go'
--- state/apiserver/client/run.go 2014-01-12 20:28:43 +0000
+++ state/apiserver/client/run.go 2014-01-14 21:31:32 +0000
@@ -150,9 +150,9 @@
150 response, err := ssh.ExecuteCommandOnMachine(param.ExecParams)150 response, err := ssh.ExecuteCommandOnMachine(param.ExecParams)
151 logger.Debugf("reponse from %s: %v (err:%v)", param.MachineId, response, err)151 logger.Debugf("reponse from %s: %v (err:%v)", param.MachineId, response, err)
152 execResponse := params.RunResult{152 execResponse := params.RunResult{
153 RemoteResponse: response,153 ExecResponse: response,
154 MachineId: param.MachineId,154 MachineId: param.MachineId,
155 UnitId: param.UnitId,155 UnitId: param.UnitId,
156 }156 }
157 if err != nil {157 if err != nil {
158 execResponse.Error = fmt.Sprint(err)158 execResponse.Error = fmt.Sprint(err)
159159
=== modified file 'state/apiserver/client/run_test.go'
--- state/apiserver/client/run_test.go 2014-01-12 20:28:43 +0000
+++ state/apiserver/client/run_test.go 2014-01-14 21:31:32 +0000
@@ -12,13 +12,13 @@
1212
13 gc "launchpad.net/gocheck"13 gc "launchpad.net/gocheck"
1414
15 "launchpad.net/juju-core/cmd"
16 "launchpad.net/juju-core/instance"15 "launchpad.net/juju-core/instance"
17 "launchpad.net/juju-core/state"16 "launchpad.net/juju-core/state"
18 "launchpad.net/juju-core/state/api/params"17 "launchpad.net/juju-core/state/api/params"
19 "launchpad.net/juju-core/state/apiserver/client"18 "launchpad.net/juju-core/state/apiserver/client"
20 "launchpad.net/juju-core/testing"19 "launchpad.net/juju-core/testing"
21 jc "launchpad.net/juju-core/testing/checkers"20 jc "launchpad.net/juju-core/testing/checkers"
21 "launchpad.net/juju-core/utils/exec"
22 "launchpad.net/juju-core/utils/ssh"22 "launchpad.net/juju-core/utils/ssh"
23)23)
2424
@@ -230,8 +230,8 @@
230 for i := 0; i < 3; i++ {230 for i := 0; i < 3; i++ {
231 expectedResults = append(expectedResults,231 expectedResults = append(expectedResults,
232 params.RunResult{232 params.RunResult{
233 RemoteResponse: cmd.RemoteResponse{Stdout: []byte("hostname\n")},233 ExecResponse: exec.ExecResponse{Stdout: []byte("hostname\n")},
234 MachineId: fmt.Sprint(i),234 MachineId: fmt.Sprint(i),
235 })235 })
236 }236 }
237237
@@ -264,18 +264,18 @@
264 c.Assert(results, gc.HasLen, 3)264 c.Assert(results, gc.HasLen, 3)
265 expectedResults := []params.RunResult{265 expectedResults := []params.RunResult{
266 params.RunResult{266 params.RunResult{
267 RemoteResponse: cmd.RemoteResponse{Stdout: []byte("hostname\n")},267 ExecResponse: exec.ExecResponse{Stdout: []byte("hostname\n")},
268 MachineId: "0",268 MachineId: "0",
269 },269 },
270 params.RunResult{270 params.RunResult{
271 RemoteResponse: cmd.RemoteResponse{Stdout: []byte("juju-run magic/0 'hostname'\n")},271 ExecResponse: exec.ExecResponse{Stdout: []byte("juju-run magic/0 'hostname'\n")},
272 MachineId: "1",272 MachineId: "1",
273 UnitId: "magic/0",273 UnitId: "magic/0",
274 },274 },
275 params.RunResult{275 params.RunResult{
276 RemoteResponse: cmd.RemoteResponse{Stdout: []byte("juju-run magic/1 'hostname'\n")},276 ExecResponse: exec.ExecResponse{Stdout: []byte("juju-run magic/1 'hostname'\n")},
277 MachineId: "2",277 MachineId: "2",
278 UnitId: "magic/1",278 UnitId: "magic/1",
279 },279 },
280 }280 }
281281
282282
=== added directory 'utils/exec'
=== added file 'utils/exec/exec.go'
--- utils/exec/exec.go 1970-01-01 00:00:00 +0000
+++ utils/exec/exec.go 2014-01-14 21:31:32 +0000
@@ -0,0 +1,73 @@
1// Copyright 2014 Canonical Ltd.
2// Licensed under the AGPLv3, see LICENCE file for details.
3
4package exec
5
6import (
7 "bytes"
8 "os/exec"
9 "syscall"
10
11 "launchpad.net/loggo"
12)
13
14var logger = loggo.GetLogger("juju.util.exec")
15
16// Parameters for RunCommands. Commands contains one or more commands to be
17// executed using '/bin/bash -s'. If WorkingDir is set, this is passed
18// through to bash. Similarly if the Environment is specified, this is used
19// for executing the command.
20type RunParams struct {
21 Commands string
22 WorkingDir string
23 Environment []string
24}
25
26// ExecResponse contains the return code and output generated by executing a
27// command.
28type ExecResponse struct {
29 Code int
30 Stdout []byte
31 Stderr []byte
32}
33
34// RunCommands executes the Commands specified in the RunParams using
35// '/bin/bash -s', passing the commands through as stdin, and collecting
36// stdout and stderr. If a non-zero return code is returned, this is
37// collected as the code for the response and this does not classify as an
38// error.
39func RunCommands(run RunParams) (*ExecResponse, error) {
40 ps := exec.Command("/bin/bash", "-s")
41 if run.Environment != nil {
42 ps.Env = run.Environment
43 }
44 if run.WorkingDir != "" {
45 ps.Dir = run.WorkingDir
46 }
47 ps.Stdin = bytes.NewBufferString(run.Commands)
48
49 stdout := &bytes.Buffer{}
50 stderr := &bytes.Buffer{}
51
52 ps.Stdout = stdout
53 ps.Stderr = stderr
54
55 err := ps.Start()
56 if err == nil {
57 err = ps.Wait()
58 }
59 result := &ExecResponse{
60 Stdout: stdout.Bytes(),
61 Stderr: stderr.Bytes(),
62 }
63 if ee, ok := err.(*exec.ExitError); ok && err != nil {
64 status := ee.ProcessState.Sys().(syscall.WaitStatus)
65 if status.Exited() {
66 // A non-zero return code isn't considered an error here.
67 result.Code = status.ExitStatus()
68 err = nil
69 }
70 logger.Infof("run result: %v", ee)
71 }
72 return result, err
73}
074
=== added file 'utils/exec/exec_test.go'
--- utils/exec/exec_test.go 1970-01-01 00:00:00 +0000
+++ utils/exec/exec_test.go 2014-01-14 21:31:32 +0000
@@ -0,0 +1,82 @@
1// Copyright 2014 Canonical Ltd.
2// Licensed under the AGPLv3, see LICENCE file for details.
3
4package exec_test
5
6import (
7 gc "launchpad.net/gocheck"
8
9 jc "launchpad.net/juju-core/testing/checkers"
10 "launchpad.net/juju-core/testing/testbase"
11 "launchpad.net/juju-core/utils/exec"
12)
13
14type execSuite struct {
15 testbase.LoggingSuite
16}
17
18var _ = gc.Suite(&execSuite{})
19
20func (*execSuite) TestRunCommands(c *gc.C) {
21 newDir := c.MkDir()
22
23 for i, test := range []struct {
24 message string
25 commands string
26 workingDir string
27 environment []string
28 stdout string
29 stderr string
30 code int
31 }{
32 {
33 message: "test stdout capture",
34 commands: "echo testing stdout",
35 stdout: "testing stdout\n",
36 }, {
37 message: "test stderr capture",
38 commands: "echo testing stderr >&2",
39 stderr: "testing stderr\n",
40 }, {
41 message: "test return code",
42 commands: "exit 42",
43 code: 42,
44 }, {
45 message: "test working dir",
46 commands: "pwd",
47 workingDir: newDir,
48 stdout: newDir + "\n",
49 }, {
50 message: "test environment",
51 commands: "echo $OMG_IT_WORKS",
52 environment: []string{"OMG_IT_WORKS=like magic"},
53 stdout: "like magic\n",
54 },
55 } {
56 c.Logf("%v: %s", i, test.message)
57
58 result, err := exec.RunCommands(
59 exec.RunParams{
60 Commands: test.commands,
61 WorkingDir: test.workingDir,
62 Environment: test.environment,
63 })
64 c.Assert(err, gc.IsNil)
65 c.Assert(string(result.Stdout), gc.Equals, test.stdout)
66 c.Assert(string(result.Stderr), gc.Equals, test.stderr)
67 c.Assert(result.Code, gc.Equals, test.code)
68 }
69}
70
71func (*execSuite) TestExecUnknownCommand(c *gc.C) {
72 result, err := exec.RunCommands(
73 exec.RunParams{
74 Commands: "unknown-command",
75 },
76 )
77 c.Assert(err, gc.IsNil)
78 c.Assert(result.Stdout, gc.HasLen, 0)
79 c.Assert(string(result.Stderr), jc.Contains, "unknown-command: command not found")
80 // 127 is a special bash return code meaning command not found.
81 c.Assert(result.Code, gc.Equals, 127)
82}
083
=== added file 'utils/exec/package_test.go'
--- utils/exec/package_test.go 1970-01-01 00:00:00 +0000
+++ utils/exec/package_test.go 2014-01-14 21:31:32 +0000
@@ -0,0 +1,24 @@
1// Copyright 2014 Canonical Ltd.
2// Licensed under the AGPLv3, see LICENCE file for details.
3
4package exec_test
5
6import (
7 "testing"
8
9 gc "launchpad.net/gocheck"
10
11 "launchpad.net/juju-core/testing/testbase"
12)
13
14func Test(t *testing.T) { gc.TestingT(t) }
15
16type Dependencies struct{}
17
18var _ = gc.Suite(&Dependencies{})
19
20func (*Dependencies) TestPackageDependencies(c *gc.C) {
21 // This test is to ensure we don't bring in dependencies without thinking.
22 c.Assert(testbase.FindJujuCoreImports(c, "launchpad.net/juju-core/utils/exec"),
23 gc.HasLen, 0)
24}
025
=== modified file 'utils/ssh/run.go'
--- utils/ssh/run.go 2014-01-10 01:57:51 +0000
+++ utils/ssh/run.go 2014-01-14 21:31:32 +0000
@@ -11,7 +11,7 @@
11 "syscall"11 "syscall"
12 "time"12 "time"
1313
14 "launchpad.net/juju-core/cmd"14 utilexec "launchpad.net/juju-core/utils/exec"
15)15)
1616
17// ExecParams are used for the parameters for ExecuteCommandOnMachine.17// ExecParams are used for the parameters for ExecuteCommandOnMachine.
@@ -27,7 +27,7 @@
27// through /bin/bash. If the command is not finished within the timeout27// through /bin/bash. If the command is not finished within the timeout
28// specified, an error is returned. Any output captured during that time28// specified, an error is returned. Any output captured during that time
29// is also returned in the remote response.29// is also returned in the remote response.
30func ExecuteCommandOnMachine(params ExecParams) (result cmd.RemoteResponse, err error) {30func ExecuteCommandOnMachine(params ExecParams) (result utilexec.ExecResponse, err error) {
31 // execute bash accepting commands on stdin31 // execute bash accepting commands on stdin
32 if params.Host == "" {32 if params.Host == "" {
33 return result, fmt.Errorf("missing host address")33 return result, fmt.Errorf("missing host address")
3434
=== modified file 'worker/uniter/context.go'
--- worker/uniter/context.go 2013-12-13 03:01:21 +0000
+++ worker/uniter/context.go 2014-01-14 21:31:32 +0000
@@ -5,7 +5,6 @@
55
6import (6import (
7 "bufio"7 "bufio"
8 "bytes"
9 "fmt"8 "fmt"
10 "io"9 "io"
11 "os"10 "os"
@@ -14,13 +13,12 @@
14 "sort"13 "sort"
15 "strings"14 "strings"
16 "sync"15 "sync"
17 "syscall"
18 "time"16 "time"
1917
20 "launchpad.net/juju-core/charm"18 "launchpad.net/juju-core/charm"
21 "launchpad.net/juju-core/cmd"
22 "launchpad.net/juju-core/state/api/params"19 "launchpad.net/juju-core/state/api/params"
23 "launchpad.net/juju-core/state/api/uniter"20 "launchpad.net/juju-core/state/api/uniter"
21 utilexec "launchpad.net/juju-core/utils/exec"
24 unitdebug "launchpad.net/juju-core/worker/uniter/debug"22 unitdebug "launchpad.net/juju-core/worker/uniter/debug"
25 "launchpad.net/juju-core/worker/uniter/jujuc"23 "launchpad.net/juju-core/worker/uniter/jujuc"
26)24)
@@ -212,9 +210,13 @@
212210
213// RunCommands executes the commands in an environment which allows it to to211// RunCommands executes the commands in an environment which allows it to to
214// call back into the hook context to execute jujuc tools.212// call back into the hook context to execute jujuc tools.
215func (ctx *HookContext) RunCommands(commands, charmDir, toolsDir, socketPath string) (*cmd.RemoteResponse, error) {213func (ctx *HookContext) RunCommands(commands, charmDir, toolsDir, socketPath string) (*utilexec.ExecResponse, error) {
216 env := ctx.hookVars(charmDir, toolsDir, socketPath)214 env := ctx.hookVars(charmDir, toolsDir, socketPath)
217 result, err := runCommands(commands, charmDir, env)215 result, err := utilexec.RunCommands(
216 utilexec.RunParams{
217 Commands: commands,
218 WorkingDir: charmDir,
219 Environment: env})
218 return result, ctx.finalizeContext("run commands", err)220 return result, ctx.finalizeContext("run commands", err)
219}221}
220222
@@ -264,38 +266,6 @@
264 return err266 return err
265}267}
266268
267func runCommands(commands, charmDir string, env []string) (*cmd.RemoteResponse, error) {
268 ps := exec.Command("/bin/bash", "-s")
269 ps.Env = env
270 ps.Dir = charmDir
271 ps.Stdin = bytes.NewBufferString(commands)
272
273 stdout := &bytes.Buffer{}
274 stderr := &bytes.Buffer{}
275
276 ps.Stdout = stdout
277 ps.Stderr = stderr
278
279 err := ps.Start()
280 if err == nil {
281 err = ps.Wait()
282 }
283 result := &cmd.RemoteResponse{
284 Stdout: stdout.Bytes(),
285 Stderr: stderr.Bytes(),
286 }
287 if ee, ok := err.(*exec.ExitError); ok && err != nil {
288 status := ee.ProcessState.Sys().(syscall.WaitStatus)
289 if status.Exited() {
290 // A non-zero return code isn't considered an error here.
291 result.Code = status.ExitStatus()
292 err = nil
293 }
294 logger.Infof("run result: %v", ee)
295 }
296 return result, err
297}
298
299type hookLogger struct {269type hookLogger struct {
300 r io.ReadCloser270 r io.ReadCloser
301 done chan struct{}271 done chan struct{}
302272
=== modified file 'worker/uniter/jujuc/server.go'
--- worker/uniter/jujuc/server.go 2013-12-12 04:31:01 +0000
+++ worker/uniter/jujuc/server.go 2014-01-14 21:31:32 +0000
@@ -18,6 +18,7 @@
18 "launchpad.net/loggo"18 "launchpad.net/loggo"
1919
20 "launchpad.net/juju-core/cmd"20 "launchpad.net/juju-core/cmd"
21 "launchpad.net/juju-core/utils/exec"
21)22)
2223
23var logger = loggo.GetLogger("worker.uniter.jujuc")24var logger = loggo.GetLogger("worker.uniter.jujuc")
@@ -79,7 +80,7 @@
7980
80// Main runs the Command specified by req, and fills in resp. A single command81// Main runs the Command specified by req, and fills in resp. A single command
81// is run at a time.82// is run at a time.
82func (j *Jujuc) Main(req Request, resp *cmd.RemoteResponse) error {83func (j *Jujuc) Main(req Request, resp *exec.ExecResponse) error {
83 if req.CommandName == "" {84 if req.CommandName == "" {
84 return badReqErrorf("command not specified")85 return badReqErrorf("command not specified")
85 }86 }
8687
=== modified file 'worker/uniter/jujuc/server_test.go'
--- worker/uniter/jujuc/server_test.go 2013-12-12 04:31:01 +0000
+++ worker/uniter/jujuc/server_test.go 2014-01-14 21:31:32 +0000
@@ -20,6 +20,7 @@
20 "launchpad.net/juju-core/testing"20 "launchpad.net/juju-core/testing"
21 jc "launchpad.net/juju-core/testing/checkers"21 jc "launchpad.net/juju-core/testing/checkers"
22 "launchpad.net/juju-core/testing/testbase"22 "launchpad.net/juju-core/testing/testbase"
23 "launchpad.net/juju-core/utils/exec"
23 "launchpad.net/juju-core/worker/uniter/jujuc"24 "launchpad.net/juju-core/worker/uniter/jujuc"
24)25)
2526
@@ -97,7 +98,7 @@
97 s.LoggingSuite.TearDownTest(c)98 s.LoggingSuite.TearDownTest(c)
98}99}
99100
100func (s *ServerSuite) Call(c *gc.C, req jujuc.Request) (resp cmd.RemoteResponse, err error) {101func (s *ServerSuite) Call(c *gc.C, req jujuc.Request) (resp exec.ExecResponse, err error) {
101 client, err := rpc.Dial("unix", s.sockPath)102 client, err := rpc.Dial("unix", s.sockPath)
102 c.Assert(err, gc.IsNil)103 c.Assert(err, gc.IsNil)
103 defer client.Close()104 defer client.Close()
@@ -162,7 +163,7 @@
162 c.Assert(err, gc.ErrorMatches, `bad request: unknown context "whatever"`)163 c.Assert(err, gc.ErrorMatches, `bad request: unknown context "whatever"`)
163}164}
164165
165func (s *ServerSuite) AssertBadCommand(c *gc.C, args []string, code int) cmd.RemoteResponse {166func (s *ServerSuite) AssertBadCommand(c *gc.C, args []string, code int) exec.ExecResponse {
166 resp, err := s.Call(c, jujuc.Request{"validCtx", c.MkDir(), args[0], args[1:]})167 resp, err := s.Call(c, jujuc.Request{"validCtx", c.MkDir(), args[0], args[1:]})
167 c.Assert(err, gc.IsNil)168 c.Assert(err, gc.IsNil)
168 c.Assert(resp.Code, gc.Equals, code)169 c.Assert(resp.Code, gc.Equals, code)
169170
=== modified file 'worker/uniter/runlistener.go'
--- worker/uniter/runlistener.go 2013-12-13 02:41:10 +0000
+++ worker/uniter/runlistener.go 2014-01-14 21:31:32 +0000
@@ -11,16 +11,16 @@
11 "net/rpc"11 "net/rpc"
12 "sync"12 "sync"
1313
14 "launchpad.net/juju-core/cmd"14 "launchpad.net/juju-core/utils/exec"
15)15)
1616
17const JujuRunEndpoint = "JujuRunServer.RunCommands"17const JujuRunEndpoint = "JujuRunServer.RunCommands"
1818
19// A CommandRunner is something that will actually execute the commands and19// A CommandRunner is something that will actually execute the commands and
20// return the results of that execution in the cmd.RemoteResponse (which20// return the results of that execution in the exec.ExecResponse (which
21// contains stdout, stderr, and return code).21// contains stdout, stderr, and return code).
22type CommandRunner interface {22type CommandRunner interface {
23 RunCommands(commands string) (results *cmd.RemoteResponse, err error)23 RunCommands(commands string) (results *exec.ExecResponse, err error)
24}24}
2525
26// RunListener is responsible for listening on the network connection and26// RunListener is responsible for listening on the network connection and
@@ -42,7 +42,7 @@
4242
43// RunCommands delegates the actual running to the runner and populates the43// RunCommands delegates the actual running to the runner and populates the
44// response structure.44// response structure.
45func (r *JujuRunServer) RunCommands(commands string, result *cmd.RemoteResponse) error {45func (r *JujuRunServer) RunCommands(commands string, result *exec.ExecResponse) error {
46 logger.Debugf("RunCommands: %q", commands)46 logger.Debugf("RunCommands: %q", commands)
47 runResult, err := r.runner.RunCommands(commands)47 runResult, err := r.runner.RunCommands(commands)
48 *result = *runResult48 *result = *runResult
4949
=== modified file 'worker/uniter/runlistener_test.go'
--- worker/uniter/runlistener_test.go 2013-12-13 02:41:10 +0000
+++ worker/uniter/runlistener_test.go 2014-01-14 21:31:32 +0000
@@ -9,8 +9,8 @@
99
10 gc "launchpad.net/gocheck"10 gc "launchpad.net/gocheck"
1111
12 "launchpad.net/juju-core/cmd"
13 "launchpad.net/juju-core/testing/testbase"12 "launchpad.net/juju-core/testing/testbase"
13 "launchpad.net/juju-core/utils/exec"
14 "launchpad.net/juju-core/worker/uniter"14 "launchpad.net/juju-core/worker/uniter"
15)15)
1616
@@ -49,7 +49,7 @@
49 c.Assert(err, gc.IsNil)49 c.Assert(err, gc.IsNil)
50 defer client.Close()50 defer client.Close()
5151
52 var result cmd.RemoteResponse52 var result exec.ExecResponse
53 err = client.Call(uniter.JujuRunEndpoint, "some-command", &result)53 err = client.Call(uniter.JujuRunEndpoint, "some-command", &result)
54 c.Assert(err, gc.IsNil)54 c.Assert(err, gc.IsNil)
5555
@@ -64,9 +64,9 @@
6464
65var _ uniter.CommandRunner = (*mockRunner)(nil)65var _ uniter.CommandRunner = (*mockRunner)(nil)
6666
67func (r *mockRunner) RunCommands(commands string) (results *cmd.RemoteResponse, err error) {67func (r *mockRunner) RunCommands(commands string) (results *exec.ExecResponse, err error) {
68 r.c.Log("mock runner: " + commands)68 r.c.Log("mock runner: " + commands)
69 return &cmd.RemoteResponse{69 return &exec.ExecResponse{
70 Code: 42,70 Code: 42,
71 Stdout: []byte(commands + " stdout"),71 Stdout: []byte(commands + " stdout"),
72 Stderr: []byte(commands + " stderr"),72 Stderr: []byte(commands + " stderr"),
7373
=== modified file 'worker/uniter/uniter.go'
--- worker/uniter/uniter.go 2014-01-03 15:34:52 +0000
+++ worker/uniter/uniter.go 2014-01-14 21:31:32 +0000
@@ -23,6 +23,7 @@
23 "launchpad.net/juju-core/state/api/uniter"23 "launchpad.net/juju-core/state/api/uniter"
24 "launchpad.net/juju-core/state/watcher"24 "launchpad.net/juju-core/state/watcher"
25 "launchpad.net/juju-core/utils"25 "launchpad.net/juju-core/utils"
26 "launchpad.net/juju-core/utils/exec"
26 "launchpad.net/juju-core/utils/fslock"27 "launchpad.net/juju-core/utils/fslock"
27 "launchpad.net/juju-core/worker/uniter/charm"28 "launchpad.net/juju-core/worker/uniter/charm"
28 "launchpad.net/juju-core/worker/uniter/hook"29 "launchpad.net/juju-core/worker/uniter/hook"
@@ -365,7 +366,7 @@
365}366}
366367
367// RunCommands executes the supplied commands in a hook context.368// RunCommands executes the supplied commands in a hook context.
368func (u *Uniter) RunCommands(commands string) (results *cmd.RemoteResponse, err error) {369func (u *Uniter) RunCommands(commands string) (results *exec.ExecResponse, err error) {
369 logger.Tracef("run commands: %s", commands)370 logger.Tracef("run commands: %s", commands)
370 hctxId := fmt.Sprintf("%s:run-commands:%d", u.unit.Name(), u.rand.Int63())371 hctxId := fmt.Sprintf("%s:run-commands:%d", u.unit.Name(), u.rand.Int63())
371 lockMessage := fmt.Sprintf("%s: running commands", u.unit.Name())372 lockMessage := fmt.Sprintf("%s: running commands", u.unit.Name())
372373
=== modified file 'worker/uniter/uniter_test.go'
--- worker/uniter/uniter_test.go 2014-01-14 14:36:31 +0000
+++ worker/uniter/uniter_test.go 2014-01-14 21:31:32 +0000
@@ -25,7 +25,6 @@
2525
26 "launchpad.net/juju-core/agent/tools"26 "launchpad.net/juju-core/agent/tools"
27 "launchpad.net/juju-core/charm"27 "launchpad.net/juju-core/charm"
28 "launchpad.net/juju-core/cmd"
29 "launchpad.net/juju-core/errors"28 "launchpad.net/juju-core/errors"
30 "launchpad.net/juju-core/juju/testing"29 "launchpad.net/juju-core/juju/testing"
31 "launchpad.net/juju-core/state"30 "launchpad.net/juju-core/state"
@@ -35,6 +34,7 @@
35 coretesting "launchpad.net/juju-core/testing"34 coretesting "launchpad.net/juju-core/testing"
36 jc "launchpad.net/juju-core/testing/checkers"35 jc "launchpad.net/juju-core/testing/checkers"
37 "launchpad.net/juju-core/utils"36 "launchpad.net/juju-core/utils"
37 utilexec "launchpad.net/juju-core/utils/exec"
38 "launchpad.net/juju-core/utils/fslock"38 "launchpad.net/juju-core/utils/fslock"
39 "launchpad.net/juju-core/worker"39 "launchpad.net/juju-core/worker"
40 "launchpad.net/juju-core/worker/uniter"40 "launchpad.net/juju-core/worker/uniter"
@@ -1963,7 +1963,7 @@
1963 c.Assert(err, gc.IsNil)1963 c.Assert(err, gc.IsNil)
1964 defer client.Close()1964 defer client.Close()
19651965
1966 var result cmd.RemoteResponse1966 var result utilexec.ExecResponse
1967 err = client.Call(uniter.JujuRunEndpoint, commands, &result)1967 err = client.Call(uniter.JujuRunEndpoint, commands, &result)
1968 c.Assert(err, gc.IsNil)1968 c.Assert(err, gc.IsNil)
1969 c.Check(result.Code, gc.Equals, 0)1969 c.Check(result.Code, gc.Equals, 0)

Subscribers

People subscribed via source and target branches

to status/vote changes: