istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pkg/test/framework/components/echo/port.go (about)

     1  // Copyright Istio Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package echo
    16  
    17  import (
    18  	"fmt"
    19  	"reflect"
    20  
    21  	"istio.io/istio/pkg/config/protocol"
    22  	"istio.io/istio/pkg/test/echo/common/scheme"
    23  )
    24  
    25  // NoServicePort defines the ServicePort value for a Port that is a workload-only port.
    26  const NoServicePort = -1
    27  
    28  // Port exposed by an Echo Instance
    29  type Port struct {
    30  	// Name of this port
    31  	Name string
    32  
    33  	// Protocol to be used for the port.
    34  	Protocol protocol.Instance
    35  
    36  	// ServicePort number where the service can be reached. Does not necessarily
    37  	// map to the corresponding port numbers for the instances behind the
    38  	// service. If zero (default), a service port will be automatically generated for this port.
    39  	// If set to NoServicePort, this port will be assumed to be a workload-only port.
    40  	ServicePort int
    41  
    42  	// WorkloadPort number where the workload is listening for connections.
    43  	// This need not be the same as the ServicePort where the service is accessed.
    44  	WorkloadPort int
    45  
    46  	// TLS determines whether the connection will be plain text or TLS. By default this is false (plain text).
    47  	TLS bool
    48  
    49  	// ServerFirst determines whether the port will use server first communication, meaning the client will not send the first byte.
    50  	ServerFirst bool
    51  
    52  	// InstanceIP determines if echo will listen on the instance IP; otherwise, it will listen on wildcard
    53  	InstanceIP bool
    54  
    55  	// LocalhostIP determines if echo will listen on the localhost IP; otherwise, it will listen on wildcard
    56  	LocalhostIP bool
    57  }
    58  
    59  // IsWorkloadOnly returns true if there is no service port specified for this Port.
    60  func (p Port) IsWorkloadOnly() bool {
    61  	return p.ServicePort == NoServicePort
    62  }
    63  
    64  // Scheme infers the scheme to be used based on the Protocol.
    65  func (p Port) Scheme() (scheme.Instance, error) {
    66  	switch p.Protocol {
    67  	case protocol.GRPC, protocol.GRPCWeb, protocol.HTTP2:
    68  		return scheme.GRPC, nil
    69  	case protocol.HTTP:
    70  		return scheme.HTTP, nil
    71  	case protocol.HTTPS:
    72  		return scheme.HTTPS, nil
    73  	case protocol.TCP:
    74  		return scheme.TCP, nil
    75  	default:
    76  		return "", fmt.Errorf("failed creating call for port %s: unsupported protocol %s",
    77  			p.Name, p.Protocol)
    78  	}
    79  }
    80  
    81  type Ports []Port
    82  
    83  func (ps Ports) Contains(p Port) bool {
    84  	for _, port := range ps {
    85  		if reflect.DeepEqual(port, p) {
    86  			return true
    87  		}
    88  	}
    89  	return false
    90  }
    91  
    92  // ForName returns the first port found with the given name.
    93  func (ps Ports) ForName(name string) (Port, bool) {
    94  	for _, port := range ps {
    95  		if name == port.Name {
    96  			return port, true
    97  		}
    98  	}
    99  	return Port{}, false
   100  }
   101  
   102  // MustForName calls ForName and panics if not found.
   103  func (ps Ports) MustForName(name string) Port {
   104  	p, found := ps.ForName(name)
   105  	if !found {
   106  		panic("port does not exist for name " + name)
   107  	}
   108  	return p
   109  }
   110  
   111  // ForProtocol returns the first port found with the given protocol.
   112  func (ps Ports) ForProtocol(protocol protocol.Instance) (Port, bool) {
   113  	for _, p := range ps {
   114  		if p.Protocol == protocol {
   115  			return p, true
   116  		}
   117  	}
   118  	return Port{}, false
   119  }
   120  
   121  // ForServicePort returns the first port found with the given service port.
   122  func (ps Ports) ForServicePort(port int) (Port, bool) {
   123  	for _, p := range ps {
   124  		if p.ServicePort == port {
   125  			return p, true
   126  		}
   127  	}
   128  	return Port{}, false
   129  }
   130  
   131  // MustForProtocol calls ForProtocol and panics if not found.
   132  func (ps Ports) MustForProtocol(protocol protocol.Instance) Port {
   133  	p, found := ps.ForProtocol(protocol)
   134  	if !found {
   135  		panic("port does not exist for protocol " + protocol)
   136  	}
   137  	return p
   138  }
   139  
   140  // GetServicePorts returns the subset of ports that contain a service port.
   141  func (ps Ports) GetServicePorts() Ports {
   142  	out := make(Ports, 0, len(ps))
   143  	for _, p := range ps {
   144  		if !p.IsWorkloadOnly() {
   145  			out = append(out, p)
   146  		}
   147  	}
   148  	return out
   149  }
   150  
   151  // GetWorkloadOnlyPorts returns the subset of ports that do not contain a service port.
   152  func (ps Ports) GetWorkloadOnlyPorts() Ports {
   153  	out := make(Ports, 0, len(ps))
   154  	for _, p := range ps {
   155  		if p.IsWorkloadOnly() {
   156  			out = append(out, p)
   157  		}
   158  	}
   159  	return out
   160  }