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 }