istio.io/istio@v0.0.0-20240520182934-d79c90f27776/cni/pkg/nodeagent/pod_cache_test.go (about)

     1  // Copyright Istio Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package nodeagent
    16  
    17  import (
    18  	"reflect"
    19  	"sync/atomic"
    20  	"testing"
    21  
    22  	corev1 "k8s.io/api/core/v1"
    23  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    24  )
    25  
    26  func openNsTestOverride(s string) (NetnsCloser, error) {
    27  	return newFakeNs(inc()), nil
    28  }
    29  
    30  func openNsTestOverrideWithInodes(inodes ...uint64) func(s string) (NetnsCloser, error) {
    31  	i := 0
    32  	return func(s string) (NetnsCloser, error) {
    33  		inode := inodes[i]
    34  		i++
    35  		return newFakeNsInode(inc(), inode), nil
    36  	}
    37  }
    38  
    39  func TestUpsertPodCache(t *testing.T) {
    40  	counter.Store(0)
    41  
    42  	p := newPodNetnsCache(openNsTestOverrideWithInodes(1, 1))
    43  
    44  	pod := &corev1.Pod{ObjectMeta: metav1.ObjectMeta{UID: "testUID"}}
    45  	nspath1 := "/path/to/netns/1"
    46  	nspath2 := "/path/to/netns/2"
    47  
    48  	netns1, err := p.UpsertPodCache(pod, nspath1)
    49  	if err != nil {
    50  		t.Fatalf("unexpected error: %v", err)
    51  	}
    52  
    53  	netns2, err := p.UpsertPodCache(pod, nspath2)
    54  	if err != nil {
    55  		t.Fatalf("unexpected error: %v", err)
    56  	}
    57  
    58  	if !reflect.DeepEqual(netns1, netns2) {
    59  		t.Fatalf("Expected the same Netns for the same uid, got %v and %v", netns1, netns2)
    60  	}
    61  
    62  	if counter.Load() != 2 {
    63  		t.Fatalf("Expected openNetns to be called twice, got %d", counter.Load())
    64  	}
    65  }
    66  
    67  func TestUpsertPodCacheWithNewInode(t *testing.T) {
    68  	counter.Store(0)
    69  
    70  	p := newPodNetnsCache(openNsTestOverrideWithInodes(1, 2))
    71  
    72  	pod := &corev1.Pod{ObjectMeta: metav1.ObjectMeta{UID: "testUID"}}
    73  	nspath1 := "/path/to/netns/1"
    74  	nspath2 := "/path/to/netns/2"
    75  
    76  	netns1, err := p.UpsertPodCache(pod, nspath1)
    77  	if err != nil {
    78  		t.Fatalf("unexpected error: %v", err)
    79  	}
    80  
    81  	netns2, err := p.UpsertPodCache(pod, nspath2)
    82  	if err != nil {
    83  		t.Fatalf("unexpected error: %v", err)
    84  	}
    85  
    86  	if reflect.DeepEqual(netns1, netns2) {
    87  		t.Fatalf("Expected the same Netns for the same uid, got %v and %v", netns1, netns2)
    88  	}
    89  
    90  	if counter.Load() != 2 {
    91  		t.Fatalf("Expected openNetns to be called twice, got %d", counter.Load())
    92  	}
    93  }
    94  
    95  func TestPodsAppearsWithNilNetnsWhenEnsureIsUsed(t *testing.T) {
    96  	p := newPodNetnsCache(openNsTestOverride)
    97  
    98  	p.Ensure("123")
    99  
   100  	found := false
   101  	snap := p.ReadCurrentPodSnapshot()
   102  	for k, v := range snap {
   103  		if k == "123" && v == (WorkloadInfo{}) {
   104  			found = true
   105  		}
   106  	}
   107  	if !found {
   108  		t.Fatalf("expected pod 123 to be in the cache")
   109  	}
   110  }
   111  
   112  func TestUpsertPodCacheWithLiveNetns(t *testing.T) {
   113  	p := newPodNetnsCache(openNsTestOverride)
   114  
   115  	pod := &corev1.Pod{ObjectMeta: metav1.ObjectMeta{UID: "testUID"}}
   116  	ns := newFakeNsInode(inc(), 1)
   117  	wl := WorkloadInfo{
   118  		Workload: podToWorkload(pod),
   119  		Netns:    ns,
   120  	}
   121  	netns1 := p.UpsertPodCacheWithNetns(string(pod.UID), wl)
   122  	if !reflect.DeepEqual(netns1, ns) {
   123  		t.Fatalf("Expected the same Netns for the same uid, got %v and %v", netns1, ns)
   124  	}
   125  
   126  	ns2 := newFakeNsInode(inc(), 1)
   127  	wl2 := WorkloadInfo{
   128  		Workload: podToWorkload(pod),
   129  		Netns:    ns2,
   130  	}
   131  	// when using same uid, the original netns should be returned
   132  	netns2 := p.UpsertPodCacheWithNetns(string(pod.UID), wl2)
   133  	if netns2 != ns {
   134  		t.Fatalf("Expected the original Netns for the same uid, got %p and %p", netns2, ns)
   135  	}
   136  	if !ns2.closed.Load() {
   137  		t.Fatalf("Expected the second Netns to be closed")
   138  	}
   139  }
   140  
   141  func TestDoubleTake(t *testing.T) {
   142  	p := newPodNetnsCache(openNsTestOverride)
   143  
   144  	pod := &corev1.Pod{ObjectMeta: metav1.ObjectMeta{UID: "testUID"}}
   145  	ns := newFakeNs(inc())
   146  	wl := WorkloadInfo{
   147  		Workload: podToWorkload(pod),
   148  		Netns:    ns,
   149  	}
   150  	netns1 := p.UpsertPodCacheWithNetns(string(pod.UID), wl)
   151  	netnsTaken := p.Take(string(pod.UID))
   152  	if netns1 != netnsTaken {
   153  		t.Fatalf("Expected the original Netns for the same uid, got %p and %p", netns1, ns)
   154  	}
   155  	if nil != p.Take(string(pod.UID)) {
   156  		// expect nil because we already took it
   157  		t.Fatalf("Expected nil Netns for the same uid twice")
   158  	}
   159  }
   160  
   161  var counter atomic.Int64
   162  
   163  func inc() uintptr {
   164  	return uintptr(counter.Add(1))
   165  }