Use networking to hold network related pkgs

Change names of unclear methods

Use net as pkg name for short
pull/6/head
Harry Zhang 2016-01-06 23:56:41 +08:00 committed by harry
parent 33c72db59c
commit 936a11e775
43 changed files with 687 additions and 626 deletions

View File

@ -53,6 +53,7 @@ import (
"k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/master" "k8s.io/kubernetes/pkg/master"
"k8s.io/kubernetes/pkg/util" "k8s.io/kubernetes/pkg/util"
utilnet "k8s.io/kubernetes/pkg/util/net"
"k8s.io/kubernetes/pkg/util/sets" "k8s.io/kubernetes/pkg/util/sets"
"k8s.io/kubernetes/pkg/util/wait" "k8s.io/kubernetes/pkg/util/wait"
"k8s.io/kubernetes/pkg/volume/empty_dir" "k8s.io/kubernetes/pkg/volume/empty_dir"
@ -153,7 +154,7 @@ func startComponents(firstManifestURL, secondManifestURL string) (string, string
} }
// The caller of master.New should guarantee pulicAddress is properly set // The caller of master.New should guarantee pulicAddress is properly set
hostIP, err := util.ValidPublicAddrForMaster(publicAddress) hostIP, err := utilnet.ChooseBindAddress(publicAddress)
if err != nil { if err != nil {
glog.Fatalf("Unable to find suitable network address.error='%v' . "+ glog.Fatalf("Unable to find suitable network address.error='%v' . "+
"Fail to get a valid public address for master.", err) "Fail to get a valid public address for master.", err)

View File

@ -31,6 +31,7 @@ import (
kubeletclient "k8s.io/kubernetes/pkg/kubelet/client" kubeletclient "k8s.io/kubernetes/pkg/kubelet/client"
"k8s.io/kubernetes/pkg/master/ports" "k8s.io/kubernetes/pkg/master/ports"
"k8s.io/kubernetes/pkg/util" "k8s.io/kubernetes/pkg/util"
utilnet "k8s.io/kubernetes/pkg/util/net"
"github.com/spf13/pflag" "github.com/spf13/pflag"
) )
@ -76,7 +77,7 @@ type APIServer struct {
ServiceAccountKeyFile string ServiceAccountKeyFile string
ServiceAccountLookup bool ServiceAccountLookup bool
ServiceClusterIPRange net.IPNet // TODO: make this a list ServiceClusterIPRange net.IPNet // TODO: make this a list
ServiceNodePortRange util.PortRange ServiceNodePortRange utilnet.PortRange
StorageVersions string StorageVersions string
TokenAuthFile string TokenAuthFile string
} }

View File

