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
1=== modified file 'cmd/juju/run_test.go'
2--- cmd/juju/run_test.go 2014-01-12 20:38:39 +0000
3+++ cmd/juju/run_test.go 2014-01-14 21:31:32 +0000
4@@ -13,6 +13,7 @@
5 "launchpad.net/juju-core/state/api/params"
6 "launchpad.net/juju-core/testing"
7 jc "launchpad.net/juju-core/testing/checkers"
8+ "launchpad.net/juju-core/utils/exec"
9 )
10
11 type RunSuite struct {
12@@ -191,7 +192,7 @@
13 message: "stdout and stderr are base64 encoded if not valid utf8",
14 results: []params.RunResult{
15 params.RunResult{
16- RemoteResponse: cmd.RemoteResponse{
17+ ExecResponse: exec.ExecResponse{
18 Stdout: []byte{0xff},
19 Stderr: []byte{0xfe},
20 },
21@@ -386,7 +387,7 @@
22
23 func makeRunResult(mock mockResponse) params.RunResult {
24 return params.RunResult{
25- RemoteResponse: cmd.RemoteResponse{
26+ ExecResponse: exec.ExecResponse{
27 Stdout: []byte(mock.stdout),
28 Stderr: []byte(mock.stderr),
29 Code: mock.code,
30
31=== modified file 'cmd/jujud/main.go'
32--- cmd/jujud/main.go 2013-12-12 22:54:02 +0000
33+++ cmd/jujud/main.go 2014-01-14 21:31:32 +0000
34@@ -10,6 +10,7 @@
35 "path/filepath"
36
37 "launchpad.net/juju-core/cmd"
38+ "launchpad.net/juju-core/utils/exec"
39 "launchpad.net/juju-core/worker/uniter/jujuc"
40
41 // Import the providers.
42@@ -76,7 +77,7 @@
43 return
44 }
45 defer client.Close()
46- var resp cmd.RemoteResponse
47+ var resp exec.ExecResponse
48 err = client.Call("Jujuc.Main", req, &resp)
49 if err != nil {
50 return
51
52=== modified file 'cmd/jujud/run.go'
53--- cmd/jujud/run.go 2013-12-13 04:40:41 +0000
54+++ cmd/jujud/run.go 2014-01-14 21:31:32 +0000
55@@ -13,6 +13,7 @@
56
57 "launchpad.net/juju-core/cmd"
58 "launchpad.net/juju-core/names"
59+ "launchpad.net/juju-core/utils/exec"
60 "launchpad.net/juju-core/worker/uniter"
61 )
62
63@@ -96,7 +97,7 @@
64 }
65 defer client.Close()
66
67- var result cmd.RemoteResponse
68+ var result exec.ExecResponse
69 err = client.Call(uniter.JujuRunEndpoint, c.commands, &result)
70 if err != nil {
71 return err
72
73=== modified file 'cmd/jujud/run_test.go'
74--- cmd/jujud/run_test.go 2013-12-13 03:37:01 +0000
75+++ cmd/jujud/run_test.go 2014-01-14 21:31:32 +0000
76@@ -15,6 +15,7 @@
77 "launchpad.net/juju-core/testing"
78 jc "launchpad.net/juju-core/testing/checkers"
79 "launchpad.net/juju-core/testing/testbase"
80+ "launchpad.net/juju-core/utils/exec"
81 "launchpad.net/juju-core/worker/uniter"
82 )
83
84@@ -125,9 +126,9 @@
85
86 var _ uniter.CommandRunner = (*mockRunner)(nil)
87
88-func (r *mockRunner) RunCommands(commands string) (results *cmd.RemoteResponse, err error) {
89+func (r *mockRunner) RunCommands(commands string) (results *exec.ExecResponse, err error) {
90 r.c.Log("mock runner: " + commands)
91- return &cmd.RemoteResponse{
92+ return &exec.ExecResponse{
93 Code: 42,
94 Stdout: []byte(commands + " stdout"),
95 Stderr: []byte(commands + " stderr"),
96
97=== removed file 'cmd/remote.go'
98--- cmd/remote.go 2013-12-12 04:31:01 +0000
99+++ cmd/remote.go 1970-01-01 00:00:00 +0000
100@@ -1,12 +0,0 @@
101-// Copyright 2013 Canonical Ltd.
102-// Licensed under the AGPLv3, see LICENCE file for details.
103-
104-package cmd
105-
106-// RemoteResponse contains the return code and output generated by a remote
107-// request.
108-type RemoteResponse struct {
109- Code int
110- Stdout []byte
111- Stderr []byte
112-}
113
114=== modified file 'state/api/params/internal.go'
115--- state/api/params/internal.go 2014-01-12 20:07:40 +0000
116+++ state/api/params/internal.go 2014-01-14 21:31:32 +0000
117@@ -6,10 +6,10 @@
118 import (
119 "time"
120
121- "launchpad.net/juju-core/cmd"
122 "launchpad.net/juju-core/constraints"
123 "launchpad.net/juju-core/instance"
124 "launchpad.net/juju-core/tools"
125+ "launchpad.net/juju-core/utils/exec"
126 "launchpad.net/juju-core/version"
127 )
128
129@@ -527,7 +527,7 @@
130 // RunResult contains the result from an individual run call on a machine.
131 // UnitId is populated if the command was run inside the unit context.
132 type RunResult struct {
133- cmd.RemoteResponse
134+ exec.ExecResponse
135 MachineId string
136 UnitId string
137 Error string
138
139=== modified file 'state/apiserver/client/run.go'
140--- state/apiserver/client/run.go 2014-01-12 20:28:43 +0000
141+++ state/apiserver/client/run.go 2014-01-14 21:31:32 +0000
142@@ -150,9 +150,9 @@
143 response, err := ssh.ExecuteCommandOnMachine(param.ExecParams)
144 logger.Debugf("reponse from %s: %v (err:%v)", param.MachineId, response, err)
145 execResponse := params.RunResult{
146- RemoteResponse: response,
147- MachineId: param.MachineId,
148- UnitId: param.UnitId,
149+ ExecResponse: response,
150+ MachineId: param.MachineId,
151+ UnitId: param.UnitId,
152 }
153 if err != nil {
154 execResponse.Error = fmt.Sprint(err)
155
156=== modified file 'state/apiserver/client/run_test.go'
157--- state/apiserver/client/run_test.go 2014-01-12 20:28:43 +0000
158+++ state/apiserver/client/run_test.go 2014-01-14 21:31:32 +0000
159@@ -12,13 +12,13 @@
160
161 gc "launchpad.net/gocheck"
162
163- "launchpad.net/juju-core/cmd"
164 "launchpad.net/juju-core/instance"
165 "launchpad.net/juju-core/state"
166 "launchpad.net/juju-core/state/api/params"
167 "launchpad.net/juju-core/state/apiserver/client"
168 "launchpad.net/juju-core/testing"
169 jc "launchpad.net/juju-core/testing/checkers"
170+ "launchpad.net/juju-core/utils/exec"
171 "launchpad.net/juju-core/utils/ssh"
172 )
173
174@@ -230,8 +230,8 @@
175 for i := 0; i < 3; i++ {
176 expectedResults = append(expectedResults,
177 params.RunResult{
178- RemoteResponse: cmd.RemoteResponse{Stdout: []byte("hostname\n")},
179- MachineId: fmt.Sprint(i),
180+ ExecResponse: exec.ExecResponse{Stdout: []byte("hostname\n")},
181+ MachineId: fmt.Sprint(i),
182 })
183 }
184
185@@ -264,18 +264,18 @@
186 c.Assert(results, gc.HasLen, 3)
187 expectedResults := []params.RunResult{
188 params.RunResult{
189- RemoteResponse: cmd.RemoteResponse{Stdout: []byte("hostname\n")},
190- MachineId: "0",
191- },
192- params.RunResult{
193- RemoteResponse: cmd.RemoteResponse{Stdout: []byte("juju-run magic/0 'hostname'\n")},
194- MachineId: "1",
195- UnitId: "magic/0",
196- },
197- params.RunResult{
198- RemoteResponse: cmd.RemoteResponse{Stdout: []byte("juju-run magic/1 'hostname'\n")},
199- MachineId: "2",
200- UnitId: "magic/1",
201+ ExecResponse: exec.ExecResponse{Stdout: []byte("hostname\n")},
202+ MachineId: "0",
203+ },
204+ params.RunResult{
205+ ExecResponse: exec.ExecResponse{Stdout: []byte("juju-run magic/0 'hostname'\n")},
206+ MachineId: "1",
207+ UnitId: "magic/0",
208+ },
209+ params.RunResult{
210+ ExecResponse: exec.ExecResponse{Stdout: []byte("juju-run magic/1 'hostname'\n")},
211+ MachineId: "2",
212+ UnitId: "magic/1",
213 },
214 }
215
216
217=== added directory 'utils/exec'
218=== added file 'utils/exec/exec.go'
219--- utils/exec/exec.go 1970-01-01 00:00:00 +0000
220+++ utils/exec/exec.go 2014-01-14 21:31:32 +0000
221@@ -0,0 +1,73 @@
222+// Copyright 2014 Canonical Ltd.
223+// Licensed under the AGPLv3, see LICENCE file for details.
224+
225+package exec
226+
227+import (
228+ "bytes"
229+ "os/exec"
230+ "syscall"
231+
232+ "launchpad.net/loggo"
233+)
234+
235+var logger = loggo.GetLogger("juju.util.exec")
236+
237+// Parameters for RunCommands. Commands contains one or more commands to be
238+// executed using '/bin/bash -s'. If WorkingDir is set, this is passed
239+// through to bash. Similarly if the Environment is specified, this is used
240+// for executing the command.
241+type RunParams struct {
242+ Commands string
243+ WorkingDir string
244+ Environment []string
245+}
246+
247+// ExecResponse contains the return code and output generated by executing a
248+// command.
249+type ExecResponse struct {
250+ Code int
251+ Stdout []byte
252+ Stderr []byte
253+}
254+
255+// RunCommands executes the Commands specified in the RunParams using
256+// '/bin/bash -s', passing the commands through as stdin, and collecting
257+// stdout and stderr. If a non-zero return code is returned, this is
258+// collected as the code for the response and this does not classify as an
259+// error.
260+func RunCommands(run RunParams) (*ExecResponse, error) {
261+ ps := exec.Command("/bin/bash", "-s")
262+ if run.Environment != nil {
263+ ps.Env = run.Environment
264+ }
265+ if run.WorkingDir != "" {
266+ ps.Dir = run.WorkingDir
267+ }
268+ ps.Stdin = bytes.NewBufferString(run.Commands)
269+
270+ stdout := &bytes.Buffer{}
271+ stderr := &bytes.Buffer{}
272+
273+ ps.Stdout = stdout
274+ ps.Stderr = stderr
275+
276+ err := ps.Start()
277+ if err == nil {
278+ err = ps.Wait()
279+ }
280+ result := &ExecResponse{
281+ Stdout: stdout.Bytes(),
282+ Stderr: stderr.Bytes(),
283+ }
284+ if ee, ok := err.(*exec.ExitError); ok && err != nil {
285+ status := ee.ProcessState.Sys().(syscall.WaitStatus)
286+ if status.Exited() {
287+ // A non-zero return code isn't considered an error here.
288+ result.Code = status.ExitStatus()
289+ err = nil
290+ }
291+ logger.Infof("run result: %v", ee)
292+ }
293+ return result, err
294+}
295
296=== added file 'utils/exec/exec_test.go'
297--- utils/exec/exec_test.go 1970-01-01 00:00:00 +0000
298+++ utils/exec/exec_test.go 2014-01-14 21:31:32 +0000
299@@ -0,0 +1,82 @@
300+// Copyright 2014 Canonical Ltd.
301+// Licensed under the AGPLv3, see LICENCE file for details.
302+
303+package exec_test
304+
305+import (
306+ gc "launchpad.net/gocheck"
307+
308+ jc "launchpad.net/juju-core/testing/checkers"
309+ "launchpad.net/juju-core/testing/testbase"
310+ "launchpad.net/juju-core/utils/exec"
311+)
312+
313+type execSuite struct {
314+ testbase.LoggingSuite
315+}
316+
317+var _ = gc.Suite(&execSuite{})
318+
319+func (*execSuite) TestRunCommands(c *gc.C) {
320+ newDir := c.MkDir()
321+
322+ for i, test := range []struct {
323+ message string
324+ commands string
325+ workingDir string
326+ environment []string
327+ stdout string
328+ stderr string
329+ code int
330+ }{
331+ {
332+ message: "test stdout capture",
333+ commands: "echo testing stdout",
334+ stdout: "testing stdout\n",
335+ }, {
336+ message: "test stderr capture",
337+ commands: "echo testing stderr >&2",
338+ stderr: "testing stderr\n",
339+ }, {
340+ message: "test return code",
341+ commands: "exit 42",
342+ code: 42,
343+ }, {
344+ message: "test working dir",
345+ commands: "pwd",
346+ workingDir: newDir,
347+ stdout: newDir + "\n",
348+ }, {
349+ message: "test environment",
350+ commands: "echo $OMG_IT_WORKS",
351+ environment: []string{"OMG_IT_WORKS=like magic"},
352+ stdout: "like magic\n",
353+ },
354+ } {
355+ c.Logf("%v: %s", i, test.message)
356+
357+ result, err := exec.RunCommands(
358+ exec.RunParams{
359+ Commands: test.commands,
360+ WorkingDir: test.workingDir,
361+ Environment: test.environment,
362+ })
363+ c.Assert(err, gc.IsNil)
364+ c.Assert(string(result.Stdout), gc.Equals, test.stdout)
365+ c.Assert(string(result.Stderr), gc.Equals, test.stderr)
366+ c.Assert(result.Code, gc.Equals, test.code)
367+ }
368+}
369+
370+func (*execSuite) TestExecUnknownCommand(c *gc.C) {
371+ result, err := exec.RunCommands(
372+ exec.RunParams{
373+ Commands: "unknown-command",
374+ },
375+ )
376+ c.Assert(err, gc.IsNil)
377+ c.Assert(result.Stdout, gc.HasLen, 0)
378+ c.Assert(string(result.Stderr), jc.Contains, "unknown-command: command not found")
379+ // 127 is a special bash return code meaning command not found.
380+ c.Assert(result.Code, gc.Equals, 127)
381+}
382
383=== added file 'utils/exec/package_test.go'
384--- utils/exec/package_test.go 1970-01-01 00:00:00 +0000
385+++ utils/exec/package_test.go 2014-01-14 21:31:32 +0000
386@@ -0,0 +1,24 @@
387+// Copyright 2014 Canonical Ltd.
388+// Licensed under the AGPLv3, see LICENCE file for details.
389+
390+package exec_test
391+
392+import (
393+ "testing"
394+
395+ gc "launchpad.net/gocheck"
396+
397+ "launchpad.net/juju-core/testing/testbase"
398+)
399+
400+func Test(t *testing.T) { gc.TestingT(t) }
401+
402+type Dependencies struct{}
403+
404+var _ = gc.Suite(&Dependencies{})
405+
406+func (*Dependencies) TestPackageDependencies(c *gc.C) {
407+ // This test is to ensure we don't bring in dependencies without thinking.
408+ c.Assert(testbase.FindJujuCoreImports(c, "launchpad.net/juju-core/utils/exec"),
409+ gc.HasLen, 0)
410+}
411
412=== modified file 'utils/ssh/run.go'
413--- utils/ssh/run.go 2014-01-10 01:57:51 +0000
414+++ utils/ssh/run.go 2014-01-14 21:31:32 +0000
415@@ -11,7 +11,7 @@
416 "syscall"
417 "time"
418
419- "launchpad.net/juju-core/cmd"
420+ utilexec "launchpad.net/juju-core/utils/exec"
421 )
422
423 // ExecParams are used for the parameters for ExecuteCommandOnMachine.
424@@ -27,7 +27,7 @@
425 // through /bin/bash. If the command is not finished within the timeout
426 // specified, an error is returned. Any output captured during that time
427 // is also returned in the remote response.
428-func ExecuteCommandOnMachine(params ExecParams) (result cmd.RemoteResponse, err error) {
429+func ExecuteCommandOnMachine(params ExecParams) (result utilexec.ExecResponse, err error) {
430 // execute bash accepting commands on stdin
431 if params.Host == "" {
432 return result, fmt.Errorf("missing host address")
433
434=== modified file 'worker/uniter/context.go'
435--- worker/uniter/context.go 2013-12-13 03:01:21 +0000
436+++ worker/uniter/context.go 2014-01-14 21:31:32 +0000
437@@ -5,7 +5,6 @@
438
439 import (
440 "bufio"
441- "bytes"
442 "fmt"
443 "io"
444 "os"
445@@ -14,13 +13,12 @@
446 "sort"
447 "strings"
448 "sync"
449- "syscall"
450 "time"
451
452 "launchpad.net/juju-core/charm"
453- "launchpad.net/juju-core/cmd"
454 "launchpad.net/juju-core/state/api/params"
455 "launchpad.net/juju-core/state/api/uniter"
456+ utilexec "launchpad.net/juju-core/utils/exec"
457 unitdebug "launchpad.net/juju-core/worker/uniter/debug"
458 "launchpad.net/juju-core/worker/uniter/jujuc"
459 )
460@@ -212,9 +210,13 @@
461
462 // RunCommands executes the commands in an environment which allows it to to
463 // call back into the hook context to execute jujuc tools.
464-func (ctx *HookContext) RunCommands(commands, charmDir, toolsDir, socketPath string) (*cmd.RemoteResponse, error) {
465+func (ctx *HookContext) RunCommands(commands, charmDir, toolsDir, socketPath string) (*utilexec.ExecResponse, error) {
466 env := ctx.hookVars(charmDir, toolsDir, socketPath)
467- result, err := runCommands(commands, charmDir, env)
468+ result, err := utilexec.RunCommands(
469+ utilexec.RunParams{
470+ Commands: commands,
471+ WorkingDir: charmDir,
472+ Environment: env})
473 return result, ctx.finalizeContext("run commands", err)
474 }
475
476@@ -264,38 +266,6 @@
477 return err
478 }
479
480-func runCommands(commands, charmDir string, env []string) (*cmd.RemoteResponse, error) {
481- ps := exec.Command("/bin/bash", "-s")
482- ps.Env = env
483- ps.Dir = charmDir
484- ps.Stdin = bytes.NewBufferString(commands)
485-
486- stdout := &bytes.Buffer{}
487- stderr := &bytes.Buffer{}
488-
489- ps.Stdout = stdout
490- ps.Stderr = stderr
491-
492- err := ps.Start()
493- if err == nil {
494- err = ps.Wait()
495- }
496- result := &cmd.RemoteResponse{
497- Stdout: stdout.Bytes(),
498- Stderr: stderr.Bytes(),
499- }
500- if ee, ok := err.(*exec.ExitError); ok && err != nil {
501- status := ee.ProcessState.Sys().(syscall.WaitStatus)
502- if status.Exited() {
503- // A non-zero return code isn't considered an error here.
504- result.Code = status.ExitStatus()
505- err = nil
506- }
507- logger.Infof("run result: %v", ee)
508- }
509- return result, err
510-}
511-
512 type hookLogger struct {
513 r io.ReadCloser
514 done chan struct{}
515
516=== modified file 'worker/uniter/jujuc/server.go'
517--- worker/uniter/jujuc/server.go 2013-12-12 04:31:01 +0000
518+++ worker/uniter/jujuc/server.go 2014-01-14 21:31:32 +0000
519@@ -18,6 +18,7 @@
520 "launchpad.net/loggo"
521
522 "launchpad.net/juju-core/cmd"
523+ "launchpad.net/juju-core/utils/exec"
524 )
525
526 var logger = loggo.GetLogger("worker.uniter.jujuc")
527@@ -79,7 +80,7 @@
528
529 // Main runs the Command specified by req, and fills in resp. A single command
530 // is run at a time.
531-func (j *Jujuc) Main(req Request, resp *cmd.RemoteResponse) error {
532+func (j *Jujuc) Main(req Request, resp *exec.ExecResponse) error {
533 if req.CommandName == "" {
534 return badReqErrorf("command not specified")
535 }
536
537=== modified file 'worker/uniter/jujuc/server_test.go'
538--- worker/uniter/jujuc/server_test.go 2013-12-12 04:31:01 +0000
539+++ worker/uniter/jujuc/server_test.go 2014-01-14 21:31:32 +0000
540@@ -20,6 +20,7 @@
541 "launchpad.net/juju-core/testing"
542 jc "launchpad.net/juju-core/testing/checkers"
543 "launchpad.net/juju-core/testing/testbase"
544+ "launchpad.net/juju-core/utils/exec"
545 "launchpad.net/juju-core/worker/uniter/jujuc"
546 )
547
548@@ -97,7 +98,7 @@
549 s.LoggingSuite.TearDownTest(c)
550 }
551
552-func (s *ServerSuite) Call(c *gc.C, req jujuc.Request) (resp cmd.RemoteResponse, err error) {
553+func (s *ServerSuite) Call(c *gc.C, req jujuc.Request) (resp exec.ExecResponse, err error) {
554 client, err := rpc.Dial("unix", s.sockPath)
555 c.Assert(err, gc.IsNil)
556 defer client.Close()
557@@ -162,7 +163,7 @@
558 c.Assert(err, gc.ErrorMatches, `bad request: unknown context "whatever"`)
559 }
560
561-func (s *ServerSuite) AssertBadCommand(c *gc.C, args []string, code int) cmd.RemoteResponse {
562+func (s *ServerSuite) AssertBadCommand(c *gc.C, args []string, code int) exec.ExecResponse {
563 resp, err := s.Call(c, jujuc.Request{"validCtx", c.MkDir(), args[0], args[1:]})
564 c.Assert(err, gc.IsNil)
565 c.Assert(resp.Code, gc.Equals, code)
566
567=== modified file 'worker/uniter/runlistener.go'
568--- worker/uniter/runlistener.go 2013-12-13 02:41:10 +0000
569+++ worker/uniter/runlistener.go 2014-01-14 21:31:32 +0000
570@@ -11,16 +11,16 @@
571 "net/rpc"
572 "sync"
573
574- "launchpad.net/juju-core/cmd"
575+ "launchpad.net/juju-core/utils/exec"
576 )
577
578 const JujuRunEndpoint = "JujuRunServer.RunCommands"
579
580 // A CommandRunner is something that will actually execute the commands and
581-// return the results of that execution in the cmd.RemoteResponse (which
582+// return the results of that execution in the exec.ExecResponse (which
583 // contains stdout, stderr, and return code).
584 type CommandRunner interface {
585- RunCommands(commands string) (results *cmd.RemoteResponse, err error)
586+ RunCommands(commands string) (results *exec.ExecResponse, err error)
587 }
588
589 // RunListener is responsible for listening on the network connection and
590@@ -42,7 +42,7 @@
591
592 // RunCommands delegates the actual running to the runner and populates the
593 // response structure.
594-func (r *JujuRunServer) RunCommands(commands string, result *cmd.RemoteResponse) error {
595+func (r *JujuRunServer) RunCommands(commands string, result *exec.ExecResponse) error {
596 logger.Debugf("RunCommands: %q", commands)
597 runResult, err := r.runner.RunCommands(commands)
598 *result = *runResult
599
600=== modified file 'worker/uniter/runlistener_test.go'
601--- worker/uniter/runlistener_test.go 2013-12-13 02:41:10 +0000
602+++ worker/uniter/runlistener_test.go 2014-01-14 21:31:32 +0000
603@@ -9,8 +9,8 @@
604
605 gc "launchpad.net/gocheck"
606
607- "launchpad.net/juju-core/cmd"
608 "launchpad.net/juju-core/testing/testbase"
609+ "launchpad.net/juju-core/utils/exec"
610 "launchpad.net/juju-core/worker/uniter"
611 )
612
613@@ -49,7 +49,7 @@
614 c.Assert(err, gc.IsNil)
615 defer client.Close()
616
617- var result cmd.RemoteResponse
618+ var result exec.ExecResponse
619 err = client.Call(uniter.JujuRunEndpoint, "some-command", &result)
620 c.Assert(err, gc.IsNil)
621
622@@ -64,9 +64,9 @@
623
624 var _ uniter.CommandRunner = (*mockRunner)(nil)
625
626-func (r *mockRunner) RunCommands(commands string) (results *cmd.RemoteResponse, err error) {
627+func (r *mockRunner) RunCommands(commands string) (results *exec.ExecResponse, err error) {
628 r.c.Log("mock runner: " + commands)
629- return &cmd.RemoteResponse{
630+ return &exec.ExecResponse{
631 Code: 42,
632 Stdout: []byte(commands + " stdout"),
633 Stderr: []byte(commands + " stderr"),
634
635=== modified file 'worker/uniter/uniter.go'
636--- worker/uniter/uniter.go 2014-01-03 15:34:52 +0000
637+++ worker/uniter/uniter.go 2014-01-14 21:31:32 +0000
638@@ -23,6 +23,7 @@
639 "launchpad.net/juju-core/state/api/uniter"
640 "launchpad.net/juju-core/state/watcher"
641 "launchpad.net/juju-core/utils"
642+ "launchpad.net/juju-core/utils/exec"
643 "launchpad.net/juju-core/utils/fslock"
644 "launchpad.net/juju-core/worker/uniter/charm"
645 "launchpad.net/juju-core/worker/uniter/hook"
646@@ -365,7 +366,7 @@
647 }
648
649 // RunCommands executes the supplied commands in a hook context.
650-func (u *Uniter) RunCommands(commands string) (results *cmd.RemoteResponse, err error) {
651+func (u *Uniter) RunCommands(commands string) (results *exec.ExecResponse, err error) {
652 logger.Tracef("run commands: %s", commands)
653 hctxId := fmt.Sprintf("%s:run-commands:%d", u.unit.Name(), u.rand.Int63())
654 lockMessage := fmt.Sprintf("%s: running commands", u.unit.Name())
655
656=== modified file 'worker/uniter/uniter_test.go'
657--- worker/uniter/uniter_test.go 2014-01-14 14:36:31 +0000
658+++ worker/uniter/uniter_test.go 2014-01-14 21:31:32 +0000
659@@ -25,7 +25,6 @@
660
661 "launchpad.net/juju-core/agent/tools"
662 "launchpad.net/juju-core/charm"
663- "launchpad.net/juju-core/cmd"
664 "launchpad.net/juju-core/errors"
665 "launchpad.net/juju-core/juju/testing"
666 "launchpad.net/juju-core/state"
667@@ -35,6 +34,7 @@
668 coretesting "launchpad.net/juju-core/testing"
669 jc "launchpad.net/juju-core/testing/checkers"
670 "launchpad.net/juju-core/utils"
671+ utilexec "launchpad.net/juju-core/utils/exec"
672 "launchpad.net/juju-core/utils/fslock"
673 "launchpad.net/juju-core/worker"
674 "launchpad.net/juju-core/worker/uniter"
675@@ -1963,7 +1963,7 @@
676 c.Assert(err, gc.IsNil)
677 defer client.Close()
678
679- var result cmd.RemoteResponse
680+ var result utilexec.ExecResponse
681 err = client.Call(uniter.JujuRunEndpoint, commands, &result)
682 c.Assert(err, gc.IsNil)
683 c.Check(result.Code, gc.Equals, 0)

Subscribers

People subscribed via source and target branches

to status/vote changes: