-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1014 from AkihiroSuda/connhelper-sshonly
support SSH connection
- Loading branch information
Showing
21 changed files
with
644 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
package system | ||
|
||
import ( | ||
"context" | ||
"io" | ||
"os" | ||
|
||
"github.com/docker/cli/cli" | ||
"github.com/docker/cli/cli/command" | ||
"github.com/pkg/errors" | ||
"github.com/sirupsen/logrus" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
// newDialStdioCommand creates a new cobra.Command for `docker system dial-stdio` | ||
func newDialStdioCommand(dockerCli command.Cli) *cobra.Command { | ||
cmd := &cobra.Command{ | ||
Use: "dial-stdio", | ||
Short: "Proxy the stdio stream to the daemon connection. Should not be invoked manually.", | ||
Args: cli.NoArgs, | ||
Hidden: true, | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
return runDialStdio(dockerCli) | ||
}, | ||
} | ||
return cmd | ||
} | ||
|
||
func runDialStdio(dockerCli command.Cli) error { | ||
ctx, cancel := context.WithCancel(context.Background()) | ||
defer cancel() | ||
dialer := dockerCli.Client().Dialer() | ||
conn, err := dialer(ctx) | ||
if err != nil { | ||
return errors.Wrap(err, "failed to open the raw stream connection") | ||
} | ||
connHalfCloser, ok := conn.(halfCloser) | ||
if !ok { | ||
return errors.New("the raw stream connection does not implement halfCloser") | ||
} | ||
stdin2conn := make(chan error) | ||
conn2stdout := make(chan error) | ||
go func() { | ||
stdin2conn <- copier(connHalfCloser, &halfReadCloserWrapper{os.Stdin}, "stdin to stream") | ||
}() | ||
go func() { | ||
conn2stdout <- copier(&halfWriteCloserWrapper{os.Stdout}, connHalfCloser, "stream to stdout") | ||
}() | ||
select { | ||
case err = <-stdin2conn: | ||
if err != nil { | ||
return err | ||
} | ||
// wait for stdout | ||
err = <-conn2stdout | ||
case err = <-conn2stdout: | ||
// return immediately without waiting for stdin to be closed. | ||
// (stdin is never closed when tty) | ||
} | ||
return err | ||
} | ||
|
||
func copier(to halfWriteCloser, from halfReadCloser, debugDescription string) error { | ||
defer func() { | ||
if err := from.CloseRead(); err != nil { | ||
logrus.Errorf("error while CloseRead (%s): %v", debugDescription, err) | ||
} | ||
if err := to.CloseWrite(); err != nil { | ||
logrus.Errorf("error while CloseWrite (%s): %v", debugDescription, err) | ||
} | ||
}() | ||
if _, err := io.Copy(to, from); err != nil { | ||
return errors.Wrapf(err, "error while Copy (%s)", debugDescription) | ||
} | ||
return nil | ||
} | ||
|
||
type halfReadCloser interface { | ||
io.Reader | ||
CloseRead() error | ||
} | ||
|
||
type halfWriteCloser interface { | ||
io.Writer | ||
CloseWrite() error | ||
} | ||
|
||
type halfCloser interface { | ||
halfReadCloser | ||
halfWriteCloser | ||
} | ||
|
||
type halfReadCloserWrapper struct { | ||
io.ReadCloser | ||
} | ||
|
||
func (x *halfReadCloserWrapper) CloseRead() error { | ||
return x.Close() | ||
} | ||
|
||
type halfWriteCloserWrapper struct { | ||
io.WriteCloser | ||
} | ||
|
||
func (x *halfWriteCloserWrapper) CloseWrite() error { | ||
return x.Close() | ||
} |
Oops, something went wrong.