mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 11:50:44 +00:00
kubelet: Set dual-stack hostNetwork pod IPs on dual-stack nodes
Add nodeutil.GetNodeHostIPs to return dual-stack node IPs (in dual-stack clusters), and make kubelet use it.
This commit is contained in:
parent
0b43753be7
commit
971477d9b5
@ -262,23 +262,23 @@ func (kl *Kubelet) GetPodCgroupRoot() string {
|
||||
return kl.containerManager.GetPodCgroupRoot()
|
||||
}
|
||||
|
||||
// GetHostIP returns host IP or nil in case of error.
|
||||
func (kl *Kubelet) GetHostIP() (net.IP, error) {
|
||||
// GetHostIPs returns host IPs or nil in case of error.
|
||||
func (kl *Kubelet) GetHostIPs() ([]net.IP, error) {
|
||||
node, err := kl.GetNode()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot get node: %v", err)
|
||||
}
|
||||
return utilnode.GetNodeHostIP(node)
|
||||
return utilnode.GetNodeHostIPs(node)
|
||||
}
|
||||
|
||||
// getHostIPAnyway attempts to return the host IP from kubelet's nodeInfo, or
|
||||
// getHostIPsAnyWay attempts to return the host IPs from kubelet's nodeInfo, or
|
||||
// the initialNode.
|
||||
func (kl *Kubelet) getHostIPAnyWay() (net.IP, error) {
|
||||
func (kl *Kubelet) getHostIPsAnyWay() ([]net.IP, error) {
|
||||
node, err := kl.getNodeAnyWay()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return utilnode.GetNodeHostIP(node)
|
||||
return utilnode.GetNodeHostIPs(node)
|
||||
}
|
||||
|
||||
// GetExtraSupplementalGroupsForPod returns a list of the extra
|
||||
|
@ -811,11 +811,11 @@ func (kl *Kubelet) podFieldSelectorRuntimeValue(fs *v1.ObjectFieldSelector, pod
|
||||
case "spec.serviceAccountName":
|
||||
return pod.Spec.ServiceAccountName, nil
|
||||
case "status.hostIP":
|
||||
hostIP, err := kl.getHostIPAnyWay()
|
||||
hostIPs, err := kl.getHostIPsAnyWay()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return hostIP.String(), nil
|
||||
return hostIPs[0].String(), nil
|
||||
case "status.podIP":
|
||||
return podIP, nil
|
||||
case "status.podIPs":
|
||||
@ -1531,14 +1531,17 @@ func (kl *Kubelet) generateAPIPodStatus(pod *v1.Pod, podStatus *kubecontainer.Po
|
||||
})
|
||||
|
||||
if kl.kubeClient != nil {
|
||||
hostIP, err := kl.getHostIPAnyWay()
|
||||
hostIPs, err := kl.getHostIPsAnyWay()
|
||||
if err != nil {
|
||||
klog.V(4).Infof("Cannot get host IP: %v", err)
|
||||
klog.V(4).Infof("Cannot get host IPs: %v", err)
|
||||
} else {
|
||||
s.HostIP = hostIP.String()
|
||||
s.HostIP = hostIPs[0].String()
|
||||
if kubecontainer.IsHostNetworkPod(pod) && s.PodIP == "" {
|
||||
s.PodIP = hostIP.String()
|
||||
s.PodIP = hostIPs[0].String()
|
||||
s.PodIPs = []v1.PodIP{{IP: s.PodIP}}
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.IPv6DualStack) && len(hostIPs) == 2 {
|
||||
s.PodIPs = append(s.PodIPs, v1.PodIP{IP: hostIPs[1].String()})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"sort"
|
||||
"testing"
|
||||
|
||||
@ -2489,3 +2490,126 @@ func TestPodResourcesAreReclaimed(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateAPIPodStatusHostNetworkPodIPs(t *testing.T) {
|
||||
testcases := []struct {
|
||||
name string
|
||||
dualStack bool
|
||||
nodeAddresses []v1.NodeAddress
|
||||
criPodIPs []string
|
||||
podIPs []v1.PodIP
|
||||
}{
|
||||
{
|
||||
name: "Simple",
|
||||
nodeAddresses: []v1.NodeAddress{
|
||||
{Type: v1.NodeInternalIP, Address: "10.0.0.1"},
|
||||
},
|
||||
podIPs: []v1.PodIP{
|
||||
{IP: "10.0.0.1"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "InternalIP is preferred over ExternalIP",
|
||||
nodeAddresses: []v1.NodeAddress{
|
||||
{Type: v1.NodeExternalIP, Address: "192.168.0.1"},
|
||||
{Type: v1.NodeInternalIP, Address: "10.0.0.1"},
|
||||
},
|
||||
podIPs: []v1.PodIP{
|
||||
{IP: "10.0.0.1"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Dual-stack addresses are ignored in single-stack cluster",
|
||||
nodeAddresses: []v1.NodeAddress{
|
||||
{Type: v1.NodeInternalIP, Address: "10.0.0.1"},
|
||||
{Type: v1.NodeInternalIP, Address: "fd01::1234"},
|
||||
},
|
||||
podIPs: []v1.PodIP{
|
||||
{IP: "10.0.0.1"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Single-stack addresses in dual-stack cluster",
|
||||
nodeAddresses: []v1.NodeAddress{
|
||||
{Type: v1.NodeInternalIP, Address: "10.0.0.1"},
|
||||
},
|
||||
dualStack: true,
|
||||
podIPs: []v1.PodIP{
|
||||
{IP: "10.0.0.1"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Multiple single-stack addresses in dual-stack cluster",
|
||||
nodeAddresses: []v1.NodeAddress{
|
||||
{Type: v1.NodeInternalIP, Address: "10.0.0.1"},
|
||||
{Type: v1.NodeInternalIP, Address: "10.0.0.2"},
|
||||
{Type: v1.NodeExternalIP, Address: "192.168.0.1"},
|
||||
},
|
||||
dualStack: true,
|
||||
podIPs: []v1.PodIP{
|
||||
{IP: "10.0.0.1"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Dual-stack addresses in dual-stack cluster",
|
||||
nodeAddresses: []v1.NodeAddress{
|
||||
{Type: v1.NodeInternalIP, Address: "10.0.0.1"},
|
||||
{Type: v1.NodeInternalIP, Address: "fd01::1234"},
|
||||
},
|
||||
dualStack: true,
|
||||
podIPs: []v1.PodIP{
|
||||
{IP: "10.0.0.1"},
|
||||
{IP: "fd01::1234"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CRI PodIPs override NodeAddresses",
|
||||
nodeAddresses: []v1.NodeAddress{
|
||||
{Type: v1.NodeInternalIP, Address: "10.0.0.1"},
|
||||
{Type: v1.NodeInternalIP, Address: "fd01::1234"},
|
||||
},
|
||||
dualStack: true,
|
||||
criPodIPs: []string{"192.168.0.1"},
|
||||
podIPs: []v1.PodIP{
|
||||
{IP: "192.168.0.1"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */)
|
||||
defer testKubelet.Cleanup()
|
||||
kl := testKubelet.kubelet
|
||||
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.IPv6DualStack, tc.dualStack)()
|
||||
|
||||
kl.nodeLister = testNodeLister{nodes: []*v1.Node{
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: string(kl.nodeName)},
|
||||
Status: v1.NodeStatus{
|
||||
Addresses: tc.nodeAddresses,
|
||||
},
|
||||
},
|
||||
}}
|
||||
|
||||
pod := podWithUIDNameNs("12345", "test-pod", "test-namespace")
|
||||
pod.Spec.HostNetwork = true
|
||||
|
||||
criStatus := &kubecontainer.PodStatus{
|
||||
ID: pod.UID,
|
||||
Name: pod.Name,
|
||||
Namespace: pod.Namespace,
|
||||
IPs: tc.criPodIPs,
|
||||
}
|
||||
|
||||
status := kl.generateAPIPodStatus(pod, criStatus)
|
||||
if !reflect.DeepEqual(status.PodIPs, tc.podIPs) {
|
||||
t.Fatalf("Expected PodIPs %#v, got %#v", tc.podIPs, status.PodIPs)
|
||||
}
|
||||
if tc.criPodIPs == nil && status.HostIP != status.PodIPs[0].IP {
|
||||
t.Fatalf("Expected HostIP %q to equal PodIPs[0].IP %q", status.HostIP, status.PodIPs[0].IP)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -231,7 +231,11 @@ func (kvh *kubeletVolumeHost) GetHostName() string {
|
||||
}
|
||||
|
||||
func (kvh *kubeletVolumeHost) GetHostIP() (net.IP, error) {
|
||||
return kvh.kubelet.GetHostIP()
|
||||
hostIPs, err := kvh.kubelet.GetHostIPs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return hostIPs[0], err
|
||||
}
|
||||
|
||||
func (kvh *kubeletVolumeHost) GetNodeAllocatable() (v1.ResourceList, error) {
|
||||
|
@ -11,15 +11,18 @@ go_library(
|
||||
srcs = ["node.go"],
|
||||
importpath = "k8s.io/kubernetes/pkg/util/node",
|
||||
deps = [
|
||||
"//pkg/features:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/strategicpatch:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/klog/v2:go_default_library",
|
||||
"//vendor/k8s.io/utils/net:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@ -28,8 +31,11 @@ go_test(
|
||||
srcs = ["node_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/features:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/component-base/featuregate/testing:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
@ -33,8 +33,11 @@ import (
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/strategicpatch"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
v1core "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
utilnet "k8s.io/utils/net"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -90,22 +93,55 @@ func GetPreferredNodeAddress(node *v1.Node, preferredAddressTypes []v1.NodeAddre
|
||||
return "", &NoMatchError{addresses: node.Status.Addresses}
|
||||
}
|
||||
|
||||
// GetNodeHostIP returns the provided node's IP, based on the priority:
|
||||
// 1. NodeInternalIP
|
||||
// 2. NodeExternalIP
|
||||
// GetNodeHostIPs returns the provided node's IP(s); either a single "primary IP" for the
|
||||
// node in a single-stack cluster, or a dual-stack pair of IPs in a dual-stack cluster
|
||||
// (for nodes that actually have dual-stack IPs). Among other things, the IPs returned
|
||||
// from this function are used as the `.status.PodIPs` values for host-network pods on the
|
||||
// node, and the first IP is used as the `.status.HostIP` for all pods on the node.
|
||||
func GetNodeHostIPs(node *v1.Node) ([]net.IP, error) {
|
||||
// Re-sort the addresses with InternalIPs first and then ExternalIPs
|
||||
allIPs := make([]net.IP, 0, len(node.Status.Addresses))
|
||||
for _, addr := range node.Status.Addresses {
|
||||
if addr.Type == v1.NodeInternalIP {
|
||||
ip := net.ParseIP(addr.Address)
|
||||
if ip != nil {
|
||||
allIPs = append(allIPs, ip)
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, addr := range node.Status.Addresses {
|
||||
if addr.Type == v1.NodeExternalIP {
|
||||
ip := net.ParseIP(addr.Address)
|
||||
if ip != nil {
|
||||
allIPs = append(allIPs, ip)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(allIPs) == 0 {
|
||||
return nil, fmt.Errorf("host IP unknown; known addresses: %v", node.Status.Addresses)
|
||||
}
|
||||
|
||||
nodeIPs := []net.IP{allIPs[0]}
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.IPv6DualStack) {
|
||||
for _, ip := range allIPs {
|
||||
if utilnet.IsIPv6(ip) != utilnet.IsIPv6(nodeIPs[0]) {
|
||||
nodeIPs = append(nodeIPs, ip)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nodeIPs, nil
|
||||
}
|
||||
|
||||
// GetNodeHostIP returns the provided node's "primary" IP; see GetNodeHostIPs for more details
|
||||
func GetNodeHostIP(node *v1.Node) (net.IP, error) {
|
||||
addresses := node.Status.Addresses
|
||||
addressMap := make(map[v1.NodeAddressType][]v1.NodeAddress)
|
||||
for i := range addresses {
|
||||
addressMap[addresses[i].Type] = append(addressMap[addresses[i].Type], addresses[i])
|
||||
ips, err := GetNodeHostIPs(node)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if addresses, ok := addressMap[v1.NodeInternalIP]; ok {
|
||||
return net.ParseIP(addresses[0].Address), nil
|
||||
}
|
||||
if addresses, ok := addressMap[v1.NodeExternalIP]; ok {
|
||||
return net.ParseIP(addresses[0].Address), nil
|
||||
}
|
||||
return nil, fmt.Errorf("host IP unknown; known addresses: %v", addresses)
|
||||
// GetNodeHostIPs always returns at least one IP if it didn't return an error
|
||||
return ips[0], nil
|
||||
}
|
||||
|
||||
// GetNodeIP returns an IP (as with GetNodeHostIP) for the node with the provided name.
|
||||
|
@ -17,10 +17,15 @@ limitations under the License.
|
||||
package node
|
||||
|
||||
import (
|
||||
"net"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
)
|
||||
|
||||
func TestGetPreferredAddress(t *testing.T) {
|
||||
@ -89,6 +94,147 @@ func TestGetPreferredAddress(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetNodeHostIPs(t *testing.T) {
|
||||
testcases := []struct {
|
||||
name string
|
||||
addresses []v1.NodeAddress
|
||||
dualStack bool
|
||||
|
||||
expectIPs []net.IP
|
||||
}{
|
||||
{
|
||||
name: "no addresses",
|
||||
expectIPs: nil,
|
||||
},
|
||||
{
|
||||
name: "no InternalIP/ExternalIP",
|
||||
addresses: []v1.NodeAddress{
|
||||
{Type: v1.NodeHostName, Address: "example.com"},
|
||||
},
|
||||
expectIPs: nil,
|
||||
},
|
||||
{
|
||||
name: "IPv4-only, simple",
|
||||
addresses: []v1.NodeAddress{
|
||||
{Type: v1.NodeInternalIP, Address: "1.2.3.4"},
|
||||
{Type: v1.NodeExternalIP, Address: "4.3.2.1"},
|
||||
{Type: v1.NodeExternalIP, Address: "4.3.2.2"},
|
||||
},
|
||||
expectIPs: []net.IP{net.ParseIP("1.2.3.4")},
|
||||
},
|
||||
{
|
||||
name: "IPv4-only, external-first",
|
||||
addresses: []v1.NodeAddress{
|
||||
{Type: v1.NodeExternalIP, Address: "4.3.2.1"},
|
||||
{Type: v1.NodeExternalIP, Address: "4.3.2.2"},
|
||||
{Type: v1.NodeInternalIP, Address: "1.2.3.4"},
|
||||
},
|
||||
expectIPs: []net.IP{net.ParseIP("1.2.3.4")},
|
||||
},
|
||||
{
|
||||
name: "IPv4-only, no internal",
|
||||
addresses: []v1.NodeAddress{
|
||||
{Type: v1.NodeExternalIP, Address: "4.3.2.1"},
|
||||
{Type: v1.NodeExternalIP, Address: "4.3.2.2"},
|
||||
},
|
||||
expectIPs: []net.IP{net.ParseIP("4.3.2.1")},
|
||||
},
|
||||
{
|
||||
name: "dual-stack node, single-stack cluster",
|
||||
addresses: []v1.NodeAddress{
|
||||
{Type: v1.NodeInternalIP, Address: "1.2.3.4"},
|
||||
{Type: v1.NodeExternalIP, Address: "4.3.2.1"},
|
||||
{Type: v1.NodeExternalIP, Address: "4.3.2.2"},
|
||||
{Type: v1.NodeInternalIP, Address: "a:b::c:d"},
|
||||
{Type: v1.NodeExternalIP, Address: "d:c::b:a"},
|
||||
},
|
||||
expectIPs: []net.IP{net.ParseIP("1.2.3.4")},
|
||||
},
|
||||
{
|
||||
name: "dual-stack node, dual-stack cluster",
|
||||
addresses: []v1.NodeAddress{
|
||||
{Type: v1.NodeInternalIP, Address: "1.2.3.4"},
|
||||
{Type: v1.NodeExternalIP, Address: "4.3.2.1"},
|
||||
{Type: v1.NodeExternalIP, Address: "4.3.2.2"},
|
||||
{Type: v1.NodeInternalIP, Address: "a:b::c:d"},
|
||||
{Type: v1.NodeExternalIP, Address: "d:c::b:a"},
|
||||
},
|
||||
dualStack: true,
|
||||
expectIPs: []net.IP{net.ParseIP("1.2.3.4"), net.ParseIP("a:b::c:d")},
|
||||
},
|
||||
{
|
||||
name: "dual-stack node, different order, single-stack cluster",
|
||||
addresses: []v1.NodeAddress{
|
||||
{Type: v1.NodeInternalIP, Address: "1.2.3.4"},
|
||||
{Type: v1.NodeInternalIP, Address: "a:b::c:d"},
|
||||
{Type: v1.NodeExternalIP, Address: "4.3.2.1"},
|
||||
{Type: v1.NodeExternalIP, Address: "4.3.2.2"},
|
||||
{Type: v1.NodeExternalIP, Address: "d:c::b:a"},
|
||||
},
|
||||
expectIPs: []net.IP{net.ParseIP("1.2.3.4")},
|
||||
},
|
||||
{
|
||||
name: "dual-stack node, different order, dual-stack cluster",
|
||||
addresses: []v1.NodeAddress{
|
||||
{Type: v1.NodeInternalIP, Address: "1.2.3.4"},
|
||||
{Type: v1.NodeInternalIP, Address: "a:b::c:d"},
|
||||
{Type: v1.NodeExternalIP, Address: "4.3.2.1"},
|
||||
{Type: v1.NodeExternalIP, Address: "4.3.2.2"},
|
||||
{Type: v1.NodeExternalIP, Address: "d:c::b:a"},
|
||||
},
|
||||
dualStack: true,
|
||||
expectIPs: []net.IP{net.ParseIP("1.2.3.4"), net.ParseIP("a:b::c:d")},
|
||||
},
|
||||
{
|
||||
name: "dual-stack node, IPv6-first, no internal IPv4, single-stack cluster",
|
||||
addresses: []v1.NodeAddress{
|
||||
{Type: v1.NodeInternalIP, Address: "a:b::c:d"},
|
||||
{Type: v1.NodeExternalIP, Address: "d:c::b:a"},
|
||||
{Type: v1.NodeExternalIP, Address: "4.3.2.1"},
|
||||
{Type: v1.NodeExternalIP, Address: "4.3.2.2"},
|
||||
},
|
||||
expectIPs: []net.IP{net.ParseIP("a:b::c:d")},
|
||||
},
|
||||
{
|
||||
name: "dual-stack node, IPv6-first, no internal IPv4, dual-stack cluster",
|
||||
addresses: []v1.NodeAddress{
|
||||
{Type: v1.NodeInternalIP, Address: "a:b::c:d"},
|
||||
{Type: v1.NodeExternalIP, Address: "d:c::b:a"},
|
||||
{Type: v1.NodeExternalIP, Address: "4.3.2.1"},
|
||||
{Type: v1.NodeExternalIP, Address: "4.3.2.2"},
|
||||
},
|
||||
dualStack: true,
|
||||
expectIPs: []net.IP{net.ParseIP("a:b::c:d"), net.ParseIP("4.3.2.1")},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.IPv6DualStack, tc.dualStack)()
|
||||
node := &v1.Node{
|
||||
Status: v1.NodeStatus{Addresses: tc.addresses},
|
||||
}
|
||||
nodeIPs, err := GetNodeHostIPs(node)
|
||||
nodeIP, err2 := GetNodeHostIP(node)
|
||||
|
||||
if (err == nil && err2 != nil) || (err != nil && err2 == nil) {
|
||||
t.Errorf("GetNodeHostIPs() returned error=%q but GetNodeHostIP() returned error=%q", err, err2)
|
||||
}
|
||||
if err != nil {
|
||||
if tc.expectIPs != nil {
|
||||
t.Errorf("expected %v, got error (%v)", tc.expectIPs, err)
|
||||
}
|
||||
} else if tc.expectIPs == nil {
|
||||
t.Errorf("expected error, got %v", nodeIPs)
|
||||
} else if !reflect.DeepEqual(nodeIPs, tc.expectIPs) {
|
||||
t.Errorf("expected %v, got %v", tc.expectIPs, nodeIPs)
|
||||
} else if !nodeIP.Equal(nodeIPs[0]) {
|
||||
t.Errorf("GetNodeHostIP did not return same primary (%s) as GetNodeHostIPs (%s)", nodeIP.String(), nodeIPs[0].String())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetHostname(t *testing.T) {
|
||||
testCases := []struct {
|
||||
hostName string
|
||||
|
Loading…
Reference in New Issue
Block a user