github.com/pachyderm/pachyderm@v1.13.4/src/client/pkg/grpcutil/addr.go (about)

     1  package grpcutil
     2  
     3  import (
     4  	"fmt"
     5  	"net/url"
     6  	"strconv"
     7  	"strings"
     8  
     9  	"github.com/pachyderm/pachyderm/src/client/pkg/errors"
    10  )
    11  
    12  const (
    13  	// DefaultPachdNodePort is the pachd kubernetes service's default
    14  	// NodePort.Port setting
    15  	DefaultPachdNodePort = 30650
    16  
    17  	// DefaultPachdPort is the pachd kubernetes service's default
    18  	// Port (often used with Pachyderm ELBs)
    19  	DefaultPachdPort = 650
    20  )
    21  
    22  var (
    23  	// ErrNoPachdAddress is returned by ParsePachdAddress when the input is an
    24  	// empty string
    25  	ErrNoPachdAddress = errors.New("no pachd address specified")
    26  	// DefaultPachdAddress is the default PachdAddress that should be used
    27  	// if none is otherwise specified. It's a loopback that should rely on
    28  	// port forwarding.
    29  	DefaultPachdAddress = PachdAddress{
    30  		Secured: false,
    31  		Host:    "0.0.0.0",
    32  		Port:    DefaultPachdNodePort,
    33  	}
    34  )
    35  
    36  // PachdAddress represents a parsed pachd address value
    37  type PachdAddress struct {
    38  	// Secured specifies whether grpcs should be used
    39  	Secured bool
    40  	// Host specifies the pachd address host without the port
    41  	Host string
    42  	// Port specifies the pachd port
    43  	Port uint16
    44  }
    45  
    46  // ParsePachdAddress parses a string into a pachd address, or returns an error
    47  // if it's invalid
    48  func ParsePachdAddress(value string) (*PachdAddress, error) {
    49  	if value == "" {
    50  		return nil, ErrNoPachdAddress
    51  	}
    52  
    53  	if !strings.Contains(value, "://") {
    54  		// append a default scheme if one does not exist, as `url.Parse`
    55  		// doesn't appropriately handle values without one
    56  		value = "grpc://" + value
    57  	}
    58  
    59  	u, err := url.Parse(value)
    60  	if err != nil {
    61  		return nil, errors.Wrapf(err, "could not parse pachd address")
    62  	}
    63  
    64  	switch u.Scheme {
    65  	case "grpc", "grpcs", "http", "https":
    66  	default:
    67  		return nil, errors.Errorf("unrecognized scheme in pachd address: %s", u.Scheme)
    68  	}
    69  
    70  	switch {
    71  	case u.User != nil:
    72  		return nil, errors.New("pachd address should not include login credentials")
    73  	case u.RawQuery != "":
    74  		return nil, errors.New("pachd address should not include a query string")
    75  	case u.Fragment != "":
    76  		return nil, errors.New("pachd address should not include a fragment")
    77  	case u.Path != "":
    78  		return nil, errors.New("pachd address should not include a path")
    79  	}
    80  
    81  	port := uint16(DefaultPachdNodePort)
    82  	if strport := u.Port(); strport != "" {
    83  		maybePort, err := strconv.ParseUint(strport, 10, 16)
    84  		if err != nil {
    85  			return nil, errors.Wrapf(err, "could not parse port in address")
    86  		}
    87  		port = uint16(maybePort)
    88  	}
    89  
    90  	return &PachdAddress{
    91  		Secured: u.Scheme == "grpcs" || u.Scheme == "https",
    92  		Host:    u.Hostname(),
    93  		Port:    port,
    94  	}, nil
    95  }
    96  
    97  // Qualified returns the "fully qualified" address, including the scheme
    98  func (p *PachdAddress) Qualified() string {
    99  	if p.Secured {
   100  		return fmt.Sprintf("grpcs://%s:%d", p.Host, p.Port)
   101  	}
   102  	return fmt.Sprintf("grpc://%s:%d", p.Host, p.Port)
   103  }
   104  
   105  // Hostname returns the host:port combination of the pachd address, without
   106  // the scheme
   107  func (p *PachdAddress) Hostname() string {
   108  	return fmt.Sprintf("%s:%d", p.Host, p.Port)
   109  }