From 2735efd5d772bc20b5d31e90e396fead6481fbff Mon Sep 17 00:00:00 2001 From: Alex Ellis Date: Thu, 15 Aug 2019 14:40:03 +0100 Subject: [PATCH] Split out ssh package Signed-off-by: Alex Ellis --- pkg/cmd/install.go | 80 ++------------------------------------- pkg/ssh/ssh.go | 93 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+), 77 deletions(-) create mode 100644 pkg/ssh/ssh.go diff --git a/pkg/cmd/install.go b/pkg/cmd/install.go index 3c0a93e7..61a04d70 100644 --- a/pkg/cmd/install.go +++ b/pkg/cmd/install.go @@ -1,14 +1,13 @@ package cmd import ( - "bytes" "fmt" - "io" "io/ioutil" - "os" "path/filepath" "strings" + kssh "github.com/alexellis/k3sup/pkg/ssh" + homedir "github.com/mitchellh/go-homedir" "github.com/pkg/errors" "github.com/spf13/cobra" @@ -57,7 +56,7 @@ func MakeInstall() *cobra.Command { } address := fmt.Sprintf("%s:%d", ip.String(), port) - operator, err := NewSSHOperator(address, config) + operator, err := kssh.NewSSHOperator(address, config) if err != nil { return errors.Wrapf(err, "unable to connect to %s over ssh", address) @@ -92,8 +91,6 @@ func MakeInstall() *cobra.Command { kubeconfig := strings.Replace(string(res.StdOut), "localhost", ip.String(), -1) - fmt.Println(res) - writeErr := ioutil.WriteFile(absPath, []byte(kubeconfig), 0600) if writeErr != nil { return writeErr @@ -134,74 +131,3 @@ func loadPublickey(path string) ssh.AuthMethod { } return ssh.PublicKeys(signer) } - -type commandRes struct { - StdOut []byte - StdErr []byte -} - -func executeCommand(cmd string) (commandRes, error) { - - return commandRes{}, nil -} - -type SSHOperator struct { - conn *ssh.Client -} - -func (s *SSHOperator) Close() error { - - return s.conn.Close() -} - -func NewSSHOperator(address string, config *ssh.ClientConfig) (*SSHOperator, error) { - conn, err := ssh.Dial("tcp", address, config) - if err != nil { - return nil, err - } - - operator := SSHOperator{ - conn: conn, - } - - return &operator, nil -} - -func (s *SSHOperator) Execute(command string) (commandRes, error) { - - sess, err := s.conn.NewSession() - if err != nil { - return commandRes{}, err - } - - defer sess.Close() - - sessStdOut, err := sess.StdoutPipe() - if err != nil { - return commandRes{}, err - } - - output := bytes.Buffer{} - - stdOutWriter := io.MultiWriter(os.Stdout, &output) - go io.Copy(stdOutWriter, sessStdOut) - - sessStderr, err := sess.StderrPipe() - if err != nil { - return commandRes{}, err - } - - errorOutput := bytes.Buffer{} - stdErrWriter := io.MultiWriter(os.Stderr, &errorOutput) - go io.Copy(stdErrWriter, sessStderr) - - err = sess.Run(command) - if err != nil { - return commandRes{}, err - } - - return commandRes{ - StdErr: errorOutput.Bytes(), - StdOut: output.Bytes(), - }, nil -} diff --git a/pkg/ssh/ssh.go b/pkg/ssh/ssh.go new file mode 100644 index 00000000..cc3fb14c --- /dev/null +++ b/pkg/ssh/ssh.go @@ -0,0 +1,93 @@ +package ssh + +import ( + "bytes" + "io" + "os" + "sync" + + "golang.org/x/crypto/ssh" +) + +type SSHOperator struct { + conn *ssh.Client +} + +func (s *SSHOperator) Close() error { + + return s.conn.Close() +} + +func NewSSHOperator(address string, config *ssh.ClientConfig) (*SSHOperator, error) { + conn, err := ssh.Dial("tcp", address, config) + if err != nil { + return nil, err + } + + operator := SSHOperator{ + conn: conn, + } + + return &operator, nil +} + +func (s *SSHOperator) Execute(command string) (commandRes, error) { + + sess, err := s.conn.NewSession() + if err != nil { + return commandRes{}, err + } + + defer sess.Close() + + sessStdOut, err := sess.StdoutPipe() + if err != nil { + return commandRes{}, err + } + + output := bytes.Buffer{} + + wg := sync.WaitGroup{} + + stdOutWriter := io.MultiWriter(os.Stdout, &output) + wg.Add(1) + go func() { + io.Copy(stdOutWriter, sessStdOut) + wg.Done() + }() + sessStderr, err := sess.StderrPipe() + if err != nil { + return commandRes{}, err + } + + errorOutput := bytes.Buffer{} + stdErrWriter := io.MultiWriter(os.Stderr, &errorOutput) + wg.Add(1) + go func() { + io.Copy(stdErrWriter, sessStderr) + wg.Done() + }() + + err = sess.Run(command) + + wg.Wait() + + if err != nil { + return commandRes{}, err + } + + return commandRes{ + StdErr: errorOutput.Bytes(), + StdOut: output.Bytes(), + }, nil +} + +type commandRes struct { + StdOut []byte + StdErr []byte +} + +func executeCommand(cmd string) (commandRes, error) { + + return commandRes{}, nil +}