blob: 9b9aa3e5da353057eb08fe99d061d802531f6521 [file] [log] [blame]
Brad Fitzpatrickadc161a2017-01-31 20:31:07 +00001// 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
5package kubernetes
6
7import (
8 "context"
9 "fmt"
Brad Fitzpatrickb30f5062017-02-09 22:41:29 +000010 "math/rand"
Brad Fitzpatrickadc161a2017-01-31 20:31:07 +000011 "net"
12 "strconv"
Brad Fitzpatrickb30f5062017-02-09 22:41:29 +000013 "strings"
14 "time"
Brad Fitzpatrickadc161a2017-01-31 20:31:07 +000015)
16
Brad Fitzpatrickb30f5062017-02-09 22:41:29 +000017var 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.
21func (c *Client) DialService(ctx context.Context, serviceName string) (net.Conn, error) {
22 return c.DialServicePort(ctx, serviceName, "")
Brad Fitzpatrickadc161a2017-01-31 20:31:07 +000023}
24
Brad Fitzpatrickb30f5062017-02-09 22:41:29 +000025// DialServicePort connects to the named port on the named service.
26// If portName is the empty string, the service must have exactly 1 port.
27func (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)))
Brad Fitzpatrickadc161a2017-01-31 20:31:07 +000048}
49
Brad Fitzpatrickb30f5062017-02-09 22:41:29 +000050func (c *Client) DialPod(ctx context.Context, podName string, port int) (net.Conn, error) {
51 status, err := c.PodStatus(ctx, podName)
Brad Fitzpatrickadc161a2017-01-31 20:31:07 +000052 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}