github.com/AliyunContainerService/cli@v0.0.0-20181009023821-814ced4b30d0/cli/connhelper/ssh/ssh.go (about) 1 // Package ssh provides the connection helper for ssh:// URL. 2 // Requires Docker 18.09 or later on the remote host. 3 package ssh 4 5 import ( 6 "net/url" 7 8 "github.com/pkg/errors" 9 ) 10 11 // New returns cmd and its args 12 func New(daemonURL string) (string, []string, error) { 13 sp, err := parseSSHURL(daemonURL) 14 if err != nil { 15 return "", nil, err 16 } 17 return "ssh", append(sp.Args(), []string{"--", "docker", "system", "dial-stdio"}...), nil 18 } 19 20 func parseSSHURL(daemonURL string) (*sshSpec, error) { 21 u, err := url.Parse(daemonURL) 22 if err != nil { 23 return nil, err 24 } 25 if u.Scheme != "ssh" { 26 return nil, errors.Errorf("expected scheme ssh, got %s", u.Scheme) 27 } 28 29 var sp sshSpec 30 31 if u.User != nil { 32 sp.user = u.User.Username() 33 if _, ok := u.User.Password(); ok { 34 return nil, errors.New("ssh helper does not accept plain-text password") 35 } 36 } 37 sp.host = u.Hostname() 38 if sp.host == "" { 39 return nil, errors.Errorf("host is not specified") 40 } 41 sp.port = u.Port() 42 if u.Path != "" { 43 return nil, errors.Errorf("extra path: %s", u.Path) 44 } 45 if u.RawQuery != "" { 46 return nil, errors.Errorf("extra query: %s", u.RawQuery) 47 } 48 if u.Fragment != "" { 49 return nil, errors.Errorf("extra fragment: %s", u.Fragment) 50 } 51 return &sp, err 52 } 53 54 type sshSpec struct { 55 user string 56 host string 57 port string 58 } 59 60 func (sp *sshSpec) Args() []string { 61 var args []string 62 if sp.user != "" { 63 args = append(args, "-l", sp.user) 64 } 65 if sp.port != "" { 66 args = append(args, "-p", sp.port) 67 } 68 args = append(args, sp.host) 69 return args 70 }