Skip to content

Commit bec7b86

Browse files
authored
Merge pull request #2166 from sthaha/refactor-pod-ctnr-lookup
refactor(pod): simplify Lookup returning Container Name
2 parents 8168279 + cc8d73c commit bec7b86

File tree

5 files changed

+93
-86
lines changed

5 files changed

+93
-86
lines changed

internal/k8s/pod/pod.go

Lines changed: 34 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ package pod
55

66
import (
77
"context"
8-
"errors"
98
"fmt"
109
"log/slog"
1110
"strings"
@@ -25,10 +24,6 @@ import (
2524
"sigs.k8s.io/controller-runtime/pkg/manager"
2625
)
2726

28-
var (
29-
ErrNoPod = errors.New("no pod found for container")
30-
)
31-
3227
const (
3328
indexContainerID = "containerID"
3429
)
@@ -37,30 +32,29 @@ type (
3732
Informer interface {
3833
service.Initializer
3934
service.Runner
40-
LookupByContainerID(containerID string) (*PodInfo, string, error)
35+
LookupByContainerID(containerID string) (*ContainerInfo, bool, error)
4136
}
4237

43-
PodInfo struct {
44-
ID string
45-
Name string
46-
Namespace string
38+
ContainerInfo struct {
39+
PodID string
40+
PodName string
41+
Namespace string
42+
ContainerName string
4743
}
48-
)
4944

50-
type podInformer struct {
51-
logger *slog.Logger
45+
podInformer struct {
46+
logger *slog.Logger
5247

53-
kubeConfigPath string
54-
nodeName string
48+
kubeConfigPath string
49+
nodeName string
5550

56-
cfg *rest.Config
57-
manager manager.Manager
51+
cfg *rest.Config
52+
manager manager.Manager
5853

59-
createRestConfigFunc func(kubeConfigPath string) (*rest.Config, error)
60-
newManagerFunc func(config *rest.Config, options ctrl.Options) (ctrl.Manager, error)
61-
}
54+
createRestConfigFunc func(kubeConfigPath string) (*rest.Config, error)
55+
newManagerFunc func(config *rest.Config, options ctrl.Options) (ctrl.Manager, error)
56+
}
6257

63-
type (
6458
Option struct {
6559
logger *slog.Logger
6660
kubeConfigPath string
@@ -140,7 +134,6 @@ func (pi *podInformer) Init() error {
140134
}
141135

142136
func (pi *podInformer) setupManager(scheme *k8sruntime.Scheme) (ctrl.Manager, error) {
143-
144137
cacheOp := cache.Options{}
145138
cacheOp.ByObject = map[client.Object]cache.ByObject{
146139
&corev1.Pod{}: {
@@ -213,7 +206,7 @@ func (pi *podInformer) Run(ctx context.Context) error {
213206
}
214207

215208
// LookupByContainerID retrieves pod details and container name given a containerID
216-
func (pi *podInformer) LookupByContainerID(containerID string) (*PodInfo, string, error) {
209+
func (pi *podInformer) LookupByContainerID(containerID string) (*ContainerInfo, bool, error) {
217210
var pods corev1.PodList
218211

219212
err := pi.manager.GetCache().List(
@@ -222,25 +215,27 @@ func (pi *podInformer) LookupByContainerID(containerID string) (*PodInfo, string
222215
client.MatchingFields{indexContainerID: containerID},
223216
)
224217
if err != nil {
225-
return nil, "", fmt.Errorf("error retrieving pod info from cache: %w", err)
218+
return nil, false, fmt.Errorf("error retrieving pod info from cache: %w", err)
226219
}
227220

228-
if len(pods.Items) == 0 {
229-
return nil, "", ErrNoPod
221+
switch count := len(pods.Items); {
222+
case count == 0:
223+
return nil, false, nil
224+
case count > 1:
225+
return nil, false, fmt.Errorf("multiple pods found for containerID: %s", containerID)
226+
227+
default: // case x == 1:
228+
pod := pods.Items[0]
229+
containerName := pi.findContainerName(&pod, containerID)
230+
pi.logger.Debug("pod found for container", "container", containerID, "pod", pod.Name, "containerName", containerName)
231+
232+
return &ContainerInfo{
233+
PodID: string(pod.UID),
234+
PodName: pod.Name,
235+
Namespace: pod.Namespace,
236+
ContainerName: containerName,
237+
}, true, nil
230238
}
231-
232-
if len(pods.Items) > 1 {
233-
return nil, "", fmt.Errorf("multiple pods found for containerID: %s", containerID)
234-
}
235-
236-
pod := pods.Items[0]
237-
containerName := pi.findContainerName(&pod, containerID)
238-
pi.logger.Debug("pod found for container", "container", containerID, "pod", pod.Name, "containerName", containerName)
239-
return &PodInfo{
240-
ID: string(pod.UID),
241-
Name: pod.Name,
242-
Namespace: pod.Namespace,
243-
}, containerName, nil
244239
}
245240

246241
func getConfig(kubeConfigPath string) (*rest.Config, error) {

internal/k8s/pod/pod_test.go

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,10 @@ func TestPodInfo(t *testing.T) {
154154
mock.Anything,
155155
mock.Anything,
156156
).Return(nil)
157-
_, _, err := pi.LookupByContainerID("container1")
158-
assert.ErrorIs(t, err, ErrNoPod, "unexpected error returned")
157+
containerInfo, found, err := pi.LookupByContainerID("container1")
158+
assert.NoError(t, err)
159+
assert.False(t, found, "expected container not to be found")
160+
assert.Nil(t, containerInfo, "expected nil container info")
159161
})
160162
t.Run("exactly one pod found", func(t *testing.T) {
161163
pi := NewInformer()
@@ -179,12 +181,14 @@ func TestPodInfo(t *testing.T) {
179181
pods := args.Get(1).(*corev1.PodList)
180182
pods.Items = []corev1.Pod{pod1}
181183
})
182-
retPod, containerName, err := pi.LookupByContainerID("container1")
184+
containerInfo, found, err := pi.LookupByContainerID("container1")
183185
assert.NoError(t, err)
184-
assert.Equal(t, string(pod1.UID), retPod.ID, "unexpected pod id")
185-
assert.Equal(t, pod1.Name, retPod.Name, "unexpected pod name")
186-
assert.Equal(t, pod1.Namespace, retPod.Namespace, "unexpected pod namespace")
187-
assert.Equal(t, "", containerName, "expected empty container name")
186+
assert.True(t, found, "expected container to be found")
187+
assert.NotNil(t, containerInfo, "expected non-nil container info")
188+
assert.Equal(t, string(pod1.UID), containerInfo.PodID, "unexpected pod id")
189+
assert.Equal(t, pod1.Name, containerInfo.PodName, "unexpected pod name")
190+
assert.Equal(t, pod1.Namespace, containerInfo.Namespace, "unexpected pod namespace")
191+
assert.Equal(t, "", containerInfo.ContainerName, "expected empty container name")
188192
})
189193
t.Run("more than one pod found", func(t *testing.T) {
190194
pi := NewInformer()
@@ -208,7 +212,8 @@ func TestPodInfo(t *testing.T) {
208212
pods := args.Get(1).(*corev1.PodList)
209213
pods.Items = []corev1.Pod{pod1, pod1}
210214
})
211-
_, _, err := pi.LookupByContainerID("container1")
215+
_, found, err := pi.LookupByContainerID("container1")
216+
assert.False(t, found, "expected container not to be found due to multiple pods")
212217
assert.ErrorContains(t, err, "multiple pods found for containerID")
213218
})
214219
t.Run("cache error", func(t *testing.T) {
@@ -223,7 +228,8 @@ func TestPodInfo(t *testing.T) {
223228
mock.Anything,
224229
mock.Anything,
225230
).Return(fmt.Errorf("!!you shall not pass!!"))
226-
_, _, err := pi.LookupByContainerID("container1")
231+
_, found, err := pi.LookupByContainerID("container1")
232+
assert.False(t, found, "expected container not to be found due to cache error")
227233
assert.ErrorContains(t, err, "error retrieving pod info from cache")
228234
})
229235
}
@@ -280,14 +286,14 @@ func TestPodInformer_RunIntegration(t *testing.T) {
280286

281287
time.Sleep(50 * time.Millisecond)
282288

283-
podInfo, containerName, err := pi.LookupByContainerID("abc123")
289+
containerInfo, found, err := pi.LookupByContainerID("abc123")
284290
if err != nil {
285291
t.Logf("LookupByContainerID lookup failed (expected in fake setup): %v", err)
286-
} else {
287-
assert.Equal(t, "test-pod", podInfo.Name)
288-
assert.Equal(t, "default", podInfo.Namespace)
289-
assert.Equal(t, "test-uid-123", podInfo.ID)
290-
assert.Equal(t, "test-container", containerName)
292+
} else if found {
293+
assert.Equal(t, "test-pod", containerInfo.PodName)
294+
assert.Equal(t, "default", containerInfo.Namespace)
295+
assert.Equal(t, "test-uid-123", containerInfo.PodID)
296+
assert.Equal(t, "test-container", containerInfo.ContainerName)
291297
}
292298

293299
cancel()

internal/resource/informer.go

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -213,23 +213,26 @@ func (ri *resourceInformer) Refresh() error {
213213
containersNoPod := []string{}
214214
if ri.podInformer != nil {
215215
for _, container := range containersRunning {
216-
podInfo, containerName, err := ri.podInformer.LookupByContainerID(container.ID)
216+
cntrInfo, found, err := ri.podInformer.LookupByContainerID(container.ID)
217217
if err != nil {
218-
if errors.Is(err, pod.ErrNoPod) {
219-
containersNoPod = append(containersNoPod, container.ID)
220-
} else {
221-
ri.logger.Debug("Failed to get pod for container", "container", container.ID, "error", err)
222-
refreshErrs = errors.Join(refreshErrs, fmt.Errorf("failed to get pod for container: %w", err))
223-
}
218+
ri.logger.Debug("Failed to get pod for container", "container", container.ID, "error", err)
219+
refreshErrs = errors.Join(refreshErrs, fmt.Errorf("failed to get pod for container: %w", err))
224220
continue
225221
}
222+
223+
if !found {
224+
containersNoPod = append(containersNoPod, container.ID)
225+
continue
226+
}
227+
226228
pod := &Pod{
227-
ID: podInfo.ID,
228-
Name: podInfo.Name,
229-
Namespace: podInfo.Namespace,
229+
ID: cntrInfo.PodID,
230+
Name: cntrInfo.PodName,
231+
Namespace: cntrInfo.Namespace,
230232
}
231233
container.Pod = pod
232-
container.Name = containerName
234+
container.Name = cntrInfo.ContainerName
235+
233236
_, seen := podsRunning[pod.ID]
234237
// reset CPU Time of the pod if it is getting added to the running list for the first time
235238
// in the subsequent iteration, the CPUTimeDelta should be incremented by container's CPUTimeDelta

internal/resource/mock_procfs_test.go

Lines changed: 4 additions & 4 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) LookupByContainerID(containerID string) (*pod.PodInfo, string, error) {
105+
func (m *mockPodInformer) LookupByContainerID(containerID string) (*pod.ContainerInfo, bool, error) {
106106
args := m.Called(containerID)
107-
if podInfo, ok := args.Get(0).(*pod.PodInfo); ok {
108-
return podInfo, args.String(1), args.Error(2)
107+
if podInfo, ok := args.Get(0).(*pod.ContainerInfo); ok {
108+
return podInfo, args.Bool(1), args.Error(2)
109109
}
110-
return nil, args.String(1), args.Error(2)
110+
return nil, args.Bool(1), args.Error(2)
111111
}
112112

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

internal/resource/procfs_reader_test.go

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -477,11 +477,12 @@ func TestRefresh_PodInformer(t *testing.T) {
477477

478478
mockPodInformer := new(mockPodInformer)
479479
mockPodInformer.On("LookupByContainerID", containerID).Return(
480-
&pod.PodInfo{
481-
ID: "pod123",
482-
Name: "mypod",
483-
Namespace: "default",
484-
}, "my-container", nil,
480+
&pod.ContainerInfo{
481+
PodID: "pod123",
482+
PodName: "mypod",
483+
Namespace: "default",
484+
ContainerName: "my-container",
485+
}, true, nil,
485486
)
486487

487488
informer, err := NewInformer(WithProcReader(mockProcFS), WithPodInformer(mockPodInformer))
@@ -516,7 +517,7 @@ func TestRefresh_PodInformer(t *testing.T) {
516517
mockProcFS.On("CPUUsageRatio").Return(0.5, nil).Once()
517518

518519
mockPodInformer := new(mockPodInformer)
519-
mockPodInformer.On("LookupByContainerID", containerID).Return(nil, "", pod.ErrNoPod)
520+
mockPodInformer.On("LookupByContainerID", containerID).Return(nil, false, nil)
520521

521522
informer, err := NewInformer(
522523
WithProcReader(mockProcFS),
@@ -556,7 +557,7 @@ func TestRefresh_PodInformer(t *testing.T) {
556557

557558
podError := errors.New("general error")
558559
mockPodInformer := new(mockPodInformer)
559-
mockPodInformer.On("LookupByContainerID", containerID).Return(nil, "", podError)
560+
mockPodInformer.On("LookupByContainerID", containerID).Return(nil, false, podError)
560561

561562
informer, err := NewInformer(
562563
WithProcReader(mockProcFS),
@@ -602,11 +603,12 @@ func TestLookupByContainerID_UpdatesContainerName(t *testing.T) {
602603
// Mock pod informer that returns container name from pod info
603604
mockPodInformer := new(mockPodInformer)
604605
mockPodInformer.On("LookupByContainerID", containerID).Return(
605-
&pod.PodInfo{
606-
ID: "pod-12345",
607-
Name: "test-app-pod",
608-
Namespace: "production",
609-
}, "app-container-from-pod", nil, // Container name comes from pod status
606+
&pod.ContainerInfo{
607+
PodID: "pod-12345",
608+
PodName: "test-app-pod",
609+
Namespace: "production",
610+
ContainerName: "app-container-from-pod", // Container name comes from pod status
611+
}, true, nil,
610612
)
611613

612614
informer, err := NewInformer(
@@ -671,11 +673,12 @@ func TestLookupByContainerID_UpdatesContainerName(t *testing.T) {
671673
// Pod informer returns different name than environment
672674
mockPodInformer := new(mockPodInformer)
673675
mockPodInformer.On("LookupByContainerID", containerID).Return(
674-
&pod.PodInfo{
675-
ID: "web-pod-67890",
676-
Name: "web-server",
677-
Namespace: "default",
678-
}, "nginx-from-pod", nil, // Different from environment name
676+
&pod.ContainerInfo{
677+
PodID: "web-pod-67890",
678+
PodName: "web-server",
679+
Namespace: "default",
680+
ContainerName: "nginx-from-pod", // Different from environment name
681+
}, true, nil,
679682
)
680683

681684
informer, err := NewInformer(

0 commit comments

Comments
 (0)