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