knative.dev/pkg@v0.0.0-20260602142205-ac97e43f6622/test/ingress/ingress.go (about)

     1  /*
     2  Copyright 2019 The Knative Authors
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package ingress
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"os"
    23  	"strconv"
    24  
    25  	v1 "k8s.io/api/core/v1"
    26  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    27  	"k8s.io/client-go/kubernetes"
    28  )
    29  
    30  const (
    31  	// TODO(tcnghia): These probably shouldn't be hard-coded here?
    32  	istioIngressNamespace = "istio-system"
    33  	istioIngressName      = "istio-ingressgateway"
    34  )
    35  
    36  // GetIngressEndpoint gets the ingress public IP or hostname.
    37  // address - is the endpoint to which we should actually connect.
    38  // portMap - translates the request's port to the port on address to which the caller
    39  //
    40  //	should connect.  This is used when the resolution to address goes through some
    41  //	sort of port-mapping, e.g. Kubernetes node ports.
    42  //
    43  // err - an error when address/portMap cannot be established.
    44  func GetIngressEndpoint(ctx context.Context, kubeClientset kubernetes.Interface, endpointOverride string) (address string, portMap func(string) string, err error) {
    45  	ingressName := istioIngressName
    46  	if gatewayOverride := os.Getenv("GATEWAY_OVERRIDE"); gatewayOverride != "" {
    47  		ingressName = gatewayOverride
    48  	}
    49  	ingressNamespace := istioIngressNamespace
    50  	if gatewayNsOverride := os.Getenv("GATEWAY_NAMESPACE_OVERRIDE"); gatewayNsOverride != "" {
    51  		ingressNamespace = gatewayNsOverride
    52  	}
    53  
    54  	ingress, err := kubeClientset.CoreV1().Services(ingressNamespace).Get(ctx, ingressName, metav1.GetOptions{})
    55  	if err != nil {
    56  		return "", nil, err
    57  	}
    58  
    59  	// If an override is provided, use it
    60  	if endpointOverride != "" {
    61  		return endpointOverride, func(port string) string {
    62  			for _, sp := range ingress.Spec.Ports {
    63  				if strconv.Itoa(int(sp.Port)) == port {
    64  					return strconv.Itoa(int(sp.NodePort))
    65  				}
    66  			}
    67  			return port
    68  		}, nil
    69  	}
    70  	endpoint, err := EndpointFromService(ingress)
    71  	if err != nil {
    72  		return "", nil, err
    73  	}
    74  	return endpoint, func(in string) string { return in }, nil
    75  }
    76  
    77  // EndpointFromService extracts the endpoint from the service's ingress.
    78  func EndpointFromService(svc *v1.Service) (string, error) {
    79  	ingresses := svc.Status.LoadBalancer.Ingress
    80  	if len(ingresses) != 1 {
    81  		return "", fmt.Errorf("expected exactly one ingress load balancer, instead had %d: %v", len(ingresses), ingresses)
    82  	}
    83  	itu := ingresses[0]
    84  
    85  	switch {
    86  	case itu.IP != "":
    87  		return itu.IP, nil
    88  	case itu.Hostname != "":
    89  		return itu.Hostname, nil
    90  	default:
    91  		return "", fmt.Errorf("expected ingress loadbalancer IP or hostname for %s to be set, instead was empty", svc.Name)
    92  	}
    93  }