17170: Attempt tunnel setup before exec()ing ssh client.
authorTom Clegg <tom@curii.com>
Tue, 26 Jan 2021 20:23:37 +0000 (15:23 -0500)
committerTom Clegg <tom@curii.com>
Tue, 26 Jan 2021 20:28:09 +0000 (15:28 -0500)
Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tom@curii.com>

cmd/arvados-client/container_gateway.go

index a638000ae625e89d56f4784702a0250570045265..2d6fd5eec2a54addb75490894ae0edd9085d3e72 100644 (file)
@@ -5,6 +5,7 @@
 package main
 
 import (
+       "bytes"
        "context"
        "flag"
        "fmt"
@@ -52,6 +53,26 @@ Options:
        }
        sshargs := f.Args()[1:]
 
+       // Try setting up a tunnel, and exit right away if it
+       // fails. This tunnel won't get used -- we'll set up a new
+       // tunnel when running as SSH client's ProxyCommand child --
+       // but in most cases where the real tunnel setup would fail,
+       // we catch the problem earlier here. This makes it less
+       // likely that an error message about tunnel setup will get
+       // hidden behind noisy errors from SSH client like this:
+       //
+       // [useful tunnel setup error message here]
+       // kex_exchange_identification: Connection closed by remote host
+       // Connection closed by UNKNOWN port 65535
+       // exit status 255
+       exitcode := connectSSHCommand{}.RunCommand(
+               "arvados-client connect-ssh",
+               []string{"-detach-keys=" + *detachKeys, "-probe-only=true", target},
+               &bytes.Buffer{}, &bytes.Buffer{}, stderr)
+       if exitcode != 0 {
+               return exitcode
+       }
+
        selfbin, err := os.Readlink("/proc/self/exe")
        if err != nil {
                fmt.Fprintln(stderr, err)
@@ -92,6 +113,7 @@ Options:
 `)
                f.PrintDefaults()
        }
+       probeOnly := f.Bool("probe-only", false, "do not transfer IO, just exit 0 immediately if tunnel setup succeeds")
        detachKeys := f.String("detach-keys", "", "set detach key sequence, as in docker-attach(1)")
        if err := f.Parse(args); err != nil {
                fmt.Fprintln(stderr, err)
@@ -148,6 +170,10 @@ Options:
        }
        defer sshconn.Conn.Close()
 
+       if *probeOnly {
+               return 0
+       }
+
        ctx, cancel := context.WithCancel(context.Background())
        go func() {
                defer cancel()