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 }