github.com/panekj/cli@v0.0.0-20230304125325-467dd2f3797e/cli/connhelper/ssh/ssh.go (about)

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