Skip to content

Commit f375f4c

Browse files
committed
chore(pod): retreive real container name from pod cache
Signed-off-by: Vimal Kumar <[email protected]>
1 parent 18630a0 commit f375f4c

File tree

5 files changed

+283
-23
lines changed

5 files changed

+283
-23
lines changed

internal/k8s/pod/pod.go

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ type (
3737
Informer interface {
3838
service.Initializer
3939
service.Runner
40-
PodInfo(containerID string) (*PodInfo, error)
40+
LookupByContainerID(containerID string) (*PodInfo, string, error)
4141
}
4242

4343
PodInfo struct {
@@ -212,8 +212,8 @@ func (pi *podInformer) Run(ctx context.Context) error {
212212
return pi.manager.Start(ctx)
213213
}
214214

215-
// PodInfo retrieves pod details given a containerID
216-
func (pi *podInformer) PodInfo(containerID string) (*PodInfo, error) {
215+
// LookupByContainerID retrieves pod details and container name given a containerID
216+
func (pi *podInformer) LookupByContainerID(containerID string) (*PodInfo, string, error) {
217217
var pods corev1.PodList
218218

219219
err := pi.manager.GetCache().List(
@@ -222,24 +222,25 @@ func (pi *podInformer) PodInfo(containerID string) (*PodInfo, error) {
222222
client.MatchingFields{indexContainerID: containerID},
223223
)
224224
if err != nil {
225-
return nil, fmt.Errorf("error retrieving pod info from cache: %w", err)
225+
return nil, "", fmt.Errorf("error retrieving pod info from cache: %w", err)
226226
}
227227

228228
if len(pods.Items) == 0 {
229-
return nil, ErrNoPod
229+
return nil, "", ErrNoPod
230230
}
231231

232232
if len(pods.Items) > 1 {
233-
return nil, fmt.Errorf("multiple pods found for containerID: %s", containerID)
233+
return nil, "", fmt.Errorf("multiple pods found for containerID: %s", containerID)
234234
}
235235

236236
pod := pods.Items[0]
237-
pi.logger.Debug("pod found for container", "container", containerID, "pod", pod.Name)
237+
containerName := pi.findContainerName(&pod, containerID)
238+
pi.logger.Debug("pod found for container", "container", containerID, "pod", pod.Name, "containerName", containerName)
238239
return &PodInfo{
239240
ID: string(pod.UID),
240241
Name: pod.Name,
241242
Namespace: pod.Namespace,
242-
}, nil
243+
}, containerName, nil
243244
}
244245

245246
func getConfig(kubeConfigPath string) (*rest.Config, error) {
@@ -273,3 +274,26 @@ func slogLevelToZapLevel(level slog.Level) zapcore.Level {
273274
return zapcore.ErrorLevel
274275
}
275276
}
277+
278+
// findContainerName finds the container name for a given containerID in the pod
279+
func (pi *podInformer) findContainerName(pod *corev1.Pod, containerID string) string {
280+
// Check regular containers
281+
for _, status := range pod.Status.ContainerStatuses {
282+
if status.ContainerID != "" && extractContainerID(status.ContainerID) == containerID {
283+
return status.Name
284+
}
285+
}
286+
// Check ephemeral containers
287+
for _, status := range pod.Status.EphemeralContainerStatuses {
288+
if status.ContainerID != "" && extractContainerID(status.ContainerID) == containerID {
289+
return status.Name
290+
}
291+
}
292+
// Check init containers
293+
for _, status := range pod.Status.InitContainerStatuses {
294+
if status.ContainerID != "" && extractContainerID(status.ContainerID) == containerID {
295+
return status.Name
296+
}
297+
}
298+
return ""
299+
}

internal/k8s/pod/pod_test.go

Lines changed: 115 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ func TestPodInfo(t *testing.T) {
154154
mock.Anything,
155155
mock.Anything,
156156
).Return(nil)
157-
_, err := pi.PodInfo("container1")
157+
_, _, err := pi.LookupByContainerID("container1")
158158
assert.ErrorIs(t, err, ErrNoPod, "unexpected error returned")
159159
})
160160
t.Run("exactly one pod found", func(t *testing.T) {
@@ -179,11 +179,12 @@ func TestPodInfo(t *testing.T) {
179179
pods := args.Get(1).(*corev1.PodList)
180180
pods.Items = []corev1.Pod{pod1}
181181
})
182-
retPod, err := pi.PodInfo("container1")
182+
retPod, containerName, err := pi.LookupByContainerID("container1")
183183
assert.NoError(t, err)
184184
assert.Equal(t, string(pod1.UID), retPod.ID, "unexpected pod id")
185185
assert.Equal(t, pod1.Name, retPod.Name, "unexpected pod name")
186186
assert.Equal(t, pod1.Namespace, retPod.Namespace, "unexpected pod namespace")
187+
assert.Equal(t, "", containerName, "expected empty container name")
187188
})
188189
t.Run("more than one pod found", func(t *testing.T) {
189190
pi := NewInformer()
@@ -207,7 +208,7 @@ func TestPodInfo(t *testing.T) {
207208
pods := args.Get(1).(*corev1.PodList)
208209
pods.Items = []corev1.Pod{pod1, pod1}
209210
})
210-
_, err := pi.PodInfo("container1")
211+
_, _, err := pi.LookupByContainerID("container1")
211212
assert.ErrorContains(t, err, "multiple pods found for containerID")
212213
})
213214
t.Run("cache error", func(t *testing.T) {
@@ -222,7 +223,7 @@ func TestPodInfo(t *testing.T) {
222223
mock.Anything,
223224
mock.Anything,
224225
).Return(fmt.Errorf("!!you shall not pass!!"))
225-
_, err := pi.PodInfo("container1")
226+
_, _, err := pi.LookupByContainerID("container1")
226227
assert.ErrorContains(t, err, "error retrieving pod info from cache")
227228
})
228229
}
@@ -244,7 +245,7 @@ func TestPodInformer_RunIntegration(t *testing.T) {
244245
},
245246
Status: corev1.PodStatus{
246247
ContainerStatuses: []corev1.ContainerStatus{
247-
{ContainerID: "containerd://abc123"},
248+
{Name: "test-container", ContainerID: "containerd://abc123"},
248249
},
249250
},
250251
}
@@ -279,13 +280,14 @@ func TestPodInformer_RunIntegration(t *testing.T) {
279280

280281
time.Sleep(50 * time.Millisecond)
281282

282-
podInfo, err := pi.PodInfo("abc123")
283+
podInfo, containerName, err := pi.LookupByContainerID("abc123")
283284
if err != nil {
284-
t.Logf("PodInfo lookup failed (expected in fake setup): %v", err)
285+
t.Logf("LookupByContainerID lookup failed (expected in fake setup): %v", err)
285286
} else {
286287
assert.Equal(t, "test-pod", podInfo.Name)
287288
assert.Equal(t, "default", podInfo.Namespace)
288289
assert.Equal(t, "test-uid-123", podInfo.ID)
290+
assert.Equal(t, "test-container", containerName)
289291
}
290292

291293
cancel()
@@ -299,6 +301,112 @@ func TestPodInformer_RunIntegration(t *testing.T) {
299301
})
300302
}
301303

