inspektor-gadget

Форк
0
/
container-collection_test.go 
243 строки · 6.5 Кб
1
// Copyright 2023 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

15
package containercollection
16

17
import (
18
	"fmt"
19
	"math/rand"
20
	"testing"
21
	"time"
22

23
	"github.com/stretchr/testify/require"
24

25
	utilstest "github.com/inspektor-gadget/inspektor-gadget/internal/test"
26
	types "github.com/inspektor-gadget/inspektor-gadget/pkg/types"
27
)
28

29
type fakeTracerMapsUpdater struct {
30
	containers map[string]*Container
31
}
32

33
var r *rand.Rand = rand.New(rand.NewSource(time.Now().UnixNano()))
34

35
func (f *fakeTracerMapsUpdater) TracerMapsUpdater() FuncNotify {
36
	return func(event PubSubEvent) {
37
		switch event.Type {
38
		case EventTypeAddContainer:
39
			f.containers[event.Container.Runtime.ContainerID] = event.Container
40
		case EventTypeRemoveContainer:
41
			delete(f.containers, event.Container.Runtime.ContainerID)
42
		}
43
	}
44
}
45

46
func BenchmarkCreateContainerCollection(b *testing.B) {
47
	b.ReportAllocs()
48

49
	for n := 0; n < b.N; n++ {
50
		cc := ContainerCollection{}
51
		cc.AddContainer(&Container{
52
			Runtime: RuntimeMetadata{
53
				BasicRuntimeMetadata: types.BasicRuntimeMetadata{
54
					ContainerID: fmt.Sprint(n),
55
				},
56
			},
57
			Mntns: uint64(n),
58
		})
59
	}
60
}
61

62
const (
63
	TestContainerCount = 10000
64
)
65

66
func BenchmarkLookupContainerByMntns(b *testing.B) {
67
	cc := ContainerCollection{}
68

69
	for n := 0; n < TestContainerCount; n++ {
70
		cc.AddContainer(&Container{
71
			Runtime: RuntimeMetadata{
72
				BasicRuntimeMetadata: types.BasicRuntimeMetadata{
73
					ContainerID: fmt.Sprint(n),
74
				},
75
			},
76
			Mntns: uint64(n),
77
		})
78
	}
79

80
	b.ResetTimer()
81

82
	for n := 0; n < b.N; n++ {
83
		mntnsID := uint64(r.Intn(TestContainerCount))
84
		container := cc.LookupContainerByMntns(mntnsID)
85
		if container == nil {
86
			b.Fatalf("there should be a container for mount namespace ID %d", mntnsID)
87
		}
88
	}
89
}
90

91
func BenchmarkLookupContainerByNetns(b *testing.B) {
92
	cc := ContainerCollection{}
93

94
	for n := 0; n < TestContainerCount; n++ {
95
		cc.AddContainer(&Container{
96
			Runtime: RuntimeMetadata{
97
				BasicRuntimeMetadata: types.BasicRuntimeMetadata{
98
					ContainerID: fmt.Sprint(n),
99
				},
100
			},
101
			Netns: uint64(n),
102
		})
103
	}
104

105
	b.ResetTimer()
106

107
	for n := 0; n < b.N; n++ {
108
		netnsID := uint64(r.Intn(TestContainerCount))
109
		container := cc.LookupContainersByNetns(netnsID)
110
		if len(container) == 0 {
111
			b.Fatalf("there should be a container for net namespace ID %d", netnsID)
112
		}
113
	}
114
}
115

