github.com/telepresenceio/telepresence/v2@v2.20.0-pro.6.0.20240517030216-236ea954e789/pkg/agentconfig/portidentifier.go (about)

     1  package agentconfig
     2  
     3  import (
     4  	"fmt"
     5  	"strconv"
     6  	"strings"
     7  
     8  	core "k8s.io/api/core/v1"
     9  	"k8s.io/apimachinery/pkg/util/validation"
    10  )
    11  
    12  // PortIdentifier identifies a port (service or container) unambiguously using
    13  // the notation <name or number>/<protocol>. A named port will always be identified
    14  // using the name and the protocol will only be appended when it is not TCP.
    15  type PortIdentifier string
    16  
    17  // ValidatePort validates a port string. An error is returned if the string isn't a
    18  // number between 1 and 65535 or a DNS_LABEL.
    19  func ValidatePort(s string) error {
    20  	_, err := ParseNumericPort(s)
    21  	if err == ErrNotInteger {
    22  		err = nil
    23  		if errs := validation.IsDNS1035Label(s); len(errs) > 0 {
    24  			err = fmt.Errorf(strings.Join(errs, " and "))
    25  		}
    26  	}
    27  	return err
    28  }
    29  
    30  // NewPortIdentifier creates a new PortIdentifier from a protocol and a string that
    31  // is either a name or a number. An error is returned if the protocol is unsupported,
    32  // if a port number is not between 1 and 65535, or if the name isn't a DNS_LABEL.
    33  func NewPortIdentifier(protocol string, portString string) (PortIdentifier, error) {
    34  	if err := ValidatePort(portString); err != nil {
    35  		return "", err
    36  	}
    37  	if protocol != "" {
    38  		pr, err := ParseProtocol(protocol)
    39  		if err != nil {
    40  			return "", err
    41  		}
    42  		portString += string([]byte{ProtoSeparator}) + string(pr)
    43  	}
    44  	return PortIdentifier(portString), nil
    45  }
    46  
    47  // HasProto returns the protocol, and the name or number.
    48  func (spi PortIdentifier) HasProto() bool {
    49  	return strings.IndexByte(string(spi), ProtoSeparator) > 0
    50  }
    51  
    52  // ProtoAndNameOrNumber returns the protocol, and the name or number.
    53  func (spi PortIdentifier) ProtoAndNameOrNumber() (core.Protocol, string, uint16) {
    54  	s := string(spi)
    55  	p := core.ProtocolTCP
    56  	if ix := strings.IndexByte(s, ProtoSeparator); ix > 0 {
    57  		p = core.Protocol(s[ix+1:])
    58  		s = s[0:ix]
    59  	}
    60  	if n, err := strconv.Atoi(s); err == nil {
    61  		return p, "", uint16(n)
    62  	}
    63  	return p, s, 0
    64  }
    65  
    66  func (spi PortIdentifier) String() string {
    67  	return string(spi)
    68  }