github.com/thajeztah/cli@v0.0.0-20240223162942-dc6bfac81a8b/cli/connhelper/ssh/ssh.go (about) 1 // Package ssh provides the connection helper for ssh:// URL. 2 package ssh 3 4 import ( 5 "net/url" 6 7 "github.com/pkg/errors" 8 ) 9 10 // ParseURL parses URL 11 func ParseURL(daemonURL string) (*Spec, error) { 12 u, err := url.Parse(daemonURL) 13 if err != nil { 14 return nil, err 15 } 16 if u.Scheme != "ssh" { 17 return nil, errors.Errorf("expected scheme ssh, got %q", u.Scheme) 18 } 19 20 var sp Spec 21 22 if u.User != nil { 23 sp.User = u.User.Username() 24 if _, ok := u.User.Password(); ok { 25 return nil, errors.New("plain-text password is not supported") 26 } 27 } 28 sp.Host = u.Hostname() 29 if sp.Host == "" { 30 return nil, errors.Errorf("no host specified") 31 } 32 sp.Port = u.Port() 33 sp.Path = u.Path 34 if u.RawQuery != "" { 35 return nil, errors.Errorf("extra query after the host: %q", u.RawQuery) 36 } 37 if u.Fragment != "" { 38 return nil, errors.Errorf("extra fragment after the host: %q", u.Fragment) 39 } 40 return &sp, err 41 } 42 43 // Spec of SSH URL 44 type Spec struct { 45 User string 46 Host string 47 Port string 48 Path string 49 } 50 51 // Args returns args except "ssh" itself combined with optional additional command args 52 func (sp *Spec) Args(add ...string) []string { 53 var args []string 54 if sp.User != "" { 55 args = append(args, "-l", sp.User) 56 } 57 if sp.Port != "" { 58 args = append(args, "-p", sp.Port) 59 } 60 args = append(args, "--", sp.Host) 61 args = append(args, add...) 62 return args 63 }