...

Source file src/edge-infra.dev/pkg/sds/k8s/iplookup/iplookup_test.go

Documentation: edge-infra.dev/pkg/sds/k8s/iplookup

     1  package iplookup
     2  
     3  import (
     4  	"context"
     5  	"math"
     6  	"net"
     7  	"testing"
     8  
     9  	"github.com/stretchr/testify/assert"
    10  
    11  	"edge-infra.dev/pkg/lib/fog"
    12  	"edge-infra.dev/pkg/lib/logging"
    13  
    14  	v1 "k8s.io/api/core/v1"
    15  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    16  	"k8s.io/client-go/kubernetes"
    17  	"k8s.io/client-go/kubernetes/fake"
    18  	"k8s.io/client-go/rest"
    19  )
    20  
    21  var (
    22  	NODES = []string{"ien-1", "ien-2", "ien-3"}
    23  	PODS  = []string{"pod-1", "pod-2", "pod-3"}
    24  	DS    = "daemonset"
    25  	NS    = "default"
    26  	QUERY = Query{
    27  		Namespace: NS,
    28  		Daemonset: DS,
    29  	}
    30  	IPS = []string{"109.137.186.131", "240.182.74.195", "161.18.36.28"}
    31  
    32  	FakeClusterConfig = func() (*rest.Config, error) { return &rest.Config{}, nil }
    33  	TestLogger        = logging.NewLogger().WithName("iplookup_test")
    34  )
    35  
    36  func TestGetDaemonsetPodIP(t *testing.T) {
    37  	tests := map[string]func(t *testing.T){
    38  		"Ideal State":     testSuccessIdealState,
    39  		"No Config":       testFailNoConfig,
    40  		"Empty Daemonset": testFailEmptyDaemonset,
    41  		"Empty Namespace": testFailEmptyNamespace,
    42  	}
    43  	for desc, test := range tests {
    44  		t.Run(desc, func(t *testing.T) { test(t) })
    45  	}
    46  }
    47  
    48  func TestDaemonsetPodIPLookup(t *testing.T) {
    49  	tests := map[string]func(t *testing.T){
    50  		"One-Node Network":         testSuccessOneNode,
    51  		"Multi-Node Network":       testSuccessMultipleNodes,
    52  		"Empty Node Name":          testFailEmptyNodeID,
    53  		"Node Name Not In Cluster": testFailInvalidNodeID,
    54  		"Namespace Not In Cluster": testFailInvalidNamespace,
    55  		"Daemonset Not In Cluster": testFailInvalidDaemonset,
    56  		"Empty Client":             testFailEmptyClient,
    57  		"Empty Clientset":          testFailEmptyClientset,
    58  		"Invalid IP Address":       testFailInvalidIP,
    59  	}
    60  	for desc, test := range tests {
    61  		t.Run(desc, func(t *testing.T) { test(t) })
    62  	}
    63  }
    64  
    65  func defaultFakeClientset() kubernetes.Interface {
    66  	return fake.NewSimpleClientset(createPod(PODS[0], NS, DS, NODES[0], IPS[0]))
    67  }
    68  
    69  func createPod(name string, namespace string, dsName string, node string, ip string) *v1.Pod {
    70  	return &v1.Pod{
    71  		ObjectMeta: metav1.ObjectMeta{
    72  			Name:      name,
    73  			Namespace: namespace,
    74  			OwnerReferences: []metav1.OwnerReference{
    75  				{
    76  					Name: dsName,
    77  					Kind: "DaemonSet",
    78  				},
    79  			},
    80  		},
    81  		Spec: v1.PodSpec{
    82  			NodeName: node,
    83  		},
    84  		Status: v1.PodStatus{
    85  			PodIP: ip,
    86  		},
    87  	}
    88  }
    89  func createPods(n int) []*v1.Pod {
    90  	n = int(math.Max(float64(n), float64(len(NODES))))
    91  	objects := make([]*v1.Pod, 0)
    92  	for i := 0; i < n; i++ {
    93  		objects = append(objects, createPod(PODS[i], NS, DS, NODES[i], IPS[i]))
    94  	}
    95  	return objects
    96  }
    97  
    98  // GetDaemonsetPodIP tests
    99  func testSuccessIdealState(t *testing.T) {
   100  	ctx := fog.IntoContext(context.Background(), TestLogger)
   101  
   102  	c, _ := FakeClusterConfig()
   103  	cs, err := kubernetes.NewForConfig(c)
   104  	assert.NoError(t, err)
   105  
   106  	ip := IPLookup{cs}
   107  
   108  	_, err = ip.GetDaemonsetPodIP(ctx, NODES[0], QUERY)
   109  	assert.ErrorContains(t, err, "failed to query kubernetes client")
   110  }
   111  
   112  func testFailNoConfig(t *testing.T) {
   113  	_, err := New()
   114  	assert.Error(t, err, ErrNotInCluster)
   115  }
   116  
   117  func testFailEmptyDaemonset(t *testing.T) {
   118  	ip := IPLookup{}
   119  	ctx := fog.IntoContext(context.Background(), TestLogger)
   120  	queryWithEmptyDaemonset := Query{Namespace: NS, Daemonset: ""}
   121  	_, err := ip.GetDaemonsetPodIP(ctx, NODES[0], queryWithEmptyDaemonset)
   122  	assert.ErrorIs(t, ErrInvalidQuery, err)
   123  }
   124  
   125  func testFailEmptyNamespace(t *testing.T) {
   126  	ip := IPLookup{}
   127  	ctx := fog.IntoContext(context.Background(), TestLogger)
   128  	queryWithEmptyNamespace := Query{Namespace: "", Daemonset: DS}
   129  	_, err := ip.GetDaemonsetPodIP(ctx, NODES[0], queryWithEmptyNamespace)
   130  	assert.ErrorIs(t, ErrInvalidQuery, err)
   131  }
   132  
   133  // daemonsetPodIPLookup tests
   134  func testSuccessOneNode(t *testing.T) {
   135  	ctx := fog.IntoContext(context.Background(), TestLogger)
   136  	clientset := defaultFakeClientset()
   137  
   138  	iplookup := IPLookup{clientset: clientset}
   139  
   140  	ip, err := iplookup.daemonsetPodIPLookup(ctx, NODES[0], QUERY)
   141  	assert.NoError(t, err)
   142  	assert.Equal(t, ip, net.ParseIP(IPS[0]))
   143  }
   144  
   145  func testSuccessMultipleNodes(t *testing.T) {
   146  	ctx := fog.IntoContext(context.Background(), TestLogger)
   147  	objects := createPods(3)
   148  	clientset := fake.NewSimpleClientset(objects[0], objects[1], objects[2])
   149  
   150  	iplookup := IPLookup{clientset}
   151  
   152  	for i := 0; i < 3; i++ {
   153  		ip, err := iplookup.GetDaemonsetPodIP(ctx, NODES[i], QUERY)
   154  		assert.NoError(t, err)
   155  		assert.Equal(t, ip, net.ParseIP(IPS[i]))
   156  	}
   157  }
   158  
   159  func testFailEmptyNodeID(t *testing.T) {
   160  	ctx := fog.IntoContext(context.Background(), TestLogger)
   161  	iplookup := IPLookup{defaultFakeClientset()}
   162  	_, err := iplookup.GetDaemonsetPodIP(ctx, "", QUERY)
   163  	assert.ErrorIs(t, err, ErrNoReturn)
   164  }
   165  
   166  func testFailInvalidNodeID(t *testing.T) {
   167  	ctx := fog.IntoContext(context.Background(), TestLogger)
   168  	iplookup := IPLookup{defaultFakeClientset()}
   169  	_, err := iplookup.GetDaemonsetPodIP(ctx, "ien-that-does-not-exist", QUERY)
   170  	assert.ErrorIs(t, err, ErrNoReturn)
   171  }
   172  
   173  func testFailInvalidNamespace(t *testing.T) {
   174  	ctx := fog.IntoContext(context.Background(), TestLogger)
   175  	iplookup := IPLookup{defaultFakeClientset()}
   176  	queryWithInvalidNamespace := Query{Namespace: "namespace-not-in-network", Daemonset: DS}
   177  	_, err := iplookup.GetDaemonsetPodIP(ctx, NODES[0], queryWithInvalidNamespace)
   178  	assert.ErrorIs(t, err, ErrNoReturn)
   179  }
   180  
   181  func testFailInvalidDaemonset(t *testing.T) {
   182  	ctx := fog.IntoContext(context.Background(), TestLogger)
   183  	iplookup := IPLookup{defaultFakeClientset()}
   184  	queryWithInvalidDaemonset := Query{Namespace: NS, Daemonset: "daemonset-not-in-network"}
   185  	_, err := iplookup.GetDaemonsetPodIP(ctx, NODES[0], queryWithInvalidDaemonset)
   186  	assert.ErrorIs(t, err, ErrNoReturn)
   187  }
   188  
   189  func testFailEmptyClient(t *testing.T) {
   190  	ctx := fog.IntoContext(context.Background(), TestLogger)
   191  	iplookup := IPLookup{defaultFakeClientset()}
   192  	_, err := iplookup.GetDaemonsetPodIP(ctx, NODES[0], Query{})
   193  	assert.ErrorIs(t, err, ErrInvalidQuery)
   194  }
   195  
   196  func testFailEmptyClientset(t *testing.T) {
   197  	ctx := fog.IntoContext(context.Background(), TestLogger)
   198  	clientset := fake.NewSimpleClientset()
   199  	iplookup := IPLookup{clientset}
   200  
   201  	_, err := iplookup.GetDaemonsetPodIP(ctx, NODES[0], QUERY)
   202  	assert.ErrorIs(t, err, ErrNoReturn)
   203  }
   204  
   205  func testFailInvalidIP(t *testing.T) {
   206  	ctx := fog.IntoContext(context.Background(), TestLogger)
   207  
   208  	clientset := fake.NewSimpleClientset(createPod(PODS[0], NS, DS, NODES[0], ""))
   209  	iplookup := IPLookup{clientset}
   210  
   211  	_, err := iplookup.GetDaemonsetPodIP(ctx, NODES[0], QUERY)
   212  	assert.ErrorIs(t, err, ErrInvalidIP)
   213  }
   214  

View as plain text