116
func TestWithTracerCollection(t *testing.T) {
117
	t.Parallel()
118

119
	// We need root to create the runners that will act as containers on this test
120
	utilstest.RequireRoot(t)
121

122
	cc := ContainerCollection{}
123
	f := &fakeTracerMapsUpdater{containers: make(map[string]*Container)}
124

125
	if err := cc.Initialize(WithTracerCollection(f)); err != nil {
126
		t.Fatalf("Failed to initialize container collection: %s", err)
127
	}
128

129
	nContainers := 5
130

131
	// We have to use real runners here as the WithTracerCollection() will drop the enricher if
132
	// this doesn't have a valid PID
133
	runners := make([]*utilstest.Runner, nContainers)
134
	containers := make([]*Container, nContainers)
135

136
	for i := 0; i < nContainers; i++ {
137
		runner, err := utilstest.NewRunner(nil)
138
		if err != nil {
139
			t.Fatalf("Creating runner: %s", err)
140
		}
141
		t.Cleanup(runner.Close)
142

143
		runners[i] = runner
144

145
		containers[i] = &Container{
146
			Runtime: RuntimeMetadata{
147
				BasicRuntimeMetadata: types.BasicRuntimeMetadata{
148
					RuntimeName:   types.RuntimeNameDocker,
149
					ContainerName: fmt.Sprintf("name%d", i),
150
					ContainerID:   fmt.Sprintf("id%d", i),
151
				},
152
			},
153
			Mntns: runner.Info.MountNsID,
154
			Netns: runner.Info.NetworkNsID,
155
			Pid:   uint32(runner.Info.Pid),
156
			K8s: K8sMetadata{
157
				BasicK8sMetadata: types.BasicK8sMetadata{
158
					ContainerName: fmt.Sprintf("name%d", i),
159
					Namespace:     fmt.Sprintf("namespace%d", i),
160
					PodName:       fmt.Sprintf("pod%d", i),
161
				},
162
			},
163
		}
164
		cc.AddContainer(containers[i])
165
	}
166

167
	require.Equal(t, nContainers, len(f.containers), "number of containers should be equal")
168

169
	verifyEnrichByMntNs := func() {
170
		for i := 0; i < nContainers; i++ {
171
			ev := types.CommonData{}
172
			expected := types.CommonData{
173
				Runtime: types.BasicRuntimeMetadata{
174
					RuntimeName:   containers[i].Runtime.RuntimeName,
175
					ContainerName: containers[i].Runtime.ContainerName,
176
					ContainerID:   containers[i].Runtime.ContainerID,
177
				},
178
				K8s: types.K8sMetadata{
179
					BasicK8sMetadata: types.BasicK8sMetadata{
180
						Namespace:     containers[i].K8s.Namespace,
181
						PodName:       containers[i].K8s.PodName,
182
						ContainerName: containers[i].K8s.ContainerName,
183
					},
184
				},
185
			}
186

187
			cc.EnrichByMntNs(&ev, containers[i].Mntns)
188

189
			require.Equal(t, expected, ev, "events should be equal")
190
		}
191
	}
192

193
	verifyEnrichByNetNs := func() {
194
		for i := 0; i < nContainers; i++ {
195
			ev := types.CommonData{}
196
			expected := types.CommonData{
197
				Runtime: types.BasicRuntimeMetadata{
198
					RuntimeName:   containers[i].Runtime.RuntimeName,
199
					ContainerName: containers[i].Runtime.ContainerName,
200
					ContainerID:   containers[i].Runtime.ContainerID,
201
				},
202
				K8s: types.K8sMetadata{
203
					BasicK8sMetadata: types.BasicK8sMetadata{
204
						Namespace:     containers[i].K8s.Namespace,
205
						PodName:       containers[i].K8s.PodName,
206
						ContainerName: containers[i].K8s.ContainerName,
207
					},
208
				},
209
			}
210

211
			cc.EnrichByNetNs(&ev, containers[i].Netns)
212

213
			require.Equal(t, expected, ev, "events should be equal")
214
		}
215
	}
216

217
	// Enrich by should work
218
	verifyEnrichByMntNs()
219
	verifyEnrichByNetNs()
220

221
	cc.RemoveContainer(containers[0].Runtime.ContainerID)
222

223
	// Pubsub events should be triggered immediately after container removal
224
	require.Equal(t, nContainers-1, len(f.containers), "number of containers should be equal")
225

226
	time.Sleep(1 * time.Second)
227

228
	// Enrich should work 1 second after removing container
229
	verifyEnrichByMntNs()
230
	verifyEnrichByNetNs()
231

232
	time.Sleep(6 * time.Second)
233

234
	// Enrich should **not** work after removing container more than 6 seconds ago
235
	ev := types.CommonData{}
236
	expected := types.CommonData{}
237
	cc.EnrichByMntNs(&ev, containers[0].Mntns)
238
	require.Equal(t, expected, ev, "events should be equal")
239

240
	// This is in a separated line to understand who is causing the issue.
241
	cc.EnrichByNetNs(&ev, containers[0].Netns)
242
	require.Equal(t, expected, ev, "events should be equal")
243
}
244

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.