github.com/castai/kvisor@v1.7.1-0.20240516114728-b3572a2607b5/cmd/controller/state/imagescan/delta_test.go (about) 1 package imagescan 2 3 import ( 4 "testing" 5 6 "github.com/google/uuid" 7 "github.com/stretchr/testify/require" 8 corev1 "k8s.io/api/core/v1" 9 "k8s.io/apimachinery/pkg/api/resource" 10 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 11 "k8s.io/apimachinery/pkg/types" 12 ) 13 14 func TestDelta(t *testing.T) { 15 t.Run("upsert images state on delta changes", func(t *testing.T) { 16 r := require.New(t) 17 18 createNode := func(name string) *corev1.Node { 19 return &corev1.Node{ 20 TypeMeta: metav1.TypeMeta{ 21 Kind: "Node", 22 APIVersion: "v1", 23 }, 24 ObjectMeta: metav1.ObjectMeta{ 25 Name: name, 26 }, 27 Status: corev1.NodeStatus{ 28 NodeInfo: corev1.NodeSystemInfo{ 29 Architecture: defaultImageArch, 30 OperatingSystem: defaultImageOs, 31 }, 32 Allocatable: corev1.ResourceList{ 33 corev1.ResourceCPU: resource.MustParse("2"), 34 corev1.ResourceMemory: resource.MustParse("4Gi"), 35 }, 36 }, 37 } 38 } 39 40 createPod := func(imageName, imageID, nodeName string) *corev1.Pod { 41 return &corev1.Pod{ 42 TypeMeta: metav1.TypeMeta{ 43 Kind: "Pod", 44 APIVersion: "v1", 45 }, 46 ObjectMeta: metav1.ObjectMeta{ 47 UID: types.UID(uuid.New().String()), 48 }, 49 Spec: corev1.PodSpec{ 50 Containers: []corev1.Container{ 51 { 52 Name: "cont", 53 Image: imageName, 54 }, 55 }, 56 NodeName: nodeName, 57 }, 58 Status: corev1.PodStatus{ 59 Phase: corev1.PodRunning, 60 ContainerStatuses: []corev1.ContainerStatus{ 61 { 62 Name: "cont", 63 Image: imageName, 64 ImageID: imageID, 65 }, 66 }, 67 }, 68 } 69 } 70 71 delta := newTestDelta() 72 73 pod1 := createPod("nginx1", "img1", "node1") 74 pod2 := createPod("nginx2", "img2", "node1") 75 pod3 := createPod("nginx1", "img1", "node2") 76 77 // Insert nodes. 78 delta.Upsert(createNode("node1")) 79 delta.Upsert(createNode("node2")) 80 // Insert new pods. 81 delta.Upsert(pod1) 82 delta.Upsert(pod2) 83 delta.Upsert(pod3) 84 r.Len(delta.images, 2) 85 img1 := delta.images["img1amd64nginx1"] 86 r.Equal("nginx1", img1.name) 87 r.Equal("img1", img1.id) 88 r.Len(img1.owners, 2) 89 90 // Delete single pod. It should be removed only from image nodes list. 91 delta.Delete(pod1) 92 r.Len(delta.images, 2) 93 94 // Delete one more pod for the same image. Image should be removed. 95 delta.Delete(pod3) 96 r.Len(delta.images, 1) 97 }) 98 99 t.Run("cleans up image references", func(t *testing.T) { 100 r := require.New(t) 101 delta := newTestDelta() 102 103 node := &corev1.Node{ 104 TypeMeta: metav1.TypeMeta{ 105 Kind: "Node", 106 APIVersion: "v1", 107 }, 108 ObjectMeta: metav1.ObjectMeta{ 109 Name: "node1", 110 }, 111 Status: corev1.NodeStatus{ 112 Allocatable: corev1.ResourceList{ 113 corev1.ResourceCPU: resource.MustParse("2"), 114 corev1.ResourceMemory: resource.MustParse("4Gi"), 115 }, 116 }, 117 } 118 delta.Upsert(node) 119 120 pod := &corev1.Pod{ 121 TypeMeta: metav1.TypeMeta{ 122 Kind: "Pod", 123 APIVersion: "v1", 124 }, 125 ObjectMeta: metav1.ObjectMeta{ 126 UID: "123", 127 }, 128 Spec: corev1.PodSpec{ 129 Containers: []corev1.Container{ 130 { 131 Name: "test", 132 Image: "test", 133 Resources: corev1.ResourceRequirements{ 134 Requests: corev1.ResourceList{ 135 corev1.ResourceCPU: resource.MustParse("1"), 136 corev1.ResourceMemory: resource.MustParse("2Gi"), 137 }, 138 }, 139 }, 140 }, 141 NodeName: "node1", 142 }, 143 Status: corev1.PodStatus{ 144 Phase: corev1.PodRunning, 145 ContainerStatuses: []corev1.ContainerStatus{ 146 { 147 Name: "test", 148 ImageID: "testid", 149 }, 150 }, 151 }, 152 } 153 154 delta.Upsert(pod) 155 img, found := delta.images["testidamd64test"] 156 r.True(found) 157 r.Len(img.owners, 1) 158 159 delta.Delete(pod) 160 img, found = delta.images["testidamd64test"] 161 r.False(found) 162 }) 163 } 164 165 func newTestDelta() *deltaState { 166 return newDeltaState(&mockKubeController{}) 167 }