github.com/jlmeeker/kismatic@v1.10.1-0.20180612190640-57f9005a1f1a/pkg/cli/ssh.go (about) 1 package cli 2 3 import ( 4 "fmt" 5 "io" 6 "strings" 7 8 "github.com/apprenda/kismatic/pkg/ssh" 9 10 "github.com/apprenda/kismatic/pkg/install" 11 "github.com/apprenda/kismatic/pkg/util" 12 "github.com/spf13/cobra" 13 ) 14 15 type sshOpts struct { 16 planFilename string 17 host string 18 pty bool 19 arguments []string 20 } 21 22 // NewCmdSSH returns an ssh shell 23 func NewCmdSSH(out io.Writer) *cobra.Command { 24 opts := &sshOpts{} 25 26 cmd := &cobra.Command{ 27 Use: "ssh HOST [commands]", 28 Short: "ssh into a node in the cluster", 29 Long: `ssh into a node in the cluster 30 31 HOST must be one of the following: 32 - A hostname defined in the plan filepath 33 - An alias: master, etcd, worker, ingress or storage. This will ssh into the first defined node of that type.`, 34 RunE: func(cmd *cobra.Command, args []string) error { 35 if len(args) < 1 { 36 return cmd.Usage() 37 } 38 // get optional arguments 39 if len(args) > 1 { 40 opts.arguments = args[1:] 41 } 42 43 opts.host = args[0] 44 45 planner := &install.FilePlanner{File: opts.planFilename} 46 // Check if plan file exists 47 if !planner.PlanExists() { 48 return planFileNotFoundErr{filename: opts.planFilename} 49 } 50 51 err := doSSH(out, planner, opts) 52 // 130 = terminated by Control-C, so not an actual error 53 if err != nil && !strings.Contains(err.Error(), "130") { 54 return fmt.Errorf("SSH error %q: %v", opts.host, err) 55 } 56 return nil 57 }, 58 } 59 60 cmd.Flags().StringVarP(&opts.planFilename, "plan-file", "f", "kismatic-cluster.yaml", "path to the installation plan file") 61 cmd.Flags().BoolVarP(&opts.pty, "pty", "t", false, "force PTY \"-t\" flag on the SSH connection") 62 63 return cmd 64 } 65 66 func doSSH(out io.Writer, planner install.Planner, opts *sshOpts) error { 67 plan, err := planner.Read() 68 if err != nil { 69 return fmt.Errorf("error reading plan file: %v", err) 70 } 71 72 // find node 73 con, err := plan.GetSSHConnection(opts.host) 74 if err != nil { 75 return err 76 } 77 78 // validate SSH access to node 79 ok, errs := install.ValidateSSHConnection(con, "") 80 if !ok { 81 util.PrintValidationErrors(out, errs) 82 return fmt.Errorf("cannot validate SSH connection to node %q", opts.host) 83 } 84 85 client, err := ssh.NewClient(con.Node.IP, con.SSHConfig.Port, con.SSHConfig.User, con.SSHConfig.Key) 86 if err != nil { 87 return fmt.Errorf("error creating SSH client: %v", err) 88 } 89 90 if err = client.Shell(opts.pty, opts.arguments...); err != nil { 91 return fmt.Errorf("error running command: %v", err) 92 } 93 94 return err 95 }