304+
func TestFindContainerName(t *testing.T) {
305+
pi := NewInformer()
306+
307+
t.Run("find container in regular containers", func(t *testing.T) {
308+
pod := &corev1.Pod{
309+
Status: corev1.PodStatus{
310+
ContainerStatuses: []corev1.ContainerStatus{
311+
{Name: "app-container", ContainerID: "containerd://abc123"},
312+
{Name: "sidecar-container", ContainerID: "containerd://def456"},
313+
},
314+
},
315+
}
316+
containerName := pi.findContainerName(pod, "abc123")
317+
assert.Equal(t, "app-container", containerName)
318+
319+
containerName = pi.findContainerName(pod, "def456")
320+
assert.Equal(t, "sidecar-container", containerName)
321+
})
322+
323+
t.Run("find container in ephemeral containers", func(t *testing.T) {
324+
pod := &corev1.Pod{
325+
Status: corev1.PodStatus{
326+
EphemeralContainerStatuses: []corev1.ContainerStatus{
327+
{Name: "debug-container", ContainerID: "cri-o://ephemeral123"},
328+
},
329+
},
330+
}
331+
containerName := pi.findContainerName(pod, "ephemeral123")
332+
assert.Equal(t, "debug-container", containerName)
333+
})
334+
335+
t.Run("find container in init containers", func(t *testing.T) {
336+
pod := &corev1.Pod{
337+
Status: corev1.PodStatus{
338+
InitContainerStatuses: []corev1.ContainerStatus{
339+
{Name: "init-container", ContainerID: "containerd://init123"},
340+
},
341+
},
342+
}
343+
containerName := pi.findContainerName(pod, "init123")
344+
assert.Equal(t, "init-container", containerName)
345+
})
346+
347+
t.Run("container not found returns empty string", func(t *testing.T) {
348+
pod := &corev1.Pod{
349+
Status: corev1.PodStatus{
350+
ContainerStatuses: []corev1.ContainerStatus{
351+
{Name: "app-container", ContainerID: "containerd://abc123"},
352+
},
353+
},
354+
}
355+
containerName := pi.findContainerName(pod, "nonexistent")
356+
assert.Equal(t, "", containerName)
357+
})
358+
359+
t.Run("empty container ID in status", func(t *testing.T) {
360+
pod := &corev1.Pod{
361+
Status: corev1.PodStatus{
362+
ContainerStatuses: []corev1.ContainerStatus{
363+
{Name: "app-container", ContainerID: ""},
364+
{Name: "running-container", ContainerID: "containerd://running123"},
365+
},
366+
},
367+
}
368+
containerName := pi.findContainerName(pod, "running123")
369+
assert.Equal(t, "running-container", containerName)
370+
})
371+
372+
t.Run("mixed container types", func(t *testing.T) {
373+
pod := &corev1.Pod{
374+
Status: corev1.PodStatus{
375+
InitContainerStatuses: []corev1.ContainerStatus{
376+
{Name: "init-container", ContainerID: "containerd://init123"},
377+
},
378+
ContainerStatuses: []corev1.ContainerStatus{
379+
{Name: "app-container", ContainerID: "containerd://app123"},
380+
},
381+
EphemeralContainerStatuses: []corev1.ContainerStatus{
382+
{Name: "debug-container", ContainerID: "cri-o://debug123"},
383+
},
384+
},
385+
}
386+
387+
// Test finding in each type
388+
assert.Equal(t, "init-container", pi.findContainerName(pod, "init123"))
389+
assert.Equal(t, "app-container", pi.findContainerName(pod, "app123"))
390+
assert.Equal(t, "debug-container", pi.findContainerName(pod, "debug123"))
391+
})
392+
393+
t.Run("different container runtime prefixes", func(t *testing.T) {
394+
pod := &corev1.Pod{
395+
Status: corev1.PodStatus{
396+
ContainerStatuses: []corev1.ContainerStatus{
397+
{Name: "containerd-container", ContainerID: "containerd://containerd123"},
398+
{Name: "crio-container", ContainerID: "cri-o://crio123"},
399+
{Name: "docker-container", ContainerID: "docker://docker123"},
400+
},
401+
},
402+
}
403+
404+
assert.Equal(t, "containerd-container", pi.findContainerName(pod, "containerd123"))
405+
assert.Equal(t, "crio-container", pi.findContainerName(pod, "crio123"))
406+
assert.Equal(t, "docker-container", pi.findContainerName(pod, "docker123"))
407+
})
408+
}
409+
302410
func TestSlogLevelToZapLevel(t *testing.T) {
303411
tests := []struct {
304412
input slog.Level

internal/resource/informer.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ func (ri *resourceInformer) Refresh() error {
213213
containersNoPod := []string{}
214214
if ri.podInformer != nil {
215215
for _, container := range containersRunning {
216-
podInfo, err := ri.podInformer.PodInfo(container.ID)
216+
podInfo, containerName, err := ri.podInformer.LookupByContainerID(container.ID)
217217
if err != nil {
218218
if errors.Is(err, pod.ErrNoPod) {
219219
containersNoPod = append(containersNoPod, container.ID)
@@ -229,6 +229,7 @@ func (ri *resourceInformer) Refresh() error {
229229
Namespace: podInfo.Namespace,
230230
}
231231
container.Pod = pod
232+
container.Name = containerName
232233
_, seen := podsRunning[pod.ID]
233234
// reset CPU Time of the pod if it is getting added to the running list for the first time
234235
// in the subsequent iteration, the CPUTimeDelta should be incremented by container's CPUTimeDelta

internal/resource/mock_procfs_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,12 +102,12 @@ func (m *mockPodInformer) Run(ctx context.Context) error {
102102
return args.Error(0)
103103
}
104104

105-
func (m *mockPodInformer) PodInfo(containerID string) (*pod.PodInfo, error) {
105+
func (m *mockPodInformer) LookupByContainerID(containerID string) (*pod.PodInfo, string, error) {
106106
args := m.Called(containerID)
107107
if podInfo, ok := args.Get(0).(*pod.PodInfo); ok {
108-
return podInfo, args.Error(1)
108+
return podInfo, args.String(1), args.Error(2)
109109
}
110-
return nil, args.Error(1)
110+
return nil, args.String(1), args.Error(2)
111111
}
112112

113113
func (m *mockPodInformer) Name() string {

0 commit comments

Comments
 (0)