inspektor-gadget
573 строки · 17.3 Кб
1// Copyright 2019-2021 The Inspektor Gadget 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
15package containercollection
16
17import (
18"fmt"
19"reflect"
20"testing"
21
22metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
23k8sTypes "k8s.io/apimachinery/pkg/types"
24
25"github.com/inspektor-gadget/inspektor-gadget/pkg/types"
26)
27
28func TestSelector(t *testing.T) {
29table := []struct {
30description string
31match bool
32selector *ContainerSelector
33container *Container
34}{
35{
36description: "Selector without filter",
37match: true,
38selector: &ContainerSelector{},
39container: &Container{
40K8s: K8sMetadata{
41BasicK8sMetadata: types.BasicK8sMetadata{
42Namespace: "this-namespace",
43PodName: "this-pod",
44ContainerName: "this-container",
45},
46},
47},
48},
49{
50description: "Selector with all filters",
51match: true,
52selector: &ContainerSelector{
53K8s: K8sSelector{
54BasicK8sMetadata: types.BasicK8sMetadata{
55Namespace: "this-namespace",
56PodName: "this-pod",
57ContainerName: "this-container",
58PodLabels: map[string]string{
59"key1": "value1",
60"key2": "value2",
61},
62},
63},
64},
65container: &Container{
66K8s: K8sMetadata{
67BasicK8sMetadata: types.BasicK8sMetadata{
68Namespace: "this-namespace",
69PodName: "this-pod",
70ContainerName: "this-container",
71PodLabels: map[string]string{
72"unrelated-label": "here",
73"key1": "value1",
74"key2": "value2",
75},
76},
77},
78},
79},
80{
81description: "Podname does not match",
82match: false,
83selector: &ContainerSelector{
84K8s: K8sSelector{
85BasicK8sMetadata: types.BasicK8sMetadata{
86Namespace: "this-namespace",
87PodName: "this-pod",
88},
89},
90},
91container: &Container{
92K8s: K8sMetadata{
93BasicK8sMetadata: types.BasicK8sMetadata{
94Namespace: "this-namespace",
95PodName: "a-misnamed-pod",
96ContainerName: "this-container",
97},
98},
99},
100},
101{
102description: "One label doesn't match",
103match: false,
104selector: &ContainerSelector{
105K8s: K8sSelector{
106BasicK8sMetadata: types.BasicK8sMetadata{
107Namespace: "this-namespace",
108PodName: "this-pod",
109ContainerName: "this-container",
110PodLabels: map[string]string{
111"key1": "value1",
112"key2": "value2",
113},
114},
115},
116},
117container: &Container{
118K8s: K8sMetadata{
119BasicK8sMetadata: types.BasicK8sMetadata{
120Namespace: "this-namespace",
121PodName: "this-pod",
122ContainerName: "this-container",
123PodLabels: map[string]string{
124"key1": "value1",
125"key2": "something-else",
126},
127},
128},
129},
130},
131{
132description: "Several namespaces without match",
133match: false,
134selector: &ContainerSelector{
135K8s: K8sSelector{
136BasicK8sMetadata: types.BasicK8sMetadata{
137Namespace: "ns1,ns2,ns3",
138PodName: "this-pod",
139},
140},
141},
142container: &Container{
143K8s: K8sMetadata{
144BasicK8sMetadata: types.BasicK8sMetadata{
145Namespace: "this-namespace",
146PodName: "this-pod",
147ContainerName: "this-container",
148},
149},
150},
151},
152{
153description: "Several namespaces with match",
154match: true,
155selector: &ContainerSelector{
156K8s: K8sSelector{
157BasicK8sMetadata: types.BasicK8sMetadata{
158Namespace: "ns1,ns2,ns3",
159PodName: "this-pod",
160},
161},
162},
163container: &Container{
164K8s: K8sMetadata{
165BasicK8sMetadata: types.BasicK8sMetadata{
166Namespace: "ns2",
167PodName: "this-pod",
168ContainerName: "this-container",
169},
170},
171},
172},
173}
174
175for i, entry := range table {
176result := ContainerSelectorMatches(entry.selector, entry.container)
177if entry.match != result {
178t.Fatalf("Failed test %q (index %d): result %v expected %v",
179entry.description, i, result, entry.match)
180}
181}
182}
183
184func TestContainerResolver(t *testing.T) {
185opts := []ContainerCollectionOption{}
186
187cc := &ContainerCollection{}
188err := cc.Initialize(opts...)
189if err != nil {
190t.Fatalf("Failed to initialize container collection: %s", err)
191}
192
193// Add 3 Containers
194for i := 0; i < 3; i++ {
195cc.AddContainer(&Container{
196Runtime: RuntimeMetadata{
197BasicRuntimeMetadata: types.BasicRuntimeMetadata{
198ContainerID: fmt.Sprintf("abcde%d", i),
199},
200},
201Mntns: 55555 + uint64(i),
202Pid: uint32(100 + i),
203CgroupPath: "/none",
204CgroupID: 1,
205K8s: K8sMetadata{
206BasicK8sMetadata: types.BasicK8sMetadata{
207Namespace: "this-namespace",
208PodName: "my-pod",
209ContainerName: fmt.Sprintf("container%d", i),
210},
211ownerReference: &metav1.OwnerReference{
212UID: k8sTypes.UID(fmt.Sprintf("abcde%d", i)),
213},
214},
215})
216}
217
218// Remove 1 Container
219cc.RemoveContainer("abcde1")
220
221// Remove non-existent Container
222cc.RemoveContainer("abcde99")
223
224// Check content
225if cc.ContainerLen() != 2 {
226t.Fatalf("Error while checking containers: len %d", cc.ContainerLen())
227}
228if cc.GetContainer("abcde0") == nil {
229t.Fatalf("Error while checking container %s: not found", "abcde0")
230}
231if cc.GetContainer("abcde2") == nil {
232t.Fatalf("Error while checking container %s: not found", "abcde2")
233}
234
235// Check content using LookupMntnsByPod
236mntnsByContainer := cc.LookupMntnsByPod("this-namespace", "my-pod")
237if !reflect.DeepEqual(mntnsByContainer, map[string]uint64{"container0": 55555, "container2": 55557}) {
238t.Fatalf("Error while looking up mount ns by Pod: unexpected %v", mntnsByContainer)
239}
240mntnsByContainer = cc.LookupMntnsByPod("this-namespace", "this-other-pod")
241if !reflect.DeepEqual(mntnsByContainer, map[string]uint64{}) {
242t.Fatalf("Error while looking up mount ns by Pod: unexpected %v", mntnsByContainer)
243}
244
245// Check content using LookupMntnsByContainer
246mntns := cc.LookupMntnsByContainer("this-namespace", "my-pod", "container0")
247if mntns != 55555 {
248t.Fatalf("Error while looking up container0: unexpected mntns %v", mntns)
249}
250mntns = cc.LookupMntnsByContainer("this-namespace", "my-pod", "container1")
251if mntns != 0 {
252t.Fatalf("Error while looking up container1: unexpected mntns %v", mntns)
253}
254mntns = cc.LookupMntnsByContainer("this-namespace", "my-pod", "container2")
255if mntns != 55557 {
256t.Fatalf("Error while looking up container2: unexpected mntns %v", mntns)
257}
258
259// Check content using LookupPIDByPod
260pidByContainer := cc.LookupPIDByPod("this-namespace", "my-pod")
261if !reflect.DeepEqual(pidByContainer, map[string]uint32{"container0": 100, "container2": 102}) {
262t.Fatalf("Error while looking up PID by Pod: unexpected %v", pidByContainer)
263}
264pidByContainer = cc.LookupPIDByPod("this-namespace", "this-other-pod")
265if !reflect.DeepEqual(pidByContainer, map[string]uint32{}) {
266t.Fatalf("Error while looking up PID by Pod: unexpected %v", pidByContainer)
267}
268
269// Check content using LookupPIDByContainer
270pid := cc.LookupPIDByContainer("this-namespace", "my-pod", "container0")
271if pid != 100 {
272t.Fatalf("Error while looking up container0: unexpected pid %v", pid)
273}
274pid = cc.LookupPIDByContainer("this-namespace", "my-pod", "container1")
275if pid != 0 {
276t.Fatalf("Error while looking up container1: unexpected pid %v", pid)
277}
278pid = cc.LookupPIDByContainer("this-namespace", "my-pod", "container2")
279if pid != 102 {
280t.Fatalf("Error while looking up container2: unexpected pid %v", pid)
281}
282
283// Check content using LookupOwnerReferenceByMntns
284ownerRef := cc.LookupOwnerReferenceByMntns(55555)
285if ownerRef == nil || ownerRef.UID != "abcde0" {
286t.Fatalf("Error while looking up owner reference: unexpected %v", ownerRef)
287}
288
289ownerRef = cc.LookupOwnerReferenceByMntns(55557)
290if ownerRef == nil || ownerRef.UID != "abcde2" {
291t.Fatalf("Error while looking up owner reference: unexpected %v", ownerRef)
292}
293
294// Non-existent mntns
295ownerRef = cc.LookupOwnerReferenceByMntns(55556)
296if ownerRef != nil {
297t.Fatalf("Error while looking up owner reference: unexpected %v", ownerRef)
298}
299
300// Check LookupContainerByMntns
301containerByMntns0 := cc.LookupContainerByMntns(55555)
302if containerByMntns0.K8s.ContainerName != "container0" {
303t.Fatalf("Error in LookupContainerByMntns: expected %s, found %s", "container0",
304containerByMntns0.K8s.ContainerName)
305}
306
307// Check LookupContainerByMntns
308containerByMntns2 := cc.LookupContainerByMntns(55555 + 2)
309if containerByMntns2.K8s.ContainerName != "container2" {
310t.Fatalf("Error in LookupContainerByMntns: expected %s, found %s", "container2",
311containerByMntns2.K8s.ContainerName)
312}
313
314containerByMntnsNotFound := cc.LookupContainerByMntns(989898)
315if containerByMntnsNotFound != nil {
316t.Fatalf("Error in LookupContainerByMntns: returned non nil")
317}
318
319// Add new container with same pod and container name of container0 but in different namespace
320cc.AddContainer(&Container{
321Runtime: RuntimeMetadata{
322BasicRuntimeMetadata: types.BasicRuntimeMetadata{
323ContainerID: "abcde0-different",
324},
325},
326K8s: K8sMetadata{
327BasicK8sMetadata: types.BasicK8sMetadata{
328Namespace: "another-namespace",
329PodName: "my-pod",
330ContainerName: "container0",
331PodLabels: map[string]string{
332"key1": "value1",
333"key2": "value2",
334},
335},
336},
337})
338
339// Look up containers with label 'key1=value1'
340selectedContainers := cc.GetContainersBySelector(&ContainerSelector{
341K8s: K8sSelector{
342BasicK8sMetadata: types.BasicK8sMetadata{
343PodLabels: map[string]string{
344"key1": "value1",
345},
346},
347},
348})
349if len(selectedContainers) != 1 {
350t.Fatalf("Error while looking up containers by one label: invalid number of matches")
351}
352if v, found := selectedContainers[0].K8s.PodLabels["key1"]; !found || v != "value1" {
353t.Fatalf("Error while looking up containers by one label: unexpected container %+v",
354selectedContainers[0])
355}
356
357// Look up containers with label 'key1=value1' and 'key2=value2'
358selector := ContainerSelector{
359K8s: K8sSelector{
360BasicK8sMetadata: types.BasicK8sMetadata{
361PodLabels: map[string]string{
362"key1": "value1",
363"key2": "value2",
364},
365},
366},
367}
368selectedContainers = cc.GetContainersBySelector(&selector)
369if len(selectedContainers) != 1 {
370t.Fatalf("Error while looking up containers by multiple labels: invalid number of matches")
371}
372for sk, sv := range selector.K8s.PodLabels {
373if v, found := selectedContainers[0].K8s.PodLabels[sk]; !found || v != sv {
374t.Fatalf("Error while looking up containers by multiple labels: unexpected container %+v",
375selectedContainers[0])
376}
377}
378
379// Look up containers in 'this-namespace'
380selectedContainers = cc.GetContainersBySelector(&ContainerSelector{
381K8s: K8sSelector{
382BasicK8sMetadata: types.BasicK8sMetadata{
383Namespace: "this-namespace",
384},
385},
386})
387if len(selectedContainers) != 2 {
388t.Fatalf("Error while looking up containers by namespace: invalid number of matches")
389}
390for _, container := range selectedContainers {
391if container.K8s.Namespace != "this-namespace" {
392t.Fatalf("Error while looking up containers by namespace: unexpected container %+v",
393container)
394}
395}
396
397// Look up containers in 'this-namespace' and 'my-pod'
398selectedContainers = cc.GetContainersBySelector(&ContainerSelector{
399K8s: K8sSelector{
400BasicK8sMetadata: types.BasicK8sMetadata{
401Namespace: "this-namespace",
402PodName: "my-pod",
403},
404},
405})
406if len(selectedContainers) != 2 {
407t.Fatalf("Error while looking up containers by namespace and pod: invalid number of matches")
408}
409for _, container := range selectedContainers {
410if container.K8s.Namespace != "this-namespace" || container.K8s.PodName != "my-pod" {
411t.Fatalf("Error while looking up containers by namespace and pod: unexpected container %+v",
412container)
413}
414}
415
416// Look up containers named 'container0' anywhere
417selectedContainers = cc.GetContainersBySelector(&ContainerSelector{
418K8s: K8sSelector{
419BasicK8sMetadata: types.BasicK8sMetadata{
420ContainerName: "container0",
421},
422},
423})
424if len(selectedContainers) != 2 {
425t.Fatalf("Error while looking up containers by name: invalid number of matches")
426}
427for _, container := range selectedContainers {
428if container.K8s.ContainerName != "container0" {
429t.Fatalf("Error while looking up containers by name: unexpected container %+v",
430container)
431}
432}
433
434// Look up containers named 'container0' in 'my-pod' but any namespace
435selectedContainers = cc.GetContainersBySelector(&ContainerSelector{
436K8s: K8sSelector{
437BasicK8sMetadata: types.BasicK8sMetadata{
438PodName: "my-pod",
439ContainerName: "container0",
440},
441},
442})
443if len(selectedContainers) != 2 {
444t.Fatalf("Error while looking up containers by name and pod: invalid number of matches")
445}
446for _, container := range selectedContainers {
447if container.K8s.PodName != "my-pod" || container.K8s.ContainerName != "container0" {
448t.Fatalf("Error while looking up containers by name and pod: unexpected container %+v",
449container)
450}
451}
452
453// Look up container0 in 'this-namespace' and 'my-pod'
454selectedContainers = cc.GetContainersBySelector(&ContainerSelector{
455K8s: K8sSelector{
456BasicK8sMetadata: types.BasicK8sMetadata{
457Namespace: "this-namespace",
458PodName: "my-pod",
459ContainerName: "container0",
460},
461},
462})
463if len(selectedContainers) != 1 {
464t.Fatalf("Error while looking up specific container: invalid number of matches")
465}
466if selectedContainers[0].K8s.Namespace != "this-namespace" || selectedContainers[0].K8s.PodName != "my-pod" || selectedContainers[0].K8s.ContainerName != "container0" {
467t.Fatalf("Error while looking up specific container: unexpected container %+v",
468selectedContainers[0])
469}
470
471// Look up container0 in 'another-namespace' and 'my-pod'
472selectedContainers = cc.GetContainersBySelector(&ContainerSelector{
473K8s: K8sSelector{
474BasicK8sMetadata: types.BasicK8sMetadata{
475Namespace: "another-namespace",
476PodName: "my-pod",
477ContainerName: "container0",
478},
479},
480})
481if len(selectedContainers) != 1 {
482t.Fatalf("Error while looking up specific container: invalid number of matches")
483}
484if selectedContainers[0].K8s.Namespace != "another-namespace" || selectedContainers[0].K8s.PodName != "my-pod" || selectedContainers[0].K8s.ContainerName != "container0" {
485t.Fatalf("Error while looking up specific container: unexpected container %+v",
486selectedContainers[0])
487}
488
489// Look up container2 in 'this-namespace' and 'my-pod'
490selectedContainers = cc.GetContainersBySelector(&ContainerSelector{
491K8s: K8sSelector{
492BasicK8sMetadata: types.BasicK8sMetadata{
493Namespace: "this-namespace",
494PodName: "my-pod",
495ContainerName: "container2",
496},
497},
498})
499if len(selectedContainers) != 1 {
500t.Fatalf("Error while looking up specific container: invalid number of matches")
501}
502if selectedContainers[0].K8s.Namespace != "this-namespace" || selectedContainers[0].K8s.PodName != "my-pod" || selectedContainers[0].K8s.ContainerName != "container2" {
503t.Fatalf("Error while looking up specific container: unexpected container %+v",
504selectedContainers[0])
505}
506
507// Look up a non-existent container
508selectedContainers = cc.GetContainersBySelector(&ContainerSelector{
509K8s: K8sSelector{
510BasicK8sMetadata: types.BasicK8sMetadata{
511Namespace: "this-namespace",
512PodName: "my-pod",
513ContainerName: "non-existent",
514},
515},
516})
517if len(selectedContainers) != 0 {
518t.Fatalf("Error while looking up a non-existent container")
519}
520
521// Look up containers in a non-existent pod
522selectedContainers = cc.GetContainersBySelector(&ContainerSelector{
523K8s: K8sSelector{
524BasicK8sMetadata: types.BasicK8sMetadata{
525Namespace: "this-namespace",
526PodName: "non-existent",
527},
528},
529})
530if len(selectedContainers) != 0 {
531t.Fatalf("Error while looking up containers in a non-existent pod")
532}
533
534// Look up containers in a non-existent pod
535selectedContainers = cc.GetContainersBySelector(&ContainerSelector{
536K8s: K8sSelector{
537BasicK8sMetadata: types.BasicK8sMetadata{
538Namespace: "this-namespace",
539PodName: "non-existent",
540ContainerName: "container0",
541},
542},
543})
544if len(selectedContainers) != 0 {
545t.Fatalf("Error while looking up containers in a non-existent namespace")
546}
547
548// Look up containers in a non-existent namespace
549selectedContainers = cc.GetContainersBySelector(&ContainerSelector{
550K8s: K8sSelector{
551BasicK8sMetadata: types.BasicK8sMetadata{
552Namespace: "non-existent",
553},
554},
555})
556if len(selectedContainers) != 0 {
557t.Fatalf("Error while looking up containers in a non-existent namespace")
558}
559
560// Look up containers in a non-existent namespace
561selectedContainers = cc.GetContainersBySelector(&ContainerSelector{
562K8s: K8sSelector{
563BasicK8sMetadata: types.BasicK8sMetadata{
564Namespace: "non-existent",
565PodName: "my-pod",
566ContainerName: "container0",
567},
568},
569})
570if len(selectedContainers) != 0 {
571t.Fatalf("Error while looking up containers in a non-existent namespace")
572}
573}
574