2017-01-31 23:31:07 +03:00
|
|
|
// Copyright 2017 The Go Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package kubernetes
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
2017-02-10 01:41:29 +03:00
|
|
|
"math/rand"
|
2017-01-31 23:31:07 +03:00
|
|
|
"net"
|
|
|
|
"strconv"
|
2017-02-10 01:41:29 +03:00
|
|
|
"strings"
|
|
|
|
"time"
|
2017-01-31 23:31:07 +03:00
|
|
|
)
|
|
|
|
|
2017-02-10 01:41:29 +03:00
|
|
|
var dialRand = rand.New(rand.NewSource(time.Now().UnixNano()))
|
|
|
|
|
|
|
|
// DialService connects to the named service. The service must have only one
|
|
|
|
// port. For multi-port services, use DialServicePort.
|
|
|
|
func (c *Client) DialService(ctx context.Context, serviceName string) (net.Conn, error) {
|
|
|
|
return c.DialServicePort(ctx, serviceName, "")
|
2017-01-31 23:31:07 +03:00
|
|
|
}
|
|
|
|
|
2017-02-10 01:41:29 +03:00
|
|
|
// DialServicePort connects to the named port on the named service.
|
|
|
|
// If portName is the empty string, the service must have exactly 1 port.
|
|
|
|
func (c *Client) DialServicePort(ctx context.Context, serviceName, portName string) (net.Conn, error) {
|
|
|
|
// TODO: cache the result of GetServiceEndpoints, at least for
|
|
|
|
// a few seconds, to rate-limit calls to the master?
|
|
|
|
eps, err := c.GetServiceEndpoints(ctx, serviceName, portName)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if len(eps) == 0 {
|
|
|
|
return nil, fmt.Errorf("no endpoints found for service %q", serviceName)
|
|
|
|
}
|
|
|
|
if portName == "" {
|
|
|
|
firstName := eps[0].PortName
|
|
|
|
for _, p := range eps[1:] {
|
|
|
|
if p.PortName != firstName {
|
|
|
|
return nil, fmt.Errorf("unspecified port name for DialServicePort is ambiguous for service %q (mix of %q, %q, ...)", serviceName, firstName, p.PortName)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ep := eps[dialRand.Intn(len(eps))]
|
|
|
|
var dialer net.Dialer
|
|
|
|
return dialer.DialContext(ctx, strings.ToLower(ep.Protocol), net.JoinHostPort(ep.IP, strconv.Itoa(ep.Port)))
|
2017-01-31 23:31:07 +03:00
|
|
|
}
|
|
|
|
|
2017-02-10 01:41:29 +03:00
|
|
|
func (c *Client) DialPod(ctx context.Context, podName string, port int) (net.Conn, error) {
|
|
|
|
status, err := c.PodStatus(ctx, podName)
|
2017-01-31 23:31:07 +03:00
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("PodStatus of %q: %v", podName, err)
|
|
|
|
}
|
|
|
|
if status.Phase != "Running" {
|
|
|
|
return nil, fmt.Errorf("pod %q in state %q", podName, status.Phase)
|
|
|
|
}
|
|
|
|
var dialer net.Dialer
|
|
|
|
return dialer.DialContext(ctx, "tcp", net.JoinHostPort(status.PodIP, strconv.Itoa(port)))
|
|
|
|
}
|