Description:
environs/manual: ignore stderr in checkProvisioned
ssh may issue warnings on stderr, for example if
the target host does not exist in known_hosts.
This was tripping up the checkProvisioned function,
which was incorrectly checking that both stdout and
stderr were empty.
Reviewers: mp+184911_ code.launchpad. net,
Message:
Please take a look.
Description:
environs/manual: ignore stderr in checkProvisioned
ssh may issue warnings on stderr, for example if
the target host does not exist in known_hosts.
This was tripping up the checkProvisioned function,
which was incorrectly checking that both stdout and
stderr were empty.
Fixes #1223277
https:/ /code.launchpad .net/~axwalk/ juju-core/ lp1223277- check-provision ed-ignore- stderr/ +merge/ 184911
(do not edit description out of merge proposal)
Please review this at https:/ /codereview. appspot. com/13477045/
Affected files (+54, -8 lines): manual/ detection. go manual/ detection_ test.go
A [revision details]
M environs/
M environs/
Index: [revision details] 20130910174617- 1ib2wgm1qymgkvv s
=== added file '[revision details]'
--- [revision details] 2012-01-01 00:00:00 +0000
+++ [revision details] 2012-01-01 00:00:00 +0000
@@ -0,0 +1,2 @@
+Old revision: tarmac-
+New revision: <email address hidden>
Index: environs/ manual/ detection. go manual/ detection. go' manual/ detection. go 2013-08-23 06:57:09 +0000 manual/ detection. go 2013-09-11 01:58:11 +0000 d(sshHost string) (bool, error) { String( checkProvisione dScript) put() TrimSpace( stderr. String( ))) TrimSpace( string( out))) > 0, nil TrimSpace( stdout. String( ))) > 0, nil
=== modified file 'environs/
--- environs/
+++ environs/
@@ -26,11 +26,16 @@
func checkProvisione
cmd := exec.Command("ssh", sshHost, "bash")
cmd.Stdin = bytes.NewBuffer
- out, err := cmd.CombinedOut
- if err != nil {
+ var stdout, stderr bytes.Buffer
+ cmd.Stdout = &stdout
+ cmd.Stderr = &stderr
+ if err := cmd.Run(); err != nil {
+ if stderr.Len() != 0 {
+ err = fmt.Errorf("%v (%v)", err, strings.
+ }
return false, err
}
- return len(strings.
+ return len(strings.
}
// detectSeriesHar dwareCharacteri stics detects the OS series
Index: environs/ manual/ detection_ test.go manual/ detection_ test.go' manual/ detection_ test.go 2013-08-29 03:58:19 +0000 manual/ detection_ test.go 2013-09-11 01:58:11 +0000 net/gocheck"
=== modified file 'environs/
--- environs/
+++ environs/
@@ -13,6 +13,7 @@
gc "launchpad.
"launchpad. net/juju- core/testing" net/juju- core/testing/ checkers"
+ jc "launchpad.
)
type detectionSuite struct { Join(fakebin, "ssh") "cat<<EOF\ n%s\nEOF" , output) "cat<<EOF\ n%s\nEOF" , output) "cat<<EOF\ n%s\nEOF" , output[0]) "cat>&2< <EOF\n% s\nEOF" , output[1]) sshscript, output, rc) sshscript, stdout, stderr, rc) WriteFile( ssh, []byte(script), 0777) WriteFile( sshexpectedinpu t, []byte(input), 0644) hc.String( ), gc.Equals, test.expectedHc) ioned(c *gc.C) { dScript, "", 0)() d("example. com") provisioned, jc.IsFalse) dScript, "non-empty", 0)() d("example. com") provisioned, jc.IsTrue) dScript, stderr" }, 0)() d("example. com") provisioned, jc.IsFalse) dScript, "non-empty- stdout" , "non-empty- stderr" }, 255)() d("example. com") empty-stderr\ \)")
@@ -34,7 +35,10 @@
echo "ERROR: did not match expected input" >&2
exit $exitcode
fi
-%s
+ # stdout
+ %s
+ # stderr
+ %s
exit %d
else
export PATH=${PATH#*:}
@@ -44,14 +48,25 @@
// sshresponse creates a fake "ssh" command in a new $PATH,
// updates $PATH, and returns a function to reset $PATH to
// its original value when called.
-func sshresponse(c *gc.C, input, output string, rc int) func() {
+//
+// output may be:
+// - nil (no output)
+// - a string (stdout)
+// - a slice of strings, of length two (stdout, stderr)
+func sshresponse(c *gc.C, input string, output interface{}, rc int) func()
{
fakebin := c.MkDir()
ssh := filepath.
sshexpectedinput := ssh + ".expected-input"
- if output != "" {
- output = fmt.Sprintf(
+ var stdout, stderr string
+ switch output := output.(type) {
+ case nil:
+ case string:
+ stdout = fmt.Sprintf(
+ case []string:
+ stdout = fmt.Sprintf(
+ stderr = fmt.Sprintf(
}
- script := fmt.Sprintf(
+ script := fmt.Sprintf(
err := ioutil.
c.Assert(err, gc.IsNil)
err = ioutil.
@@ -139,3 +154,27 @@
c.Assert(
}
}
+
+func (s *detectionSuite) TestCheckProvis
+ defer sshresponse(c, checkProvisione
+ provisioned, err := checkProvisione
+ c.Assert(err, gc.IsNil)
+ c.Assert(
+
+ defer sshresponse(c, checkProvisione
+ provisioned, err = checkProvisione
+ c.Assert(err, gc.IsNil)
+ c.Assert(
+
+ // stderr should not affect result.
+ defer sshresponse(c, checkProvisione
[]string{"", "non-empty-
+ provisioned, err = checkProvisione
+ c.Assert(err, gc.IsNil)
+ c.Assert(
+
+ // if the script fails for whatever reason, then checkProvisioned
+ // will return an error. stderr will be included in the error message.
+ defer sshresponse(c, checkProvisione
[]string{
+ _, err = checkProvisione
+ c.Assert(err, gc.ErrorMatches, "exit status 255 \\(non-
+}