172 lines
3.5 KiB
Go
172 lines
3.5 KiB
Go
package port
|
|
|
|
import (
|
|
"strconv"
|
|
"strings"
|
|
|
|
v1 "k8s.io/api/core/v1"
|
|
"k8s.io/apimachinery/pkg/util/intstr"
|
|
)
|
|
|
|
// ContainerPortSpecs represents a container exposed ports.
|
|
type ContainerPortSpecs []ContainerPortSpec
|
|
|
|
func (c ContainerPortSpecs) Dump() string {
|
|
ss := make([]string, 0, len(c))
|
|
for _, spec := range c {
|
|
ss = append(ss, spec.String())
|
|
}
|
|
|
|
return strings.Join(ss, "\n")
|
|
}
|
|
|
|
// InSpecs checks if given port matches a spec.
|
|
func (c ContainerPortSpecs) MatchSpec(s string) bool {
|
|
// Skip validation if No port are exposed or no container port spec.
|
|
if len(c) == 0 || !strings.Contains(s, "::") {
|
|
return true
|
|
}
|
|
for _, spec := range c {
|
|
if spec.MatchSpec(s) {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// ToTunnels convert port specs to tunnels.
|
|
func (c ContainerPortSpecs) ToTunnels(address string) PortTunnels {
|
|
tt := make(PortTunnels, 0, len(c))
|
|
for _, spec := range c {
|
|
tt = append(tt, spec.ToTunnel(address))
|
|
}
|
|
|
|
return tt
|
|
}
|
|
|
|
// Find finds a matching container port.
|
|
func (c ContainerPortSpecs) Find(pf *PFAnn) (ContainerPortSpec, bool) {
|
|
for _, spec := range c {
|
|
if spec.Match(pf) {
|
|
return spec, true
|
|
}
|
|
}
|
|
|
|
return ContainerPortSpec{}, false
|
|
}
|
|
|
|
// Match checks if container ports match a pf annotation.
|
|
func (c ContainerPortSpecs) Match(pf *PFAnn) bool {
|
|
for _, spec := range c {
|
|
if spec.Match(pf) {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func (c ContainerPortSpecs) MatchAnnotations(s string) PFAnns {
|
|
pfs, err := ParsePFs(s)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
|
|
mm := make(PFAnns, 0, len(c))
|
|
for _, pf := range pfs {
|
|
if pf.Match(c) {
|
|
mm = append(mm, pf)
|
|
}
|
|
}
|
|
|
|
return mm
|
|
}
|
|
|
|
// FromContainerPorts hydrates from a pod container specification.
|
|
func FromContainerPorts(co string, pp []v1.ContainerPort) ContainerPortSpecs {
|
|
specs := make(ContainerPortSpecs, 0, len(pp))
|
|
for _, p := range pp {
|
|
if p.Protocol != v1.ProtocolTCP {
|
|
continue
|
|
}
|
|
specs = append(specs, NewPortSpec(co, p.Name, p.ContainerPort))
|
|
}
|
|
|
|
return specs
|
|
}
|
|
|
|
// ContainerPortSpec represents a container port specification.
|
|
type ContainerPortSpec struct {
|
|
Container string
|
|
PortName string
|
|
PortNum string
|
|
}
|
|
|
|
// NewPortSpec returns a new instance.
|
|
func NewPortSpec(co, portName string, port int32) ContainerPortSpec {
|
|
return ContainerPortSpec{
|
|
Container: co,
|
|
PortName: portName,
|
|
PortNum: strconv.Itoa(int(port)),
|
|
}
|
|
}
|
|
|
|
func (c ContainerPortSpec) MatchSpec(s string) bool {
|
|
tokens := strings.Split(s, "::")
|
|
if len(tokens) < 2 {
|
|
return false
|
|
}
|
|
|
|
return tokens[0] == c.Container && tokens[1] == c.PortNum
|
|
}
|
|
|
|
func (c ContainerPortSpec) ToTunnel(address string) PortTunnel {
|
|
return PortTunnel{
|
|
Address: address,
|
|
LocalPort: c.PortNum,
|
|
ContainerPort: c.PortNum,
|
|
}
|
|
}
|
|
|
|
func (c ContainerPortSpec) Port() intstr.IntOrString {
|
|
if c.PortName != "" {
|
|
return intstr.Parse(c.PortName)
|
|
}
|
|
|
|
return intstr.Parse(c.PortNum)
|
|
}
|
|
|
|
func (c ContainerPortSpec) ToPFAnn() *PFAnn {
|
|
return &PFAnn{
|
|
Container: c.Container,
|
|
ContainerPort: c.Port(),
|
|
LocalPort: c.PortNum,
|
|
}
|
|
}
|
|
|
|
// Match checks if the container spec matches an annotation.
|
|
func (c ContainerPortSpec) Match(ann *PFAnn) bool {
|
|
if c.Container != ann.Container {
|
|
return false
|
|
}
|
|
|
|
switch ann.ContainerPort.Type {
|
|
case intstr.String:
|
|
return c.PortName == ann.ContainerPort.String()
|
|
case intstr.Int:
|
|
return c.PortNum == ann.ContainerPort.String()
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
// String dumps spec to string.
|
|
func (c ContainerPortSpec) String() string {
|
|
s := c.Container + "::" + c.PortNum
|
|
if c.PortName != "" {
|
|
s += "(" + c.PortName + ")"
|
|
}
|
|
return s
|
|
}
|