state: add ssh forwarding functionality
https://code.launchpad.net/~rogpeppe/juju/go-ssh-connect/+merge/100281
(do not edit description out of merge proposal)
I've skimmed over it, and the overall approach looks nice. As a minor, I think
sshDial should wait after it kills the forwarder so that we don't have stuff
running in the background. I'll have a more careful look tomorrow.
https://codereview.appspot.com/5970053/diff/2001/state/ssh.go
File state/ssh.go (right):
https://codereview.appspot.com/5970053/diff/2001/state/ssh.go#newcode19
state/ssh.go:19: fwd, err := newSSHForwarder(addr)
On 2012/04/17 15:24:15, fwereade wrote:
> Maybe this is one for a future branch, but shouldn't we really be creating a
> forwarder for each of N addresses and giving ZK all the local addresses?
yes, but i'm sticking with the python version's current functionality for now.
by the time we get around to implementing multiple zk nodes, i hope we can have
a better solution than this horrible hack.
https://codereview.appspot.com/5970053/diff/2001/state/ssh.go#newcode87
state/ssh.go:87: var timeout <-chan time.Time
On 2012/04/17 15:24:15, fwereade wrote:
> Could we call this waitErrTimeout instead?
Done.
https://codereview.appspot.com/5970053/diff/2001/state/ssh.go#newcode105
state/ssh.go:105: // going wrong and quit.
On 2012/04/17 15:24:15, fwereade wrote:
> I presume we'll be handling the necessary
> wait-for-server-to-exist-and-accept-connections behaviour at a higher level?
if the ssh client fails because the server doesn't yet exist, the error (sshErr)
shouldn't be fatal and this loop will repeat.
https://codereview.appspot.com/5970053/diff/2001/state/ssh.go#newcode124
state/ssh.go:124: case <-timeout:
On 2012/04/17 15:24:15, fwereade wrote:
> Ah, interesting, didn't realise you could select on a nil chan.
it's a very useful technique. in Limbo, to do the same thing you had to create a
dummy channel, which is significantly more awkward.
https://codereview.appspot.com/5970053/diff/2001/state/ssh.go#newcode215
state/ssh.go:215: unknown bool // Whether we've have not recognised the error
message.
On 2012/04/17 15:24:15, fwereade wrote:
> s/have not recognised/failed to recognise/
Done.
https://codereview.appspot.com/5970053/diff/2001/state/ssh_test.go
File state/ssh_test.go (right):
https://codereview.appspot.com/5970053/diff/2001/state/ssh_test.go#newcode167
state/ssh_test.go:167: //func (sshSuite) TestSSHConnect(c *C) {
On 2012/04/17 15:24:15, fwereade wrote:
> I like the approach above, but I'd be happier if we were to *also* test
against
> a real ssh executable.
>
> I don't think that test needs the level of sophistication planned here -- just
> hitting the happy path should be enough to verify basic sanity -- but I'm not
> comfortable leaving it out entirely.
me neither - the real test is coming soon, honest!
maybe i have been a bit ambitious - that's probably why it's taking a while. see
what you think when it's ready.
Please take a look. https://codereview.appspot.com/5970053/diff/15001/state/ssh.go File state/ssh.go (right): https://codereview.appspot.com/5970053/diff/15001/state/ssh.go#newcode16 state/ssh.go:16: // These two variables would ...
Please take a look.
https://codereview.appspot.com/5970053/diff/15001/state/ssh.go
File state/ssh.go (right):
https://codereview.appspot.com/5970053/diff/15001/state/ssh.go#newcode16
state/ssh.go:16: // These two variables would be constants but they are varied
On 2012/04/19 04:07:22, niemeyer wrote:
> s/two//
Done.
https://codereview.appspot.com/5970053/diff/15001/state/ssh.go#newcode22
state/ssh.go:22: sshKeyFile string
On 2012/04/19 04:07:22, niemeyer wrote:
> This shouldn't be here. The ssh identity is configurable. Please check the
> Python code and ping me if you'd like to discuss it.
Done.
https://codereview.appspot.com/5970053/diff/15001/state/ssh.go#newcode34
state/ssh.go:34: fwd.Kill(nil)
On 2012/04/19 04:07:22, niemeyer wrote:
> I believe this should be fwd.stop()
Done.
https://codereview.appspot.com/5970053/diff/15001/state/ssh.go#newcode42
state/ssh.go:42: fwd.Wait()
On 2012/04/19 04:07:22, niemeyer wrote:
> That can be fwd.stop()
Done.
https://codereview.appspot.com/5970053/diff/15001/state/ssh.go#newcode63
state/ssh.go:63: remoteHost, remotePort, err := net.SplitHostPort(remoteAddr)
On 2012/04/19 04:07:22, niemeyer wrote:
> Should we have a default for remotePort?
i don't *think* so. i think it's reasonable to expect the remoteAddr to be well
formed - it's not an address coming from the user, after all, and the default is
elsewhere (zkPort in environs/ec2). YMMV.
https://codereview.appspot.com/5970053/diff/15001/state/ssh.go#newcode76
state/ssh.go:76: p, err := fwd.start()
On 2012/04/19 04:07:22, niemeyer wrote:
> Would you mind to s/p/proc/? It's not obvious from context.
Done.
https://codereview.appspot.com/5970053/diff/15001/state/ssh.go#newcode166
state/ssh.go:166: // TODO how does the user specify a particular ssh identity?
(IdentityFile?)
On 2012/04/19 04:07:22, niemeyer wrote:
> Nope. Please check the Python side of things. Should be easy to follow if you
> start from the forwarder.
Done.
https://codereview.appspot.com/5970053/diff/15001/state/ssh.go#newcode179
state/ssh.go:179: c := exec.Command(
On 2012/04/19 04:07:22, niemeyer wrote:
> This begs to be a single line.
done (a hang over from when all the args were specified in line)
https://codereview.appspot.com/5970053/diff/15001/state/ssh.go#newcode201
state/ssh.go:201: go func() {
On 2012/04/19 04:07:22, niemeyer wrote:
> defer close just in case?
just in case of what? i'm not sure that it's strictly legal to close twice, and
the output will be closed when the forwarder is stopped. if the forwarder isn't
stopped, it's an error anyway and is entitled to leak. in the end, the finaliser
will close it in that case.
https://codereview.appspot.com/5970053/diff/15001/state/ssh.go#newcode211
state/ssh.go:211: }
On 2012/04/19 04:07:22, niemeyer wrote:
> We don't need stripNewline:
>
> line = strings.TrimRight(line, "\r\n")
thanks. i'd forgotten about TrimRight.
https://codereview.appspot.com/5970053/diff/15001/state/ssh.go#newcode277
state/ssh.go:277: err.msg = "Invalid SSH key: " + err.msg
On 2012/04/19 04:07:22, niemeyer wrote:
> Modifying the real SSH message seems unhelpful and perhaps misleading
depending
> on what's inside err.msg.
i took these heuristics directly from the python code. the ssh message is indeed
misleading in this context (it just says "Permission denied" without mentioning
anything about keys - sample message: "Permission denied
(publickey,keyboard-interactive).")
the forwarding error is more of a marginal case. example error: "channel 3: open
failed: connect failed: Connection refused". i'll lose the "SSH forwarding
error" in that case, as it's moderately self-explanatory.