Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions internal/ingress/status/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,9 +225,11 @@ func (s *statusSync) runningAddresses() ([]v1.IngressLoadBalancerIngress, error)
continue
}

name := k8s.GetNodeIPOrName(s.Client, pod.Spec.NodeName, s.UseNodeInternalIP)
if !stringInIngresses(name, addrs) {
addrs = append(addrs, nameOrIPToLoadBalancerIngress(name))
theseAddresses := k8s.GetNodeIPs(s.Client, pod.Spec.NodeName, s.UseNodeInternalIP)
for _, thisAddress := range theseAddresses {
if !stringInIngresses(thisAddress, addrs) {
addrs = append(addrs, nameOrIPToLoadBalancerIngress(thisAddress))
}
}
}

Expand Down
34 changes: 14 additions & 20 deletions internal/k8s/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,37 +42,31 @@ func ParseNameNS(input string) (ns, name string, err error) {
return nsName[0], nsName[1], nil
}

// GetNodeIPOrName returns the IP address or the name of a node in the cluster
func GetNodeIPOrName(kubeClient clientset.Interface, name string, useInternalIP bool) string {
// GetNodeIPs returns the IP addresses of a node in the cluster
func GetNodeIPs(kubeClient clientset.Interface, name string, useInternalIP bool) []string {
node, err := kubeClient.CoreV1().Nodes().Get(context.TODO(), name, metav1.GetOptions{})
if err != nil {
klog.ErrorS(err, "Error getting node", "name", name)
return ""
return []string{}
}

defaultOrInternalIP := ""
externalIPs := []string{}
internalIPs := []string{}

for _, address := range node.Status.Addresses {
if address.Type == apiv1.NodeInternalIP {
if address.Address != "" {
defaultOrInternalIP = address.Address
break
}
if address.Type == apiv1.NodeInternalIP && address.Address != "" {
internalIPs = append(internalIPs, address.Address)
}
if address.Type == apiv1.NodeExternalIP && address.Address != "" {
externalIPs = append(externalIPs, address.Address)
}
}

if useInternalIP {
return defaultOrInternalIP
}

for _, address := range node.Status.Addresses {
if address.Type == apiv1.NodeExternalIP {
if address.Address != "" {
return address.Address
}
}
if useInternalIP || len(externalIPs) == 0 {
return internalIPs
}

return defaultOrInternalIP
return externalIPs
}

var (
Expand Down
133 changes: 117 additions & 16 deletions internal/k8s/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package k8s

import (
"slices"
"testing"

apiv1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -60,13 +61,15 @@ func TestGetNodeIP(t *testing.T) {
name string
cs *testclient.Clientset
nodeName string
ea string
ea []string
useInternalIP bool
}{
{
"empty node list",
testclient.NewSimpleClientset(),
"demo", "", true,
"demo",
[]string{},
true,
},
{
"node does not exist",
Expand All @@ -82,10 +85,12 @@ func TestGetNodeIP(t *testing.T) {
},
},
},
}}}), "notexistnode", "", true,
}}}), "notexistnode",
[]string{},
true,
},
{
"node exist and only has an internal IP address (useInternalIP=false)",
"node exists and only has an internal IP address (useInternalIP=false)",
testclient.NewSimpleClientset(&apiv1.NodeList{Items: []apiv1.Node{{
ObjectMeta: metav1.ObjectMeta{
Name: "demo",
Expand All @@ -98,10 +103,56 @@ func TestGetNodeIP(t *testing.T) {
},
},
},
}}}), "demo", "10.0.0.1", false,
}}}), "demo",
[]string{"10.0.0.1"},
false,
},
{
"node exist and only has an internal IP address",
"node exists has an internal IP address and an empty external IP address (useInternalIP=false)",
testclient.NewSimpleClientset(&apiv1.NodeList{Items: []apiv1.Node{{
ObjectMeta: metav1.ObjectMeta{
Name: "demo",
},
Status: apiv1.NodeStatus{
Addresses: []apiv1.NodeAddress{
{
Type: apiv1.NodeExternalIP,
Address: "",
},
{
Type: apiv1.NodeInternalIP,
Address: "10.0.0.1",
},
},
},
}}}), "demo",
[]string{"10.0.0.1"},
false,
},
{
"node exists and has two internal IP address (useInternalIP=false)",
testclient.NewSimpleClientset(&apiv1.NodeList{Items: []apiv1.Node{{
ObjectMeta: metav1.ObjectMeta{
Name: "demo",
},
Status: apiv1.NodeStatus{
Addresses: []apiv1.NodeAddress{
{
Type: apiv1.NodeInternalIP,
Address: "10.0.0.1",
},
{
Type: apiv1.NodeInternalIP,
Address: "fd00::1",
},
},
},
}}}), "demo",
[]string{"10.0.0.1", "fd00::1"},
false,
},
{
"node exists and only has an internal IP address",
testclient.NewSimpleClientset(&apiv1.NodeList{Items: []apiv1.Node{{
ObjectMeta: metav1.ObjectMeta{
Name: "demo",
Expand All @@ -114,7 +165,31 @@ func TestGetNodeIP(t *testing.T) {
},
},
},
}}}), "demo", "10.0.0.1", true,
}}}), "demo",
[]string{"10.0.0.1"},
true,
},
{
"node exists and has two internal IP address",
testclient.NewSimpleClientset(&apiv1.NodeList{Items: []apiv1.Node{{
ObjectMeta: metav1.ObjectMeta{
Name: "demo",
},
Status: apiv1.NodeStatus{
Addresses: []apiv1.NodeAddress{
{
Type: apiv1.NodeInternalIP,
Address: "10.0.0.1",
},
{
Type: apiv1.NodeInternalIP,
Address: "fd00::1",
},
},
},
}}}), "demo",
[]string{"10.0.0.1", "fd00::1"},
true,
},
{
"node exist and only has an external IP address",
Expand All @@ -130,7 +205,27 @@ func TestGetNodeIP(t *testing.T) {
},
},
},
}}}), "demo", "10.0.0.1", false,
}}}), "demo",
[]string{"10.0.0.1"},
false,
},
{
"node exist and only has an external IP address (useInternalIP=true)",
testclient.NewSimpleClientset(&apiv1.NodeList{Items: []apiv1.Node{{
ObjectMeta: metav1.ObjectMeta{
Name: "demo",
},
Status: apiv1.NodeStatus{
Addresses: []apiv1.NodeAddress{
{
Type: apiv1.NodeExternalIP,
Address: "10.0.0.1",
},
},
},
}}}), "demo",
[]string{},
true,
},
{
"multiple nodes - choose the right one",
Expand Down Expand Up @@ -162,10 +257,12 @@ func TestGetNodeIP(t *testing.T) {
},
},
}}),
"demo2", "10.0.0.2", true,
"demo2",
[]string{"10.0.0.2"},
true,
},
{
"node with both IP internal and external IP address - returns external IP",
"node with both internal and external IP address - returns external IP",
testclient.NewSimpleClientset(&apiv1.NodeList{Items: []apiv1.Node{{
ObjectMeta: metav1.ObjectMeta{
Name: "demo",
Expand All @@ -182,10 +279,12 @@ func TestGetNodeIP(t *testing.T) {
},
},
}}}),
"demo", "10.0.0.2", false,
"demo",
[]string{"10.0.0.2"},
false,
},
{
"node with both IP internal and external IP address - returns internal IP",
"node with both internal and external IP address - returns internal IP",
testclient.NewSimpleClientset(&apiv1.NodeList{Items: []apiv1.Node{{
ObjectMeta: metav1.ObjectMeta{
Name: "demo",
Expand All @@ -202,14 +301,16 @@ func TestGetNodeIP(t *testing.T) {
},
},
}}}),
"demo", "10.0.0.2", true,
"demo",
[]string{"10.0.0.2"},
true,
},
}

for _, fk := range fKNodes {
address := GetNodeIPOrName(fk.cs, fk.nodeName, fk.useInternalIP)
if address != fk.ea {
t.Errorf("%v - expected %s, but returned %s", fk.name, fk.ea, address)
addresses := GetNodeIPs(fk.cs, fk.nodeName, fk.useInternalIP)
if !slices.Equal(addresses, fk.ea) {
t.Errorf("%v - expected %v, but returned %v", fk.name, fk.ea, addresses)
}
}
}
Expand Down