golang.org/x/build@v0.0.0-20240506185731-218518f32b70/kubernetes/dialer.go (about)

     1  // Copyright 2017 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package kubernetes
     6  
     7  import (
     8  	"context"
     9  	"fmt"
    10  	"math/rand"
    11  	"net"
    12  	"strconv"
    13  	"strings"
    14  	"time"
    15  )
    16  
    17  var dialRand = rand.New(rand.NewSource(time.Now().UnixNano()))
    18  
    19  // DialService connects to the named service. The service must have only one
    20  // port. For multi-port services, use DialServicePort.
    21  func (c *Client) DialService(ctx context.Context, serviceName string) (net.Conn, error) {
    22  	return c.DialServicePort(ctx, serviceName, "")
    23  }
    24  
    25  // DialServicePort connects to the named port on the named service.
    26  // If portName is the empty string, the service must have exactly 1 port.
    27  func (c *Client) DialServicePort(ctx context.Context, serviceName, portName string) (net.Conn, error) {
    28  	// TODO: cache the result of GetServiceEndpoints, at least for
    29  	// a few seconds, to rate-limit calls to the master?
    30  	eps, err := c.GetServiceEndpoints(ctx, serviceName, portName)
    31  	if err != nil {
    32  		return nil, err
    33  	}
    34  	if len(eps) == 0 {
    35  		return nil, fmt.Errorf("no endpoints found for service %q", serviceName)
    36  	}
    37  	if portName == "" {
    38  		firstName := eps[0].PortName
    39  		for _, p := range eps[1:] {
    40  			if p.PortName != firstName {
    41  				return nil, fmt.Errorf("unspecified port name for DialServicePort is ambiguous for service %q (mix of %q, %q, ...)", serviceName, firstName, p.PortName)
    42  			}
    43  		}
    44  	}
    45  	ep := eps[dialRand.Intn(len(eps))]
    46  	var dialer net.Dialer
    47  	return dialer.DialContext(ctx, strings.ToLower(ep.Protocol), net.JoinHostPort(ep.IP, strconv.Itoa(ep.Port)))
    48  }
    49  
    50  func (c *Client) DialPod(ctx context.Context, podName string, port int) (net.Conn, error) {
    51  	status, err := c.PodStatus(ctx, podName)
    52  	if err != nil {
    53  		return nil, fmt.Errorf("PodStatus of %q: %v", podName, err)
    54  	}
    55  	if status.Phase != "Running" {
    56  		return nil, fmt.Errorf("pod %q in state %q", podName, status.Phase)
    57  	}
    58  	var dialer net.Dialer
    59  	return dialer.DialContext(ctx, "tcp", net.JoinHostPort(status.PodIP, strconv.Itoa(port)))
    60  }