@ -51,7 +51,7 @@ import (
"k8s.io/kubernetes/pkg/serviceaccount" "k8s.io/kubernetes/pkg/serviceaccount"
"k8s.io/kubernetes/pkg/storage" "k8s.io/kubernetes/pkg/storage"
etcdstorage "k8s.io/kubernetes/pkg/storage/etcd" etcdstorage "k8s.io/kubernetes/pkg/storage/etcd"
"k8s.io/kubernetes/pkg/util" utilnet "k8s.io/kubernetes/pkg/util/net"
) )
// NewAPIServerCommand creates a *cobra.Command object with default parameters // NewAPIServerCommand creates a *cobra.Command object with default parameters
@ -164,9 +164,9 @@ func Run(s *options.APIServer) error {
// If advertise-address is not specified, use bind-address. If bind-address // If advertise-address is not specified, use bind-address. If bind-address
// is not usable (unset, 0.0.0.0, or loopback), we will use the host's default // is not usable (unset, 0.0.0.0, or loopback), we will use the host's default
// interface as valid public addr for master (see: util#ValidPublicAddrForMaster) // interface as valid public addr for master (see: util/net#ValidPublicAddrForMaster)
if s.AdvertiseAddress == nil || s.AdvertiseAddress.IsUnspecified() { if s.AdvertiseAddress == nil || s.AdvertiseAddress.IsUnspecified() {
hostIP, err := util.ValidPublicAddrForMaster(s.BindAddress) hostIP, err := utilnet.ChooseBindAddress(s.BindAddress)
if err != nil { if err != nil {
glog.Fatalf("Unable to find suitable network address.error='%v' . "+ glog.Fatalf("Unable to find suitable network address.error='%v' . "+
"Try to set the AdvertiseAddress directly or provide a valid BindAddress to fix this.", err) "Try to set the AdvertiseAddress directly or provide a valid BindAddress to fix this.", err)

View File

@ -24,7 +24,7 @@ import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/kubelet/qos" "k8s.io/kubernetes/pkg/kubelet/qos"
"k8s.io/kubernetes/pkg/util" utilnet "k8s.io/kubernetes/pkg/util/net"
"github.com/spf13/pflag" "github.com/spf13/pflag"
) )
@ -42,7 +42,7 @@ type ProxyServerConfig struct {
ResourceContainer string ResourceContainer string
Master string Master string
Kubeconfig string Kubeconfig string
PortRange util.PortRange PortRange utilnet.PortRange
HostnameOverride string HostnameOverride string
ProxyMode string ProxyMode string
IptablesSyncPeriod time.Duration IptablesSyncPeriod time.Duration

View File

@ -43,6 +43,7 @@ import (
"k8s.io/kubernetes/pkg/util" "k8s.io/kubernetes/pkg/util"
utilerrors "k8s.io/kubernetes/pkg/util/errors" utilerrors "k8s.io/kubernetes/pkg/util/errors"
"k8s.io/kubernetes/pkg/util/flushwriter" "k8s.io/kubernetes/pkg/util/flushwriter"
utilnet "k8s.io/kubernetes/pkg/util/net"
"k8s.io/kubernetes/pkg/util/wsstream" "k8s.io/kubernetes/pkg/util/wsstream"
"k8s.io/kubernetes/pkg/version" "k8s.io/kubernetes/pkg/version"
@ -61,7 +62,7 @@ func monitorFilter(action, resource string) restful.FilterFunction {
reqStart := time.Now() reqStart := time.Now()
chain.ProcessFilter(req, res) chain.ProcessFilter(req, res)
httpCode := res.StatusCode() httpCode := res.StatusCode()
metrics.Monitor(&action, &resource, util.GetClient(req.Request), &httpCode, reqStart) metrics.Monitor(&action, &resource, utilnet.GetHTTPClient(req.Request), &httpCode, reqStart)
} }
} }

View File

@ -32,8 +32,8 @@ import (
"k8s.io/kubernetes/pkg/apiserver/metrics" "k8s.io/kubernetes/pkg/apiserver/metrics"
"k8s.io/kubernetes/pkg/httplog" "k8s.io/kubernetes/pkg/httplog"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util"
"k8s.io/kubernetes/pkg/util/httpstream" "k8s.io/kubernetes/pkg/util/httpstream"
"k8s.io/kubernetes/pkg/util/net"
proxyutil "k8s.io/kubernetes/pkg/util/proxy" proxyutil "k8s.io/kubernetes/pkg/util/proxy"
"github.com/golang/glog" "github.com/golang/glog"
@ -56,7 +56,7 @@ func (r *ProxyHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
var apiResource string var apiResource string
var httpCode int var httpCode int
reqStart := time.Now() reqStart := time.Now()
defer metrics.Monitor(&verb, &apiResource, util.GetClient(req), &httpCode, reqStart) defer metrics.Monitor(&verb, &apiResource, net.GetHTTPClient(req), &httpCode, reqStart)
requestInfo, err := r.requestInfoResolver.GetRequestInfo(req) requestInfo, err := r.requestInfoResolver.GetRequestInfo(req)
if err != nil || !requestInfo.IsResourceRequest { if err != nil || !requestInfo.IsResourceRequest {

View File

@ -21,7 +21,7 @@ import (
"k8s.io/kubernetes/pkg/probe" "k8s.io/kubernetes/pkg/probe"
httpprober "k8s.io/kubernetes/pkg/probe/http" httpprober "k8s.io/kubernetes/pkg/probe/http"
"k8s.io/kubernetes/pkg/util" utilnet "k8s.io/kubernetes/pkg/util/net"
"time" "time"
) )
@ -57,7 +57,7 @@ func (server *Server) DoServerCheck(prober httpprober.HTTPProber) (probe.Result,
if server.EnableHTTPS { if server.EnableHTTPS {
scheme = "https" scheme = "https"
} }
url := util.FormatURL(scheme, server.Addr, server.Port, server.Path) url := utilnet.FormatURL(scheme, server.Addr, server.Port, server.Path)
result, data, err := prober.Probe(url, probeTimeOut) result, data, err := prober.Probe(url, probeTimeOut)

View File

@ -29,7 +29,7 @@ import (
"reflect" "reflect"
"runtime" "runtime"
"k8s.io/kubernetes/pkg/util" "k8s.io/kubernetes/pkg/util/net"
) )
// chaosrt provides the ability to perform simulations of HTTP client failures // chaosrt provides the ability to perform simulations of HTTP client failures
@ -88,7 +88,7 @@ func (rt *chaosrt) RoundTrip(req *http.Request) (*http.Response, error) {
return rt.rt.RoundTrip(req) return rt.rt.RoundTrip(req)
} }
var _ = util.RoundTripperWrapper(&chaosrt{}) var _ = net.RoundTripperWrapper(&chaosrt{})
func (rt *chaosrt) WrappedRoundTripper() http.RoundTripper { func (rt *chaosrt) WrappedRoundTripper() http.RoundTripper {
return rt.rt return rt.rt

View File

@ -40,7 +40,7 @@ import (
"k8s.io/kubernetes/pkg/fields" "k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util" "k8s.io/kubernetes/pkg/util/net"
"k8s.io/kubernetes/pkg/util/sets" "k8s.io/kubernetes/pkg/util/sets"
"k8s.io/kubernetes/pkg/watch" "k8s.io/kubernetes/pkg/watch"
watchjson "k8s.io/kubernetes/pkg/watch/json" watchjson "k8s.io/kubernetes/pkg/watch/json"
@ -637,7 +637,7 @@ func (r *Request) Watch() (watch.Interface, error) {
if err != nil { if err != nil {
// The watch stream mechanism handles many common partial data errors, so closed // The watch stream mechanism handles many common partial data errors, so closed
// connections can be retried in many cases. // connections can be retried in many cases.
if util.IsProbableEOF(err) { if net.IsProbableEOF(err) {
return watch.NewEmptyWatch(), nil return watch.NewEmptyWatch(), nil
} }
return nil, err return nil, err

View File

@ -18,7 +18,7 @@ package unversioned
import ( import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/util" "k8s.io/kubernetes/pkg/util/net"
"k8s.io/kubernetes/pkg/watch" "k8s.io/kubernetes/pkg/watch"
) )
@ -103,7 +103,7 @@ func (c *services) ProxyGet(scheme, name, port, path string, params map[string]s
Prefix("proxy"). Prefix("proxy").
Namespace(c.ns). Namespace(c.ns).
Resource("services"). Resource("services").
Name(util.JoinSchemeNamePort(scheme, name, port)). Name(net.JoinSchemeNamePort(scheme, name, port)).
Suffix(path) Suffix(path)
for k, v := range params { for k, v := range params {
request = request.Param(k, v) request = request.Param(k, v)

View File

@ -33,7 +33,7 @@ import (
"golang.org/x/net/context" "golang.org/x/net/context"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/resource" "k8s.io/kubernetes/pkg/api/resource"
"k8s.io/kubernetes/pkg/util" utilnet "k8s.io/kubernetes/pkg/util/net"
) )
const defaultClusterName = "mesos" const defaultClusterName = "mesos"
@ -111,7 +111,7 @@ func newMesosClient(
md detector.Master, md detector.Master,
mesosHttpClientTimeout, stateCacheTTL time.Duration) (*mesosClient, error) { mesosHttpClientTimeout, stateCacheTTL time.Duration) (*mesosClient, error) {
tr := util.SetTransportDefaults(&http.Transport{}) tr := utilnet.SetTransportDefaults(&http.Transport{})
httpClient := &http.Client{ httpClient := &http.Client{
Transport: tr, Transport: tr,
Timeout: mesosHttpClientTimeout, Timeout: mesosHttpClientTimeout,

View File

@ -43,6 +43,7 @@ import (
"k8s.io/kubernetes/pkg/storage" "k8s.io/kubernetes/pkg/storage"
"k8s.io/kubernetes/pkg/ui" "k8s.io/kubernetes/pkg/ui"
"k8s.io/kubernetes/pkg/util" "k8s.io/kubernetes/pkg/util"
utilnet "k8s.io/kubernetes/pkg/util/net"
"k8s.io/kubernetes/pkg/util/sets" "k8s.io/kubernetes/pkg/util/sets"
systemd "github.com/coreos/go-systemd/daemon" systemd "github.com/coreos/go-systemd/daemon"
@ -212,7 +213,7 @@ type Config struct {
ServiceReadWriteIP net.IP ServiceReadWriteIP net.IP
// The range of ports to be assigned to services with type=NodePort or greater // The range of ports to be assigned to services with type=NodePort or greater
ServiceNodePortRange util.PortRange ServiceNodePortRange utilnet.PortRange
// Used to customize default proxy dial/tls options // Used to customize default proxy dial/tls options
ProxyDialer apiserver.ProxyDialerFunc ProxyDialer apiserver.ProxyDialerFunc
@ -237,7 +238,7 @@ type Config struct {
type GenericAPIServer struct { type GenericAPIServer struct {
// "Inputs", Copied from Config // "Inputs", Copied from Config
ServiceClusterIPRange *net.IPNet ServiceClusterIPRange *net.IPNet
ServiceNodePortRange util.PortRange ServiceNodePortRange utilnet.PortRange
cacheTimeout time.Duration cacheTimeout time.Duration
MinRequestTimeout time.Duration MinRequestTimeout time.Duration
@ -319,7 +320,7 @@ func setDefaults(c *Config) {
// We should probably allow this for clouds that don't require NodePort to do load-balancing (GCE) // We should probably allow this for clouds that don't require NodePort to do load-balancing (GCE)
// but then that breaks the strict nestedness of ServiceType. // but then that breaks the strict nestedness of ServiceType.
// Review post-v1 // Review post-v1
defaultServiceNodePortRange := util.PortRange{Base: 30000, Size: 2768} defaultServiceNodePortRange := utilnet.PortRange{Base: 30000, Size: 2768}
c.ServiceNodePortRange = defaultServiceNodePortRange c.ServiceNodePortRange = defaultServiceNodePortRange
glog.Infof("Node port range unspecified. Defaulting to %v.", c.ServiceNodePortRange) glog.Infof("Node port range unspecified. Defaulting to %v.", c.ServiceNodePortRange)
} }
@ -454,7 +455,7 @@ func NewHandlerContainer(mux *http.ServeMux) *restful.Container {
func (s *GenericAPIServer) init(c *Config) { func (s *GenericAPIServer) init(c *Config) {
if c.ProxyDialer != nil || c.ProxyTLSClientConfig != nil { if c.ProxyDialer != nil || c.ProxyTLSClientConfig != nil {
s.ProxyTransport = util.SetTransportDefaults(&http.Transport{ s.ProxyTransport = utilnet.SetTransportDefaults(&http.Transport{
Dial: c.ProxyDialer, Dial: c.ProxyDialer,
TLSClientConfig: c.ProxyTLSClientConfig, TLSClientConfig: c.ProxyTLSClientConfig,
}) })

View File

@ -30,7 +30,7 @@ import (
"k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/apiserver" "k8s.io/kubernetes/pkg/apiserver"
etcdtesting "k8s.io/kubernetes/pkg/storage/etcd/testing" etcdtesting "k8s.io/kubernetes/pkg/storage/etcd/testing"
"k8s.io/kubernetes/pkg/util" utilnet "k8s.io/kubernetes/pkg/util/net"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -77,7 +77,7 @@ func TestNew(t *testing.T) {
assert.Equal(s.ServiceReadWriteIP, config.ServiceReadWriteIP) assert.Equal(s.ServiceReadWriteIP, config.ServiceReadWriteIP)
// These functions should point to the same memory location // These functions should point to the same memory location
serverDialer, _ := util.Dialer(s.ProxyTransport) serverDialer, _ := utilnet.Dialer(s.ProxyTransport)
serverDialerFunc := fmt.Sprintf("%p", serverDialer) serverDialerFunc := fmt.Sprintf("%p", serverDialer)
configDialerFunc := fmt.Sprintf("%p", config.ProxyDialer) configDialerFunc := fmt.Sprintf("%p", config.ProxyDialer)
assert.Equal(serverDialerFunc, configDialerFunc) assert.Equal(serverDialerFunc, configDialerFunc)

View File

@ -27,7 +27,7 @@ import (
"k8s.io/kubernetes/pkg/api/validation" "k8s.io/kubernetes/pkg/api/validation"
"k8s.io/kubernetes/pkg/client/transport" "k8s.io/kubernetes/pkg/client/transport"
client "k8s.io/kubernetes/pkg/client/unversioned" client "k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/kubernetes/pkg/util" utilnet "k8s.io/kubernetes/pkg/util/net"
) )
type KubeletClientConfig struct { type KubeletClientConfig struct {
@ -71,7 +71,7 @@ func MakeTransport(config *KubeletClientConfig) (http.RoundTripper, error) {
rt := http.DefaultTransport rt := http.DefaultTransport
if config.Dial != nil || tlsConfig != nil { if config.Dial != nil || tlsConfig != nil {
rt = util.SetTransportDefaults(&http.Transport{ rt = utilnet.SetTransportDefaults(&http.Transport{
Dial: config.Dial, Dial: config.Dial,
TLSClientConfig: tlsConfig, TLSClientConfig: tlsConfig,
}) })

View File

@ -73,6 +73,7 @@ import (
utilerrors "k8s.io/kubernetes/pkg/util/errors" utilerrors "k8s.io/kubernetes/pkg/util/errors"
kubeio "k8s.io/kubernetes/pkg/util/io" kubeio "k8s.io/kubernetes/pkg/util/io"
"k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/util/mount"
utilnet "k8s.io/kubernetes/pkg/util/net"
nodeutil "k8s.io/kubernetes/pkg/util/node" nodeutil "k8s.io/kubernetes/pkg/util/node"
"k8s.io/kubernetes/pkg/util/oom" "k8s.io/kubernetes/pkg/util/oom"
"k8s.io/kubernetes/pkg/util/procfs" "k8s.io/kubernetes/pkg/util/procfs"
@ -2677,7 +2678,7 @@ func (kl *Kubelet) setNodeAddress(node *api.Node) error {
} }
if len(node.Status.Addresses) == 0 { if len(node.Status.Addresses) == 0 {
ip, err := util.ChooseHostInterface() ip, err := utilnet.ChooseHostInterface()
if err != nil { if err != nil {
return err return err
} }

View File

@ -21,6 +21,7 @@ import (
"net" "net"
"time" "time"
"github.com/golang/glog"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/endpoints" "k8s.io/kubernetes/pkg/api/endpoints"
"k8s.io/kubernetes/pkg/api/errors" "k8s.io/kubernetes/pkg/api/errors"
@ -32,8 +33,7 @@ import (
portallocatorcontroller "k8s.io/kubernetes/pkg/registry/service/portallocator/controller" portallocatorcontroller "k8s.io/kubernetes/pkg/registry/service/portallocator/controller"
"k8s.io/kubernetes/pkg/util" "k8s.io/kubernetes/pkg/util"
"k8s.io/kubernetes/pkg/util/intstr" "k8s.io/kubernetes/pkg/util/intstr"
utilnet "k8s.io/kubernetes/pkg/util/net"
"github.com/golang/glog"
) )
// Controller is the controller manager for the core bootstrap Kubernetes controller // Controller is the controller manager for the core bootstrap Kubernetes controller
@ -51,7 +51,7 @@ type Controller struct {
ServiceNodePortRegistry service.RangeRegistry ServiceNodePortRegistry service.RangeRegistry
ServiceNodePortInterval time.Duration ServiceNodePortInterval time.Duration
ServiceNodePortRange util.PortRange ServiceNodePortRange utilnet.PortRange
EndpointRegistry endpoint.Registry EndpointRegistry endpoint.Registry
EndpointInterval time.Duration EndpointInterval time.Duration

View File

@ -33,6 +33,8 @@ import (
"k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/api/testapi"
"k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/api/unversioned"
apiutil "k8s.io/kubernetes/pkg/api/util" apiutil "k8s.io/kubernetes/pkg/api/util"
utilnet "k8s.io/kubernetes/pkg/util/net"
"k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/genericapiserver" "k8s.io/kubernetes/pkg/genericapiserver"
"k8s.io/kubernetes/pkg/kubelet/client" "k8s.io/kubernetes/pkg/kubelet/client"
@ -44,7 +46,6 @@ import (
etcdstorage "k8s.io/kubernetes/pkg/storage/etcd" etcdstorage "k8s.io/kubernetes/pkg/storage/etcd"
"k8s.io/kubernetes/pkg/storage/etcd/etcdtest" "k8s.io/kubernetes/pkg/storage/etcd/etcdtest"
etcdtesting "k8s.io/kubernetes/pkg/storage/etcd/testing" etcdtesting "k8s.io/kubernetes/pkg/storage/etcd/testing"
"k8s.io/kubernetes/pkg/util"
"k8s.io/kubernetes/pkg/util/intstr" "k8s.io/kubernetes/pkg/util/intstr"
"github.com/emicklei/go-restful" "github.com/emicklei/go-restful"
@ -110,7 +111,7 @@ func TestNew(t *testing.T) {
assert.Equal(master.ServiceReadWriteIP, config.ServiceReadWriteIP) assert.Equal(master.ServiceReadWriteIP, config.ServiceReadWriteIP)
// These functions should point to the same memory location // These functions should point to the same memory location
masterDialer, _ := util.Dialer(master.ProxyTransport) masterDialer, _ := utilnet.Dialer(master.ProxyTransport)
masterDialerFunc := fmt.Sprintf("%p", masterDialer) masterDialerFunc := fmt.Sprintf("%p", masterDialer)
configDialerFunc := fmt.Sprintf("%p", config.ProxyDialer) configDialerFunc := fmt.Sprintf("%p", config.ProxyDialer)
assert.Equal(masterDialerFunc, configDialerFunc) assert.Equal(masterDialerFunc, configDialerFunc)
@ -164,7 +165,7 @@ func TestNewBootstrapController(t *testing.T) {
master, etcdserver, _, assert := setUp(t) master, etcdserver, _, assert := setUp(t)
defer etcdserver.Terminate(t) defer etcdserver.Terminate(t)
portRange := util.PortRange{Base: 10, Size: 10} portRange := utilnet.PortRange{Base: 10, Size: 10}
master.namespaceRegistry = namespace.NewRegistry(nil) master.namespaceRegistry = namespace.NewRegistry(nil)
master.serviceRegistry = registrytest.NewServiceRegistry() master.serviceRegistry = registrytest.NewServiceRegistry()

View File

@ -24,6 +24,7 @@ import (
"time" "time"
"k8s.io/kubernetes/pkg/util" "k8s.io/kubernetes/pkg/util"
"k8s.io/kubernetes/pkg/util/net"
) )
var ( var (
@ -52,7 +53,7 @@ func (r *randomAllocator) Release(_ int) {
// newPortAllocator builds PortAllocator for a given PortRange. If the PortRange is empty // newPortAllocator builds PortAllocator for a given PortRange. If the PortRange is empty
// then a random port allocator is returned; otherwise, a new range-based allocator // then a random port allocator is returned; otherwise, a new range-based allocator
// is returned. // is returned.
func newPortAllocator(r util.PortRange) PortAllocator { func newPortAllocator(r net.PortRange) PortAllocator {
if r.Base == 0 { if r.Base == 0 {
return &randomAllocator{} return &randomAllocator{}
} }
@ -66,14 +67,14 @@ const (
) )
type rangeAllocator struct { type rangeAllocator struct {
util.PortRange net.PortRange
ports chan int ports chan int
used big.Int used big.Int
lock sync.Mutex lock sync.Mutex
rand *rand.Rand rand *rand.Rand
} }
func newPortRangeAllocator(r util.PortRange) PortAllocator { func newPortRangeAllocator(r net.PortRange) PortAllocator {
if r.Base == 0 || r.Size == 0 { if r.Base == 0 || r.Size == 0 {
panic("illegal argument: may not specify an empty port range") panic("illegal argument: may not specify an empty port range")
} }

View File

@ -20,11 +20,11 @@ import (
"reflect" "reflect"
"testing" "testing"
"k8s.io/kubernetes/pkg/util" "k8s.io/kubernetes/pkg/util/net"
) )
func TestRangeAllocatorEmpty(t *testing.T) { func TestRangeAllocatorEmpty(t *testing.T) {
r := &util.PortRange{} r := &net.PortRange{}
r.Set("0-0") r.Set("0-0")
defer func() { defer func() {
if rv := recover(); rv == nil { if rv := recover(); rv == nil {
@ -35,7 +35,7 @@ func TestRangeAllocatorEmpty(t *testing.T) {
} }
func TestRangeAllocatorFullyAllocated(t *testing.T) { func TestRangeAllocatorFullyAllocated(t *testing.T) {
r := &util.PortRange{} r := &net.PortRange{}
r.Set("1-1") r.Set("1-1")
a := newPortRangeAllocator(*r) a := newPortRangeAllocator(*r)
p, err := a.AllocateNext() p, err := a.AllocateNext()
@ -67,7 +67,7 @@ func TestRangeAllocatorFullyAllocated(t *testing.T) {
} }
func TestRangeAllocator_RandomishAllocation(t *testing.T) { func TestRangeAllocator_RandomishAllocation(t *testing.T) {
r := &util.PortRange{} r := &net.PortRange{}
r.Set("1-100") r.Set("1-100")
a := newPortRangeAllocator(*r) a := newPortRangeAllocator(*r)

View File

@ -30,6 +30,8 @@ import (
"k8s.io/kubernetes/pkg/proxy" "k8s.io/kubernetes/pkg/proxy"
"k8s.io/kubernetes/pkg/types" "k8s.io/kubernetes/pkg/types"
"k8s.io/kubernetes/pkg/util" "k8s.io/kubernetes/pkg/util"
utilnet "k8s.io/kubernetes/pkg/util/net"
utilerrors "k8s.io/kubernetes/pkg/util/errors" utilerrors "k8s.io/kubernetes/pkg/util/errors"
"k8s.io/kubernetes/pkg/util/iptables" "k8s.io/kubernetes/pkg/util/iptables"
) )
@ -137,12 +139,12 @@ func IsProxyLocked(err error) bool {
// if iptables fails to update or acquire the initial lock. Once a proxier is // if iptables fails to update or acquire the initial lock. Once a proxier is
// created, it will keep iptables up to date in the background and will not // created, it will keep iptables up to date in the background and will not
// terminate if a particular iptables call fails. // terminate if a particular iptables call fails.
func NewProxier(loadBalancer LoadBalancer, listenIP net.IP, iptables iptables.Interface, pr util.PortRange, syncPeriod, udpIdleTimeout time.Duration) (*Proxier, error) { func NewProxier(loadBalancer LoadBalancer, listenIP net.IP, iptables iptables.Interface, pr utilnet.PortRange, syncPeriod, udpIdleTimeout time.Duration) (*Proxier, error) {
if listenIP.Equal(localhostIPv4) || listenIP.Equal(localhostIPv6) { if listenIP.Equal(localhostIPv4) || listenIP.Equal(localhostIPv6) {
return nil, ErrProxyOnLocalhost return nil, ErrProxyOnLocalhost
} }
hostIP, err := util.ChooseHostInterface() hostIP, err := utilnet.ChooseHostInterface()
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to select a host interface: %v", err) return nil, fmt.Errorf("failed to select a host interface: %v", err)
} }
@ -161,7 +163,7 @@ func NewProxier(loadBalancer LoadBalancer, listenIP net.IP, iptables iptables.In
func createProxier(loadBalancer LoadBalancer, listenIP net.IP, iptables iptables.Interface, hostIP net.IP, proxyPorts PortAllocator, syncPeriod, udpIdleTimeout time.Duration) (*Proxier, error) { func createProxier(loadBalancer LoadBalancer, listenIP net.IP, iptables iptables.Interface, hostIP net.IP, proxyPorts PortAllocator, syncPeriod, udpIdleTimeout time.Duration) (*Proxier, error) {
// convenient to pass nil for tests.. // convenient to pass nil for tests..
if proxyPorts == nil { if proxyPorts == nil {
proxyPorts = newPortAllocator(util.PortRange{}) proxyPorts = newPortAllocator(utilnet.PortRange{})
} }
// Set up the iptables foundations we need. // Set up the iptables foundations we need.
if err := iptablesInit(iptables); err != nil { if err := iptablesInit(iptables); err != nil {

View File

@ -26,8 +26,8 @@ import (
"time" "time"
"k8s.io/kubernetes/pkg/api/errors" "k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/util"
"k8s.io/kubernetes/pkg/util/httpstream" "k8s.io/kubernetes/pkg/util/httpstream"
"k8s.io/kubernetes/pkg/util/net"
"k8s.io/kubernetes/pkg/util/proxy" "k8s.io/kubernetes/pkg/util/proxy"
"github.com/golang/glog" "github.com/golang/glog"
@ -226,7 +226,7 @@ func (p *corsRemovingTransport) RoundTrip(req *http.Request) (*http.Response, er
return resp, nil return resp, nil
} }
var _ = util.RoundTripperWrapper(&corsRemovingTransport{}) var _ = net.RoundTripperWrapper(&corsRemovingTransport{})
func (rt *corsRemovingTransport) WrappedRoundTripper() http.RoundTripper { func (rt *corsRemovingTransport) WrappedRoundTripper() http.RoundTripper {
return rt.RoundTripper return rt.RoundTripper

View File

@ -32,7 +32,7 @@ import (
"k8s.io/kubernetes/pkg/master/ports" "k8s.io/kubernetes/pkg/master/ports"
"k8s.io/kubernetes/pkg/registry/generic" "k8s.io/kubernetes/pkg/registry/generic"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util" utilnet "k8s.io/kubernetes/pkg/util/net"
nodeutil "k8s.io/kubernetes/pkg/util/node" nodeutil "k8s.io/kubernetes/pkg/util/node"
"k8s.io/kubernetes/pkg/util/validation/field" "k8s.io/kubernetes/pkg/util/validation/field"
) )
@ -162,7 +162,7 @@ func MatchNode(label labels.Selector, field fields.Selector) generic.Matcher {
// ResourceLocation returns an URL and transport which one can use to send traffic for the specified node. // ResourceLocation returns an URL and transport which one can use to send traffic for the specified node.
func ResourceLocation(getter ResourceGetter, connection client.ConnectionInfoGetter, proxyTransport http.RoundTripper, ctx api.Context, id string) (*url.URL, http.RoundTripper, error) { func ResourceLocation(getter ResourceGetter, connection client.ConnectionInfoGetter, proxyTransport http.RoundTripper, ctx api.Context, id string) (*url.URL, http.RoundTripper, error) {
schemeReq, name, portReq, valid := util.SplitSchemeNamePort(id) schemeReq, name, portReq, valid := utilnet.SplitSchemeNamePort(id)
if !valid { if !valid {
return nil, nil, errors.NewBadRequest(fmt.Sprintf("invalid node request %q", id)) return nil, nil, errors.NewBadRequest(fmt.Sprintf("invalid node request %q", id))
} }

View File

@ -32,7 +32,7 @@ import (
"k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/generic" "k8s.io/kubernetes/pkg/registry/generic"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util" utilnet "k8s.io/kubernetes/pkg/util/net"
"k8s.io/kubernetes/pkg/util/validation/field" "k8s.io/kubernetes/pkg/util/validation/field"
) )
@ -199,7 +199,7 @@ func getPod(getter ResourceGetter, ctx api.Context, name string) (*api.Pod, erro
func ResourceLocation(getter ResourceGetter, rt http.RoundTripper, ctx api.Context, id string) (*url.URL, http.RoundTripper, error) { func ResourceLocation(getter ResourceGetter, rt http.RoundTripper, ctx api.Context, id string) (*url.URL, http.RoundTripper, error) {
// Allow ID as "podname" or "podname:port" or "scheme:podname:port". // Allow ID as "podname" or "podname:port" or "scheme:podname:port".
// If port is not specified, try to use the first defined port on the pod. // If port is not specified, try to use the first defined port on the pod.
scheme, name, port, valid := util.SplitSchemeNamePort(id) scheme, name, port, valid := utilnet.SplitSchemeNamePort(id)
if !valid { if !valid {
return nil, nil, errors.NewBadRequest(fmt.Sprintf("invalid pod request %q", id)) return nil, nil, errors.NewBadRequest(fmt.Sprintf("invalid pod request %q", id))
} }

View File

@ -22,7 +22,7 @@ import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/registry/service/allocator" "k8s.io/kubernetes/pkg/registry/service/allocator"
"k8s.io/kubernetes/pkg/util" "k8s.io/kubernetes/pkg/util/net"
"github.com/golang/glog" "github.com/golang/glog"
) )
@ -43,7 +43,7 @@ var (
) )
type PortAllocator struct { type PortAllocator struct {
portRange util.PortRange portRange net.PortRange
alloc allocator.Interface alloc allocator.Interface
} }
@ -51,8 +51,8 @@ type PortAllocator struct {
// PortAllocator implements Interface and Snapshottable // PortAllocator implements Interface and Snapshottable
var _ Interface = &PortAllocator{} var _ Interface = &PortAllocator{}
// NewPortAllocatorCustom creates a PortAllocator over a util.PortRange, calling allocatorFactory to construct the backing store. // NewPortAllocatorCustom creates a PortAllocator over a net.PortRange, calling allocatorFactory to construct the backing store.
func NewPortAllocatorCustom(pr util.PortRange, allocatorFactory allocator.AllocatorFactory) *PortAllocator { func NewPortAllocatorCustom(pr net.PortRange, allocatorFactory allocator.AllocatorFactory) *PortAllocator {
max := pr.Size max := pr.Size
rangeSpec := pr.String() rangeSpec := pr.String()
@ -64,7 +64,7 @@ func NewPortAllocatorCustom(pr util.PortRange, allocatorFactory allocator.Alloca
} }
// Helper that wraps NewAllocatorCIDRRange, for creating a range backed by an in-memory store. // Helper that wraps NewAllocatorCIDRRange, for creating a range backed by an in-memory store.
func NewPortAllocator(pr util.PortRange) *PortAllocator { func NewPortAllocator(pr net.PortRange) *PortAllocator {
return NewPortAllocatorCustom(pr, func(max int, rangeSpec string) allocator.Interface { return NewPortAllocatorCustom(pr, func(max int, rangeSpec string) allocator.Interface {
return allocator.NewAllocationMap(max, rangeSpec) return allocator.NewAllocationMap(max, rangeSpec)
}) })
@ -146,7 +146,7 @@ func (r *PortAllocator) Snapshot(dst *api.RangeAllocation) error {
// Restore restores the pool to the previously captured state. ErrMismatchedNetwork // Restore restores the pool to the previously captured state. ErrMismatchedNetwork
// is returned if the provided port range doesn't exactly match the previous range. // is returned if the provided port range doesn't exactly match the previous range.
func (r *PortAllocator) Restore(pr util.PortRange, data []byte) error { func (r *PortAllocator) Restore(pr net.PortRange, data []byte) error {
if pr.String() != r.portRange.String() { if pr.String() != r.portRange.String() {
return ErrMismatchedNetwork return ErrMismatchedNetwork
} }

View File

@ -22,12 +22,12 @@ import (
"strconv" "strconv"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/util" "k8s.io/kubernetes/pkg/util/net"
"k8s.io/kubernetes/pkg/util/sets" "k8s.io/kubernetes/pkg/util/sets"
) )
func TestAllocate(t *testing.T) { func TestAllocate(t *testing.T) {
pr, err := util.ParsePortRange("10000-10200") pr, err := net.ParsePortRange("10000-10200")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -97,7 +97,7 @@ func TestAllocate(t *testing.T) {
} }
func TestSnapshot(t *testing.T) { func TestSnapshot(t *testing.T) {
pr, err := util.ParsePortRange("10000-10200") pr, err := net.ParsePortRange("10000-10200")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -117,7 +117,7 @@ func TestSnapshot(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
pr2, err := util.ParsePortRange(dst.Range) pr2, err := net.ParsePortRange(dst.Range)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -126,7 +126,7 @@ func TestSnapshot(t *testing.T) {
t.Fatalf("mismatched networks: %s : %s", pr, pr2) t.Fatalf("mismatched networks: %s : %s", pr, pr2)
} }
otherPr, err := util.ParsePortRange("200-300") otherPr, err := net.ParsePortRange("200-300")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -24,19 +24,20 @@ import (
"k8s.io/kubernetes/pkg/registry/service" "k8s.io/kubernetes/pkg/registry/service"
"k8s.io/kubernetes/pkg/registry/service/portallocator" "k8s.io/kubernetes/pkg/registry/service/portallocator"
"k8s.io/kubernetes/pkg/util" "k8s.io/kubernetes/pkg/util"
"k8s.io/kubernetes/pkg/util/net"
) )
// See ipallocator/controller/repair.go; this is a copy for ports. // See ipallocator/controller/repair.go; this is a copy for ports.
type Repair struct { type Repair struct {
interval time.Duration interval time.Duration
registry service.Registry registry service.Registry
portRange util.PortRange portRange net.PortRange
alloc service.RangeRegistry alloc service.RangeRegistry
} }
// NewRepair creates a controller that periodically ensures that all ports are uniquely allocated across the cluster // NewRepair creates a controller that periodically ensures that all ports are uniquely allocated across the cluster
// and generates informational warnings for a cluster that is not in sync. // and generates informational warnings for a cluster that is not in sync.
func NewRepair(interval time.Duration, registry service.Registry, portRange util.PortRange, alloc service.RangeRegistry) *Repair { func NewRepair(interval time.Duration, registry service.Registry, portRange net.PortRange, alloc service.RangeRegistry) *Repair {
return &Repair{ return &Repair{
interval: interval, interval: interval,
registry: registry, registry: registry,

View File

@ -34,7 +34,7 @@ import (
"k8s.io/kubernetes/pkg/registry/service/ipallocator" "k8s.io/kubernetes/pkg/registry/service/ipallocator"
"k8s.io/kubernetes/pkg/registry/service/portallocator" "k8s.io/kubernetes/pkg/registry/service/portallocator"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util" utilnet "k8s.io/kubernetes/pkg/util/net"
"k8s.io/kubernetes/pkg/util/validation/field" "k8s.io/kubernetes/pkg/util/validation/field"
"k8s.io/kubernetes/pkg/watch" "k8s.io/kubernetes/pkg/watch"
) )
@ -287,7 +287,7 @@ var _ = rest.Redirector(&REST{})
// ResourceLocation returns a URL to which one can send traffic for the specified service. // ResourceLocation returns a URL to which one can send traffic for the specified service.
func (rs *REST) ResourceLocation(ctx api.Context, id string) (*url.URL, http.RoundTripper, error) { func (rs *REST) ResourceLocation(ctx api.Context, id string) (*url.URL, http.RoundTripper, error) {
// Allow ID as "svcname", "svcname:port", or "scheme:svcname:port". // Allow ID as "svcname", "svcname:port", or "scheme:svcname:port".
svcScheme, svcName, portStr, valid := util.SplitSchemeNamePort(id) svcScheme, svcName, portStr, valid := utilnet.SplitSchemeNamePort(id)
if !valid { if !valid {
return nil, nil, errors.NewBadRequest(fmt.Sprintf("invalid service request %q", id)) return nil, nil, errors.NewBadRequest(fmt.Sprintf("invalid service request %q", id))
} }

View File

@ -27,7 +27,8 @@ import (
"k8s.io/kubernetes/pkg/registry/registrytest" "k8s.io/kubernetes/pkg/registry/registrytest"
"k8s.io/kubernetes/pkg/registry/service/ipallocator" "k8s.io/kubernetes/pkg/registry/service/ipallocator"
"k8s.io/kubernetes/pkg/registry/service/portallocator" "k8s.io/kubernetes/pkg/registry/service/portallocator"
"k8s.io/kubernetes/pkg/util" utilnet "k8s.io/kubernetes/pkg/util/net"
"k8s.io/kubernetes/pkg/util/intstr" "k8s.io/kubernetes/pkg/util/intstr"
) )
@ -42,7 +43,7 @@ func NewTestREST(t *testing.T, endpoints *api.EndpointsList) (*REST, *registryte
} }
r := ipallocator.NewCIDRRange(makeIPNet(t)) r := ipallocator.NewCIDRRange(makeIPNet(t))
portRange := util.PortRange{Base: 30000, Size: 1000} portRange := utilnet.PortRange{Base: 30000, Size: 1000}
portAllocator := portallocator.NewPortAllocator(portRange) portAllocator := portallocator.NewPortAllocator(portRange)
storage := NewStorage(registry, endpointRegistry, r, portAllocator, nil) storage := NewStorage(registry, endpointRegistry, r, portAllocator, nil)

View File

@ -1,5 +1,5 @@
/* /*
Copyright 2014 The Kubernetes Authors All rights reserved. Copyright 2016 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package util package net
import ( import (
"crypto/tls" "crypto/tls"
@ -111,3 +111,12 @@ func FormatURL(scheme string, host string, port int, path string) *url.URL {
Path: path, Path: path,
} }
} }
func GetHTTPClient(req *http.Request) string {
if userAgent, ok := req.Header["User-Agent"]; ok {
if len(userAgent) > 0 {
return userAgent[0]
}
}
return "unknown"
}

278
pkg/util/net/interface.go Normal file
View File

@ -0,0 +1,278 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package net
import (
"bufio"
"encoding/hex"
"fmt"
"io"
"net"
"os"
"strings"
"github.com/golang/glog"
)
type Route struct {
Interface string
Destination net.IP
Gateway net.IP
// TODO: add more fields here if needed
}
func getRoutes(input io.Reader) ([]Route, error) {
routes := []Route{}
if input == nil {
return nil, fmt.Errorf("input is nil")
}
scanner := bufio.NewReader(input)
for {
line, err := scanner.ReadString('\n')
if err == io.EOF {
break
}
//ignore the headers in the route info
if strings.HasPrefix(line, "Iface") {
continue
}
fields := strings.Fields(line)
routes = append(routes, Route{})
route := &routes[len(routes)-1]
route.Interface = fields[0]
ip, err := parseIP(fields[1])
if err != nil {
return nil, err
}
route.Destination = ip
ip, err = parseIP(fields[2])
if err != nil {
return nil, err
}
route.Gateway = ip
}
return routes, nil
}
func parseIP(str string) (net.IP, error) {
if str == "" {
return nil, fmt.Errorf("input is nil")
}
bytes, err := hex.DecodeString(str)
if err != nil {
return nil, err
}
//TODO add ipv6 support
if len(bytes) != net.IPv4len {
return nil, fmt.Errorf("only IPv4 is supported")
}
bytes[0], bytes[1], bytes[2], bytes[3] = bytes[3], bytes[2], bytes[1], bytes[0]
return net.IP(bytes), nil
}
func isInterfaceUp(intf *net.Interface) bool {
if intf == nil {
return false
}
if intf.Flags&net.FlagUp != 0 {
glog.V(4).Infof("Interface %v is up", intf.Name)
return true
}
return false
}
//getFinalIP method receives all the IP addrs of a Interface
//and returns a nil if the address is Loopback, Ipv6, link-local or nil.
//It returns a valid IPv4 if an Ipv4 address is found in the array.
func getFinalIP(addrs []net.Addr) (net.IP, error) {
if len(addrs) > 0 {
for i := range addrs {
glog.V(4).Infof("Checking addr %s.", addrs[i].String())
ip, _, err := net.ParseCIDR(addrs[i].String())
if err != nil {
return nil, err
}
//Only IPv4
//TODO : add IPv6 support
if ip.To4() != nil {
if !ip.IsLoopback() && !ip.IsLinkLocalMulticast() && !ip.IsLinkLocalUnicast() {
glog.V(4).Infof("IP found %v", ip)
return ip, nil
} else {
glog.V(4).Infof("Loopback/link-local found %v", ip)
}
} else {
glog.V(4).Infof("%v is not a valid IPv4 address", ip)
}
}
}
return nil, nil
}
func getIPFromInterface(intfName string, nw networkInterfacer) (net.IP, error) {
intf, err := nw.InterfaceByName(intfName)
if err != nil {
return nil, err
}
if isInterfaceUp(intf) {
addrs, err := nw.Addrs(intf)
if err != nil {
return nil, err
}
glog.V(4).Infof("Interface %q has %d addresses :%v.", intfName, len(addrs), addrs)
finalIP, err := getFinalIP(addrs)
if err != nil {
return nil, err
}
if finalIP != nil {
glog.V(4).Infof("valid IPv4 address for interface %q found as %v.", intfName, finalIP)
return finalIP, nil
}
}
return nil, nil
}
func flagsSet(flags net.Flags, test net.Flags) bool {
return flags&test != 0
}
func flagsClear(flags net.Flags, test net.Flags) bool {
return flags&test == 0
}
func chooseHostInterfaceNativeGo() (net.IP, error) {
intfs, err := net.Interfaces()
if err != nil {
return nil, err
}
i := 0
var ip net.IP
for i = range intfs {
if flagsSet(intfs[i].Flags, net.FlagUp) && flagsClear(intfs[i].Flags, net.FlagLoopback|net.FlagPointToPoint) {
addrs, err := intfs[i].Addrs()
if err != nil {
return nil, err
}
if len(addrs) > 0 {
for _, addr := range addrs {
if addrIP, _, err := net.ParseCIDR(addr.String()); err == nil {
if addrIP.To4() != nil {
ip = addrIP.To4()
if !ip.IsLinkLocalMulticast() && !ip.IsLinkLocalUnicast() {
break
}
}
}
}
if ip != nil {
// This interface should suffice.
break
}
}
}
}
if ip == nil {
return nil, fmt.Errorf("no acceptable interface from host")
}
glog.V(4).Infof("Choosing interface %s (IP %v) as default", intfs[i].Name, ip)
return ip, nil
}
//ChooseHostInterface is a method used fetch an IP for a daemon.
//It uses data from /proc/net/route file.
//For a node with no internet connection ,it returns error
//For a multi n/w interface node it returns the IP of the interface with gateway on it.
func ChooseHostInterface() (net.IP, error) {
inFile, err := os.Open("/proc/net/route")
if err != nil {
if os.IsNotExist(err) {
return chooseHostInterfaceNativeGo()
}
return nil, err
}
defer inFile.Close()
var nw networkInterfacer = networkInterface{}
return chooseHostInterfaceFromRoute(inFile, nw)
}
type networkInterfacer interface {
InterfaceByName(intfName string) (*net.Interface, error)
Addrs(intf *net.Interface) ([]net.Addr, error)
}
type networkInterface struct{}
func (_ networkInterface) InterfaceByName(intfName string) (*net.Interface, error) {
intf, err := net.InterfaceByName(intfName)
if err != nil {
return nil, err
}
return intf, nil
}
func (_ networkInterface) Addrs(intf *net.Interface) ([]net.Addr, error) {
addrs, err := intf.Addrs()
if err != nil {
return nil, err
}
return addrs, nil
}
func chooseHostInterfaceFromRoute(inFile io.Reader, nw networkInterfacer) (net.IP, error) {
routes, err := getRoutes(inFile)
if err != nil {
return nil, err
}
zero := net.IP{0, 0, 0, 0}
var finalIP net.IP
for i := range routes {
//find interface with gateway
if routes[i].Destination.Equal(zero) {
glog.V(4).Infof("Default route transits interface %q", routes[i].Interface)
finalIP, err := getIPFromInterface(routes[i].Interface, nw)
if err != nil {
return nil, err
}
if finalIP != nil {
glog.V(4).Infof("Choosing IP %v ", finalIP)
return finalIP, nil
}
}
}
glog.V(4).Infof("No valid IP found")
if finalIP == nil {
return nil, fmt.Errorf("Unable to select an IP.")
}
return nil, nil
}
// If bind-address is usable, return it directly
// If bind-address is not usable (unset, 0.0.0.0, or loopback), we will use the host's default
// interface.
func ChooseBindAddress(bindAddress net.IP) (net.IP, error) {
if bindAddress == nil || bindAddress.IsUnspecified() || bindAddress.IsLoopback() {
hostIP, err := ChooseHostInterface()
if err != nil {
return nil, err
}
bindAddress = hostIP
}
return bindAddress, nil
}

View File

@ -0,0 +1,300 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package net
import (
"fmt"
"io"
"net"
"strings"
"testing"
)
const gatewayfirst = `Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
eth3 00000000 0100FE0A 0003 0 0 1024 00000000 0 0 0
eth3 0000FE0A 00000000 0001 0 0 0 0080FFFF 0 0 0
docker0 000011AC 00000000 0001 0 0 0 0000FFFF 0 0 0
virbr0 007AA8C0 00000000 0001 0 0 0 00FFFFFF 0 0 0
`
const gatewaylast = `Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
docker0 000011AC 00000000 0001 0 0 0 0000FFFF 0 0 0
virbr0 007AA8C0 00000000 0001 0 0 0 00FFFFFF 0 0 0
eth3 0000FE0A 00000000 0001 0 0 0 0080FFFF 0 0 0
eth3 00000000 0100FE0A 0003 0 0 1024 00000000 0 0 0
`
const gatewaymiddle = `Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
eth3 0000FE0A 00000000 0001 0 0 0 0080FFFF 0 0 0
docker0 000011AC 00000000 0001 0 0 0 0000FFFF 0 0 0
eth3 00000000 0100FE0A 0003 0 0 1024 00000000 0 0 0
virbr0 007AA8C0 00000000 0001 0 0 0 00FFFFFF 0 0 0
`
const noInternetConnection = `Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
docker0 000011AC 00000000 0001 0 0 0 0000FFFF 0 0 0
virbr0 007AA8C0 00000000 0001 0 0 0 00FFFFFF 0 0 0
`
const nothing = `Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
`
const gatewayfirstIpv6_1 = `Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
eth3 00000000 0100FE0A 0003 0 0 1024 00000000 0 0 0
eth3 0000FE0AA1 00000000 0001 0 0 0 0080FFFF 0 0 0
docker0 000011AC 00000000 0001 0 0 0 0000FFFF 0 0 0
virbr0 007AA8C0 00000000 0001 0 0 0 00FFFFFF 0 0 0
`
const gatewayfirstIpv6_2 = `Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
eth3 00000000 0100FE0AA1 0003 0 0 1024 00000000 0 0 0
eth3 0000FE0A 00000000 0001 0 0 0 0080FFFF 0 0 0
docker0 000011AC 00000000 0001 0 0 0 0000FFFF 0 0 0
virbr0 007AA8C0 00000000 0001 0 0 0 00FFFFFF 0 0 0
`
const route_Invalidhex = `Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
eth3 00000000 0100FE0AA 0003 0 0 1024 00000000 0 0 0
eth3 0000FE0A 00000000 0001 0 0 0 0080FFFF 0 0 0
docker0 000011AC 00000000 0001 0 0 0 0000FFFF 0 0 0
virbr0 007AA8C0 00000000 0001 0 0 0 00FFFFFF 0 0 0
`
// Based on DigitalOcean COREOS
const gatewayfirstLinkLocal = `Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
eth0 00000000 0120372D 0001 0 0 0 00000000 0 0 0
eth0 00000000 00000000 0001 0 0 2048 00000000 0 0 0
`
func TestGetRoutes(t *testing.T) {
testCases := []struct {
tcase string
route string
expected int
}{
{"gatewayfirst", gatewayfirst, 4},
{"gatewaymiddle", gatewaymiddle, 4},
{"gatewaylast", gatewaylast, 4},
{"nothing", nothing, 0},
{"gatewayfirstIpv6_1", gatewayfirstIpv6_1, 0},
{"gatewayfirstIpv6_2", gatewayfirstIpv6_2, 0},
{"route_Invalidhex", route_Invalidhex, 0},
}
for _, tc := range testCases {
r := strings.NewReader(tc.route)
routes, err := getRoutes(r)
if len(routes) != tc.expected {
t.Errorf("case[%v]: expected %v, got %v .err : %v", tc.tcase, tc.expected, len(routes), err)
}
}
}
func TestParseIP(t *testing.T) {
testCases := []struct {
tcase string
ip string
success bool
expected net.IP
}{
{"empty", "", false, nil},
{"too short", "AA", false, nil},
{"too long", "0011223344", false, nil},
{"invalid", "invalid!", false, nil},
{"zero", "00000000", true, net.IP{0, 0, 0, 0}},
{"ffff", "FFFFFFFF", true, net.IP{0xff, 0xff, 0xff, 0xff}},
{"valid", "12345678", true, net.IP{120, 86, 52, 18}},
}
for _, tc := range testCases {
ip, err := parseIP(tc.ip)
if !ip.Equal(tc.expected) {
t.Errorf("case[%v]: expected %q, got %q . err : %v", tc.tcase, tc.expected, ip, err)
}
}
}
func TestIsInterfaceUp(t *testing.T) {
testCases := []struct {
tcase string
intf net.Interface
expected bool
}{
{"up", net.Interface{Index: 0, MTU: 0, Name: "eth3", HardwareAddr: nil, Flags: net.FlagUp}, true},
{"down", net.Interface{Index: 0, MTU: 0, Name: "eth3", HardwareAddr: nil, Flags: 0}, false},
{"nothing", net.Interface{}, false},
}
for _, tc := range testCases {
it := isInterfaceUp(&tc.intf)
if it != tc.expected {
t.Errorf("case[%v]: expected %v, got %v .", tc.tcase, tc.expected, it)
}
}
}
type addrStruct struct{ val string }
func (a addrStruct) Network() string {
return a.val
}
func (a addrStruct) String() string {
return a.val
}
func TestFinalIP(t *testing.T) {
testCases := []struct {
tcase string
addr []net.Addr
expected net.IP
}{
{"ipv6", []net.Addr{addrStruct{val: "fe80::2f7:6fff:fe6e:2956/64"}}, nil},
{"invalidCIDR", []net.Addr{addrStruct{val: "fe80::2f7:67fff:fe6e:2956/64"}}, nil},
{"loopback", []net.Addr{addrStruct{val: "127.0.0.1/24"}}, nil},
{"ip4", []net.Addr{addrStruct{val: "10.254.12.132/17"}}, net.ParseIP("10.254.12.132")},
{"nothing", []net.Addr{}, nil},
}
for _, tc := range testCases {
ip, err := getFinalIP(tc.addr)
if !ip.Equal(tc.expected) {
t.Errorf("case[%v]: expected %v, got %v .err : %v", tc.tcase, tc.expected, ip, err)
}
}
}
func TestAddrs(t *testing.T) {
var nw networkInterfacer = validNetworkInterface{}
intf := net.Interface{Index: 0, MTU: 0, Name: "eth3", HardwareAddr: nil, Flags: 0}
addrs, err := nw.Addrs(&intf)
if err != nil {
t.Errorf("expected no error got : %v", err)
}
if len(addrs) != 2 {
t.Errorf("expected addrs: 2 got null")
}
}
type validNetworkInterface struct {
}
func (_ validNetworkInterface) InterfaceByName(intfName string) (*net.Interface, error) {
c := net.Interface{Index: 0, MTU: 0, Name: "eth3", HardwareAddr: nil, Flags: net.FlagUp}
return &c, nil
}
func (_ validNetworkInterface) Addrs(intf *net.Interface) ([]net.Addr, error) {
var ifat []net.Addr
ifat = []net.Addr{
addrStruct{val: "fe80::2f7:6fff:fe6e:2956/64"}, addrStruct{val: "10.254.71.145/17"}}
return ifat, nil
}
type validNetworkInterfaceWithLinkLocal struct {
}
func (_ validNetworkInterfaceWithLinkLocal) InterfaceByName(intfName string) (*net.Interface, error) {
c := net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: net.FlagUp}
return &c, nil
}
func (_ validNetworkInterfaceWithLinkLocal) Addrs(intf *net.Interface) ([]net.Addr, error) {
var ifat []net.Addr
ifat = []net.Addr{addrStruct{val: "169.254.162.166/16"}, addrStruct{val: "45.55.47.146/19"}}
return ifat, nil
}
type validNetworkInterfacewithIpv6Only struct {
}
func (_ validNetworkInterfacewithIpv6Only) InterfaceByName(intfName string) (*net.Interface, error) {
c := net.Interface{Index: 0, MTU: 0, Name: "eth3", HardwareAddr: nil, Flags: net.FlagUp}
return &c, nil
}
func (_ validNetworkInterfacewithIpv6Only) Addrs(intf *net.Interface) ([]net.Addr, error) {
var ifat []net.Addr
ifat = []net.Addr{addrStruct{val: "fe80::2f7:6fff:fe6e:2956/64"}}
return ifat, nil
}
type noNetworkInterface struct {
}
func (_ noNetworkInterface) InterfaceByName(intfName string) (*net.Interface, error) {
return nil, fmt.Errorf("unable get Interface")
}
func (_ noNetworkInterface) Addrs(intf *net.Interface) ([]net.Addr, error) {
return nil, nil
}
type networkInterfacewithNoAddrs struct {
}
func (_ networkInterfacewithNoAddrs) InterfaceByName(intfName string) (*net.Interface, error) {
c := net.Interface{Index: 0, MTU: 0, Name: "eth3", HardwareAddr: nil, Flags: net.FlagUp}
return &c, nil
}
func (_ networkInterfacewithNoAddrs) Addrs(intf *net.Interface) ([]net.Addr, error) {
return nil, fmt.Errorf("unable get Addrs")
}
type networkInterfacewithIpv6addrs struct {
}
func (_ networkInterfacewithIpv6addrs) InterfaceByName(intfName string) (*net.Interface, error) {
c := net.Interface{Index: 0, MTU: 0, Name: "eth3", HardwareAddr: nil, Flags: net.FlagUp}
return &c, nil
}
func (_ networkInterfacewithIpv6addrs) Addrs(intf *net.Interface) ([]net.Addr, error) {
var ifat []net.Addr
ifat = []net.Addr{addrStruct{val: "fe80::2f7:6ffff:fe6e:2956/64"}}
return ifat, nil
}
func TestGetIPFromInterface(t *testing.T) {
testCases := []struct {
tcase string
nwname string
nw networkInterfacer
expected net.IP
}{
{"valid", "eth3", validNetworkInterface{}, net.ParseIP("10.254.71.145")},
{"ipv6", "eth3", validNetworkInterfacewithIpv6Only{}, nil},
{"nothing", "eth3", noNetworkInterface{}, nil},
}
for _, tc := range testCases {
ip, err := getIPFromInterface(tc.nwname, tc.nw)
if !ip.Equal(tc.expected) {
t.Errorf("case[%v]: expected %v, got %+v .err : %v", tc.tcase, tc.expected, ip, err)
}
}
}
func TestChooseHostInterfaceFromRoute(t *testing.T) {
testCases := []struct {
tcase string
inFile io.Reader
nw networkInterfacer
expected net.IP
}{
{"valid_routefirst", strings.NewReader(gatewayfirst), validNetworkInterface{}, net.ParseIP("10.254.71.145")},
{"valid_routelast", strings.NewReader(gatewaylast), validNetworkInterface{}, net.ParseIP("10.254.71.145")},
{"valid_routemiddle", strings.NewReader(gatewaymiddle), validNetworkInterface{}, net.ParseIP("10.254.71.145")},
{"valid_routemiddle_ipv6", strings.NewReader(gatewaymiddle), validNetworkInterfacewithIpv6Only{}, nil},
{"no internet connection", strings.NewReader(noInternetConnection), validNetworkInterface{}, nil},
{"no non-link-local ip", strings.NewReader(gatewayfirstLinkLocal), validNetworkInterfaceWithLinkLocal{}, net.ParseIP("45.55.47.146")},
{"no route", strings.NewReader(nothing), validNetworkInterface{}, nil},
{"no route file", nil, validNetworkInterface{}, nil},
{"no interfaces", nil, noNetworkInterface{}, nil},
{"no interface Addrs", strings.NewReader(gatewaymiddle), networkInterfacewithNoAddrs{}, nil},
{"Invalid Addrs", strings.NewReader(gatewaymiddle), networkInterfacewithIpv6addrs{}, nil},
}
for _, tc := range testCases {
ip, err := chooseHostInterfaceFromRoute(tc.inFile, tc.nw)
if !ip.Equal(tc.expected) {
t.Errorf("case[%v]: expected %v, got %+v .err : %v", tc.tcase, tc.expected, ip, err)
}
}
}

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package util package net
import ( import (
"fmt" "fmt"

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package util package net
import ( import (
"testing" "testing"

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package util package net
import ( import (
"strings" "strings"

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package util package net
import ( import (
"testing" "testing"

View File

@ -25,14 +25,14 @@ import (
"github.com/golang/glog" "github.com/golang/glog"
"k8s.io/kubernetes/pkg/util" utilnet "k8s.io/kubernetes/pkg/util/net"
"k8s.io/kubernetes/third_party/golang/netutil" "k8s.io/kubernetes/third_party/golang/netutil"
) )
func DialURL(url *url.URL, transport http.RoundTripper) (net.Conn, error) { func DialURL(url *url.URL, transport http.RoundTripper) (net.Conn, error) {
dialAddr := netutil.CanonicalAddr(url) dialAddr := netutil.CanonicalAddr(url)
dialer, _ := util.Dialer(transport) dialer, _ := utilnet.Dialer(transport)
switch url.Scheme { switch url.Scheme {
case "http": case "http":
@ -45,7 +45,7 @@ func DialURL(url *url.URL, transport http.RoundTripper) (net.Conn, error) {
var tlsConfig *tls.Config var tlsConfig *tls.Config
var tlsConn *tls.Conn var tlsConn *tls.Conn
var err error var err error
tlsConfig, _ = util.TLSClientConfig(transport) tlsConfig, _ = utilnet.TLSClientConfig(transport)
if dialer != nil { if dialer != nil {
// We have a dialer; use it to open the connection, then // We have a dialer; use it to open the connection, then

View File

@ -31,7 +31,7 @@ import (
"golang.org/x/net/html" "golang.org/x/net/html"
"golang.org/x/net/html/atom" "golang.org/x/net/html/atom"
"k8s.io/kubernetes/pkg/util" "k8s.io/kubernetes/pkg/util/net"
"k8s.io/kubernetes/pkg/util/sets" "k8s.io/kubernetes/pkg/util/sets"
) )
@ -123,7 +123,7 @@ func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
return t.rewriteResponse(req, resp) return t.rewriteResponse(req, resp)
} }
var _ = util.RoundTripperWrapper(&Transport{}) var _ = net.RoundTripperWrapper(&Transport{})
func (rt *Transport) WrappedRoundTripper() http.RoundTripper { func (rt *Transport) WrappedRoundTripper() http.RoundTripper {
return rt.RoundTripper return rt.RoundTripper

View File

@ -17,13 +17,8 @@ limitations under the License.
package util package util
import ( import (
"bufio"
"encoding/hex"
"fmt" "fmt"
"io"
"math" "math"
"net"
"net/http"
"os" "os"
"reflect" "reflect"
"regexp" "regexp"
@ -203,249 +198,6 @@ func AllPtrFieldsNil(obj interface{}) bool {
return true return true
} }
type Route struct {
Interface string
Destination net.IP
Gateway net.IP
// TODO: add more fields here if needed
}
func getRoutes(input io.Reader) ([]Route, error) {
routes := []Route{}
if input == nil {
return nil, fmt.Errorf("input is nil")
}
scanner := bufio.NewReader(input)
for {
line, err := scanner.ReadString('\n')
if err == io.EOF {
break
}
//ignore the headers in the route info
if strings.HasPrefix(line, "Iface") {
continue
}
fields := strings.Fields(line)
routes = append(routes, Route{})
route := &routes[len(routes)-1]
route.Interface = fields[0]
ip, err := parseIP(fields[1])
if err != nil {
return nil, err
}
route.Destination = ip
ip, err = parseIP(fields[2])
if err != nil {
return nil, err
}
route.Gateway = ip
}
return routes, nil
}
func parseIP(str string) (net.IP, error) {
if str == "" {
return nil, fmt.Errorf("input is nil")
}
bytes, err := hex.DecodeString(str)
if err != nil {
return nil, err
}
//TODO add ipv6 support
if len(bytes) != net.IPv4len {
return nil, fmt.Errorf("only IPv4 is supported")
}
bytes[0], bytes[1], bytes[2], bytes[3] = bytes[3], bytes[2], bytes[1], bytes[0]
return net.IP(bytes), nil
}
func isInterfaceUp(intf *net.Interface) bool {
if intf == nil {
return false
}
if intf.Flags&net.FlagUp != 0 {
glog.V(4).Infof("Interface %v is up", intf.Name)
return true
}
return false
}
//getFinalIP method receives all the IP addrs of a Interface
//and returns a nil if the address is Loopback, Ipv6, link-local or nil.
//It returns a valid IPv4 if an Ipv4 address is found in the array.
func getFinalIP(addrs []net.Addr) (net.IP, error) {
if len(addrs) > 0 {
for i := range addrs {
glog.V(4).Infof("Checking addr %s.", addrs[i].String())
ip, _, err := net.ParseCIDR(addrs[i].String())
if err != nil {
return nil, err
}
//Only IPv4
//TODO : add IPv6 support
if ip.To4() != nil {
if !ip.IsLoopback() && !ip.IsLinkLocalMulticast() && !ip.IsLinkLocalUnicast() {
glog.V(4).Infof("IP found %v", ip)
return ip, nil
} else {
glog.V(4).Infof("Loopback/link-local found %v", ip)
}
} else {
glog.V(4).Infof("%v is not a valid IPv4 address", ip)
}
}
}
return nil, nil
}
func getIPFromInterface(intfName string, nw networkInterfacer) (net.IP, error) {
intf, err := nw.InterfaceByName(intfName)
if err != nil {
return nil, err
}
if isInterfaceUp(intf) {
addrs, err := nw.Addrs(intf)
if err != nil {
return nil, err
}
glog.V(4).Infof("Interface %q has %d addresses :%v.", intfName, len(addrs), addrs)
finalIP, err := getFinalIP(addrs)
if err != nil {
return nil, err
}
if finalIP != nil {
glog.V(4).Infof("valid IPv4 address for interface %q found as %v.", intfName, finalIP)
return finalIP, nil
}
}
return nil, nil
}
func flagsSet(flags net.Flags, test net.Flags) bool {
return flags&test != 0
}
func flagsClear(flags net.Flags, test net.Flags) bool {
return flags&test == 0
}
func chooseHostInterfaceNativeGo() (net.IP, error) {
intfs, err := net.Interfaces()
if err != nil {
return nil, err
}
i := 0
var ip net.IP
for i = range intfs {
if flagsSet(intfs[i].Flags, net.FlagUp) && flagsClear(intfs[i].Flags, net.FlagLoopback|net.FlagPointToPoint) {
addrs, err := intfs[i].Addrs()
if err != nil {
return nil, err
}
if len(addrs) > 0 {
for _, addr := range addrs {
if addrIP, _, err := net.ParseCIDR(addr.String()); err == nil {
if addrIP.To4() != nil {
ip = addrIP.To4()
if !ip.IsLinkLocalMulticast() && !ip.IsLinkLocalUnicast() {
break
}
}
}
}
if ip != nil {
// This interface should suffice.
break
}
}
}
}
if ip == nil {
return nil, fmt.Errorf("no acceptable interface from host")
}
glog.V(4).Infof("Choosing interface %s (IP %v) as default", intfs[i].Name, ip)
return ip, nil
}
//ChooseHostInterface is a method used fetch an IP for a daemon.
//It uses data from /proc/net/route file.
//For a node with no internet connection ,it returns error
//For a multi n/w interface node it returns the IP of the interface with gateway on it.
func ChooseHostInterface() (net.IP, error) {
inFile, err := os.Open("/proc/net/route")
if err != nil {
if os.IsNotExist(err) {
return chooseHostInterfaceNativeGo()
}
return nil, err
}
defer inFile.Close()
var nw networkInterfacer = networkInterface{}
return chooseHostInterfaceFromRoute(inFile, nw)
}
type networkInterfacer interface {
InterfaceByName(intfName string) (*net.Interface, error)
Addrs(intf *net.Interface) ([]net.Addr, error)
}
type networkInterface struct{}
func (_ networkInterface) InterfaceByName(intfName string) (*net.Interface, error) {
intf, err := net.InterfaceByName(intfName)
if err != nil {
return nil, err
}
return intf, nil
}
func (_ networkInterface) Addrs(intf *net.Interface) ([]net.Addr, error) {
addrs, err := intf.Addrs()
if err != nil {
return nil, err
}
return addrs, nil
}
func chooseHostInterfaceFromRoute(inFile io.Reader, nw networkInterfacer) (net.IP, error) {
routes, err := getRoutes(inFile)
if err != nil {
return nil, err
}
zero := net.IP{0, 0, 0, 0}
var finalIP net.IP
for i := range routes {
//find interface with gateway
if routes[i].Destination.Equal(zero) {
glog.V(4).Infof("Default route transits interface %q", routes[i].Interface)
finalIP, err := getIPFromInterface(routes[i].Interface, nw)
if err != nil {
return nil, err
}
if finalIP != nil {
glog.V(4).Infof("Choosing IP %v ", finalIP)
return finalIP, nil
}
}
}
glog.V(4).Infof("No valid IP found")
if finalIP == nil {
return nil, fmt.Errorf("Unable to select an IP.")
}
return nil, nil
}
func GetClient(req *http.Request) string {
if userAgent, ok := req.Header["User-Agent"]; ok {
if len(userAgent) > 0 {
return userAgent[0]
}
}
return "unknown"
}
func FileExists(filename string) (bool, error) { func FileExists(filename string) (bool, error) {
if _, err := os.Stat(filename); os.IsNotExist(err) { if _, err := os.Stat(filename); os.IsNotExist(err) {
return false, nil return false, nil
@ -486,17 +238,3 @@ func ReadDirNoExit(dirname string) ([]os.FileInfo, []error, error) {
return list, errs, nil return list, errs, nil
} }
// If bind-address is usable, return it directly
// If bind-address is not usable (unset, 0.0.0.0, or loopback), we will use the host's default
// interface.
func ValidPublicAddrForMaster(bindAddress net.IP) (net.IP, error) {
if bindAddress == nil || bindAddress.IsUnspecified() || bindAddress.IsLoopback() {
hostIP, err := ChooseHostInterface()
if err != nil {
return nil, err
}
bindAddress = hostIP
}
return bindAddress, nil
}

View File

@ -18,9 +18,6 @@ package util
import ( import (
"fmt" "fmt"
"io"
"net"
"strings"
"testing" "testing"
"time" "time"
) )
@ -182,278 +179,3 @@ func TestAllPtrFieldsNil(t *testing.T) {
} }
} }
} }
const gatewayfirst = `Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
eth3 00000000 0100FE0A 0003 0 0 1024 00000000 0 0 0
eth3 0000FE0A 00000000 0001 0 0 0 0080FFFF 0 0 0
docker0 000011AC 00000000 0001 0 0 0 0000FFFF 0 0 0
virbr0 007AA8C0 00000000 0001 0 0 0 00FFFFFF 0 0 0
`
const gatewaylast = `Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
docker0 000011AC 00000000 0001 0 0 0 0000FFFF 0 0 0
virbr0 007AA8C0 00000000 0001 0 0 0 00FFFFFF 0 0 0
eth3 0000FE0A 00000000 0001 0 0 0 0080FFFF 0 0 0
eth3 00000000 0100FE0A 0003 0 0 1024 00000000 0 0 0
`
const gatewaymiddle = `Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
eth3 0000FE0A 00000000 0001 0 0 0 0080FFFF 0 0 0
docker0 000011AC 00000000 0001 0 0 0 0000FFFF 0 0 0
eth3 00000000 0100FE0A 0003 0 0 1024 00000000 0 0 0
virbr0 007AA8C0 00000000 0001 0 0 0 00FFFFFF 0 0 0
`
const noInternetConnection = `Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
docker0 000011AC 00000000 0001 0 0 0 0000FFFF 0 0 0
virbr0 007AA8C0 00000000 0001 0 0 0 00FFFFFF 0 0 0
`
const nothing = `Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
`
const gatewayfirstIpv6_1 = `Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
eth3 00000000 0100FE0A 0003 0 0 1024 00000000 0 0 0
eth3 0000FE0AA1 00000000 0001 0 0 0 0080FFFF 0 0 0
docker0 000011AC 00000000 0001 0 0 0 0000FFFF 0 0 0
virbr0 007AA8C0 00000000 0001 0 0 0 00FFFFFF 0 0 0
`
const gatewayfirstIpv6_2 = `Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
eth3 00000000 0100FE0AA1 0003 0 0 1024 00000000 0 0 0
eth3 0000FE0A 00000000 0001 0 0 0 0080FFFF 0 0 0
docker0 000011AC 00000000 0001 0 0 0 0000FFFF 0 0 0
virbr0 007AA8C0 00000000 0001 0 0 0 00FFFFFF 0 0 0
`
const route_Invalidhex = `Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
eth3 00000000 0100FE0AA 0003 0 0 1024 00000000 0 0 0
eth3 0000FE0A 00000000 0001 0 0 0 0080FFFF 0 0 0
docker0 000011AC 00000000 0001 0 0 0 0000FFFF 0 0 0
virbr0 007AA8C0 00000000 0001 0 0 0 00FFFFFF 0 0 0
`
// Based on DigitalOcean COREOS
const gatewayfirstLinkLocal = `Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
eth0 00000000 0120372D 0001 0 0 0 00000000 0 0 0
eth0 00000000 00000000 0001 0 0 2048 00000000 0 0 0
`
func TestGetRoutes(t *testing.T) {
testCases := []struct {
tcase string
route string
expected int
}{
{"gatewayfirst", gatewayfirst, 4},
{"gatewaymiddle", gatewaymiddle, 4},
{"gatewaylast", gatewaylast, 4},
{"nothing", nothing, 0},
{"gatewayfirstIpv6_1", gatewayfirstIpv6_1, 0},
{"gatewayfirstIpv6_2", gatewayfirstIpv6_2, 0},
{"route_Invalidhex", route_Invalidhex, 0},
}
for _, tc := range testCases {
r := strings.NewReader(tc.route)
routes, err := getRoutes(r)
if len(routes) != tc.expected {
t.Errorf("case[%v]: expected %v, got %v .err : %v", tc.tcase, tc.expected, len(routes), err)
}
}
}
func TestParseIP(t *testing.T) {
testCases := []struct {
tcase string
ip string
success bool
expected net.IP
}{
{"empty", "", false, nil},
{"too short", "AA", false, nil},
{"too long", "0011223344", false, nil},
{"invalid", "invalid!", false, nil},
{"zero", "00000000", true, net.IP{0, 0, 0, 0}},
{"ffff", "FFFFFFFF", true, net.IP{0xff, 0xff, 0xff, 0xff}},
{"valid", "12345678", true, net.IP{120, 86, 52, 18}},
}
for _, tc := range testCases {
ip, err := parseIP(tc.ip)
if !ip.Equal(tc.expected) {
t.Errorf("case[%v]: expected %q, got %q . err : %v", tc.tcase, tc.expected, ip, err)
}
}
}
func TestIsInterfaceUp(t *testing.T) {
testCases := []struct {
tcase string
intf net.Interface
expected bool
}{
{"up", net.Interface{Index: 0, MTU: 0, Name: "eth3", HardwareAddr: nil, Flags: net.FlagUp}, true},
{"down", net.Interface{Index: 0, MTU: 0, Name: "eth3", HardwareAddr: nil, Flags: 0}, false},
{"nothing", net.Interface{}, false},
}
for _, tc := range testCases {
it := isInterfaceUp(&tc.intf)
if it != tc.expected {
t.Errorf("case[%v]: expected %v, got %v .", tc.tcase, tc.expected, it)
}
}
}
type addrStruct struct{ val string }
func (a addrStruct) Network() string {
return a.val
}
func (a addrStruct) String() string {
return a.val
}
func TestFinalIP(t *testing.T) {
testCases := []struct {
tcase string
addr []net.Addr
expected net.IP
}{
{"ipv6", []net.Addr{addrStruct{val: "fe80::2f7:6fff:fe6e:2956/64"}}, nil},
{"invalidCIDR", []net.Addr{addrStruct{val: "fe80::2f7:67fff:fe6e:2956/64"}}, nil},
{"loopback", []net.Addr{addrStruct{val: "127.0.0.1/24"}}, nil},
{"ip4", []net.Addr{addrStruct{val: "10.254.12.132/17"}}, net.ParseIP("10.254.12.132")},
{"nothing", []net.Addr{}, nil},
}
for _, tc := range testCases {
ip, err := getFinalIP(tc.addr)
if !ip.Equal(tc.expected) {
t.Errorf("case[%v]: expected %v, got %v .err : %v", tc.tcase, tc.expected, ip, err)
}
}
}
func TestAddrs(t *testing.T) {
var nw networkInterfacer = validNetworkInterface{}
intf := net.Interface{Index: 0, MTU: 0, Name: "eth3", HardwareAddr: nil, Flags: 0}
addrs, err := nw.Addrs(&intf)
if err != nil {
t.Errorf("expected no error got : %v", err)
}
if len(addrs) != 2 {
t.Errorf("expected addrs: 2 got null")
}
}
type validNetworkInterface struct {
}
func (_ validNetworkInterface) InterfaceByName(intfName string) (*net.Interface, error) {
c := net.Interface{Index: 0, MTU: 0, Name: "eth3", HardwareAddr: nil, Flags: net.FlagUp}
return &c, nil
}
func (_ validNetworkInterface) Addrs(intf *net.Interface) ([]net.Addr, error) {
var ifat []net.Addr
ifat = []net.Addr{
addrStruct{val: "fe80::2f7:6fff:fe6e:2956/64"}, addrStruct{val: "10.254.71.145/17"}}
return ifat, nil
}
type validNetworkInterfaceWithLinkLocal struct {
}
func (_ validNetworkInterfaceWithLinkLocal) InterfaceByName(intfName string) (*net.Interface, error) {
c := net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: net.FlagUp}
return &c, nil
}
func (_ validNetworkInterfaceWithLinkLocal) Addrs(intf *net.Interface) ([]net.Addr, error) {
var ifat []net.Addr
ifat = []net.Addr{addrStruct{val: "169.254.162.166/16"}, addrStruct{val: "45.55.47.146/19"}}
return ifat, nil
}
type validNetworkInterfacewithIpv6Only struct {
}
func (_ validNetworkInterfacewithIpv6Only) InterfaceByName(intfName string) (*net.Interface, error) {
c := net.Interface{Index: 0, MTU: 0, Name: "eth3", HardwareAddr: nil, Flags: net.FlagUp}
return &c, nil
}
func (_ validNetworkInterfacewithIpv6Only) Addrs(intf *net.Interface) ([]net.Addr, error) {
var ifat []net.Addr
ifat = []net.Addr{addrStruct{val: "fe80::2f7:6fff:fe6e:2956/64"}}
return ifat, nil
}
type noNetworkInterface struct {
}
func (_ noNetworkInterface) InterfaceByName(intfName string) (*net.Interface, error) {
return nil, fmt.Errorf("unable get Interface")
}
func (_ noNetworkInterface) Addrs(intf *net.Interface) ([]net.Addr, error) {
return nil, nil
}
type networkInterfacewithNoAddrs struct {
}
func (_ networkInterfacewithNoAddrs) InterfaceByName(intfName string) (*net.Interface, error) {
c := net.Interface{Index: 0, MTU: 0, Name: "eth3", HardwareAddr: nil, Flags: net.FlagUp}
return &c, nil
}
func (_ networkInterfacewithNoAddrs) Addrs(intf *net.Interface) ([]net.Addr, error) {
return nil, fmt.Errorf("unable get Addrs")
}
type networkInterfacewithIpv6addrs struct {
}
func (_ networkInterfacewithIpv6addrs) InterfaceByName(intfName string) (*net.Interface, error) {
c := net.Interface{Index: 0, MTU: 0, Name: "eth3", HardwareAddr: nil, Flags: net.FlagUp}
return &c, nil
}
func (_ networkInterfacewithIpv6addrs) Addrs(intf *net.Interface) ([]net.Addr, error) {
var ifat []net.Addr
ifat = []net.Addr{addrStruct{val: "fe80::2f7:6ffff:fe6e:2956/64"}}
return ifat, nil
}
func TestGetIPFromInterface(t *testing.T) {
testCases := []struct {
tcase string
nwname string
nw networkInterfacer
expected net.IP
}{
{"valid", "eth3", validNetworkInterface{}, net.ParseIP("10.254.71.145")},
{"ipv6", "eth3", validNetworkInterfacewithIpv6Only{}, nil},
{"nothing", "eth3", noNetworkInterface{}, nil},
}
for _, tc := range testCases {
ip, err := getIPFromInterface(tc.nwname, tc.nw)
if !ip.Equal(tc.expected) {
t.Errorf("case[%v]: expected %v, got %+v .err : %v", tc.tcase, tc.expected, ip, err)
}
}
}
func TestChooseHostInterfaceFromRoute(t *testing.T) {
testCases := []struct {
tcase string
inFile io.Reader
nw networkInterfacer
expected net.IP
}{
{"valid_routefirst", strings.NewReader(gatewayfirst), validNetworkInterface{}, net.ParseIP("10.254.71.145")},
{"valid_routelast", strings.NewReader(gatewaylast), validNetworkInterface{}, net.ParseIP("10.254.71.145")},
{"valid_routemiddle", strings.NewReader(gatewaymiddle), validNetworkInterface{}, net.ParseIP("10.254.71.145")},
{"valid_routemiddle_ipv6", strings.NewReader(gatewaymiddle), validNetworkInterfacewithIpv6Only{}, nil},
{"no internet connection", strings.NewReader(noInternetConnection), validNetworkInterface{}, nil},
{"no non-link-local ip", strings.NewReader(gatewayfirstLinkLocal), validNetworkInterfaceWithLinkLocal{}, net.ParseIP("45.55.47.146")},
{"no route", strings.NewReader(nothing), validNetworkInterface{}, nil},
{"no route file", nil, validNetworkInterface{}, nil},
{"no interfaces", nil, noNetworkInterface{}, nil},
{"no interface Addrs", strings.NewReader(gatewaymiddle), networkInterfacewithNoAddrs{}, nil},
{"Invalid Addrs", strings.NewReader(gatewaymiddle), networkInterfacewithIpv6addrs{}, nil},
}
for _, tc := range testCases {
ip, err := chooseHostInterfaceFromRoute(tc.inFile, tc.nw)
if !ip.Equal(tc.expected) {
t.Errorf("case[%v]: expected %v, got %+v .err : %v", tc.tcase, tc.expected, ip, err)
}
}
}

View File

@ -23,6 +23,7 @@ import (
"github.com/golang/glog" "github.com/golang/glog"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util" "k8s.io/kubernetes/pkg/util"
"k8s.io/kubernetes/pkg/util/net"
) )
// Decoder allows StreamWatcher to watch any stream for which a Decoder can be written. // Decoder allows StreamWatcher to watch any stream for which a Decoder can be written.
@ -102,7 +103,7 @@ func (sw *StreamWatcher) receive() {
glog.V(1).Infof("Unexpected EOF during watch stream event decoding: %v", err) glog.V(1).Infof("Unexpected EOF during watch stream event decoding: %v", err)
default: default:
msg := "Unable to decode an event from the watch stream: %v" msg := "Unable to decode an event from the watch stream: %v"
if util.IsProbableEOF(err) { if net.IsProbableEOF(err) {
glog.V(5).Infof(msg, err) glog.V(5).Infof(msg, err)
} else { } else {
glog.Errorf(msg, err) glog.Errorf(msg, err)

View File

@ -30,6 +30,7 @@ import (
"github.com/golang/glog" "github.com/golang/glog"
"k8s.io/kubernetes/pkg/auth/user" "k8s.io/kubernetes/pkg/auth/user"
"k8s.io/kubernetes/pkg/util" "k8s.io/kubernetes/pkg/util"
"k8s.io/kubernetes/pkg/util/net"
) )
var ( var (
@ -72,7 +73,7 @@ func New(issuerURL, clientID, caFile, usernameClaim string) (*OIDCAuthenticator,
} }
// Copied from http.DefaultTransport. // Copied from http.DefaultTransport.
tr := util.SetTransportDefaults(&http.Transport{ tr := net.SetTransportDefaults(&http.Transport{
// According to golang's doc, if RootCAs is nil, // According to golang's doc, if RootCAs is nil,
// TLS uses the host's root CA set. // TLS uses the host's root CA set.
TLSClientConfig: &tls.Config{RootCAs: roots}, TLSClientConfig: &tls.Config{RootCAs: roots},

View File

@ -27,8 +27,8 @@ import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/api/testapi"
client "k8s.io/kubernetes/pkg/client/unversioned" client "k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/kubernetes/pkg/util"
"k8s.io/kubernetes/pkg/util/intstr" "k8s.io/kubernetes/pkg/util/intstr"
"k8s.io/kubernetes/pkg/util/net"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
@ -133,13 +133,13 @@ func proxyContext(version string) {
// Try proxying through the service and directly to through the pod. // Try proxying through the service and directly to through the pod.
svcProxyURL := func(scheme, port string) string { svcProxyURL := func(scheme, port string) string {
return prefix + "/proxy/namespaces/" + f.Namespace.Name + "/services/" + util.JoinSchemeNamePort(scheme, service.Name, port) return prefix + "/proxy/namespaces/" + f.Namespace.Name + "/services/" + net.JoinSchemeNamePort(scheme, service.Name, port)
} }
podProxyURL := func(scheme, port string) string { podProxyURL := func(scheme, port string) string {
return prefix + "/proxy/namespaces/" + f.Namespace.Name + "/pods/" + util.JoinSchemeNamePort(scheme, pods[0].Name, port) return prefix + "/proxy/namespaces/" + f.Namespace.Name + "/pods/" + net.JoinSchemeNamePort(scheme, pods[0].Name, port)
} }
subresourcePodProxyURL := func(scheme, port string) string { subresourcePodProxyURL := func(scheme, port string) string {
return prefix + "/namespaces/" + f.Namespace.Name + "/pods/" + util.JoinSchemeNamePort(scheme, pods[0].Name, port) + "/proxy" return prefix + "/namespaces/" + f.Namespace.Name + "/pods/" + net.JoinSchemeNamePort(scheme, pods[0].Name, port) + "/proxy"
} }
expectations := map[string]string{ expectations := map[string]string{
svcProxyURL("", "portname1") + "/": "foo", svcProxyURL("", "portname1") + "/": "foo",

View File

@ -35,12 +35,13 @@ import (
"k8s.io/kubernetes/pkg/types" "k8s.io/kubernetes/pkg/types"
"k8s.io/kubernetes/pkg/util" "k8s.io/kubernetes/pkg/util"
"k8s.io/kubernetes/pkg/util/intstr" "k8s.io/kubernetes/pkg/util/intstr"
utilnet "k8s.io/kubernetes/pkg/util/net"
"k8s.io/kubernetes/pkg/util/sets" "k8s.io/kubernetes/pkg/util/sets"
"k8s.io/kubernetes/pkg/util/wait" "k8s.io/kubernetes/pkg/util/wait"
) )
// This should match whatever the default/configured range is // This should match whatever the default/configured range is
var ServiceNodePortRange = util.PortRange{Base: 30000, Size: 2768} var ServiceNodePortRange = utilnet.PortRange{Base: 30000, Size: 2768}
var _ = Describe("Services", func() { var _ = Describe("Services", func() {
f := NewFramework("services") f := NewFramework("services")