Skip to content

Commit d90c753

Browse files
committed
fact(NPC): refactor isPodUpdateNetPolRelevant
Refactor this logic so that it can be more easily tested and expanded without cluttering the pod.go file. Additionally, add some safe guards around the pod cast to ensure that we're working with pods before we pass them.
1 parent 1a82db7 commit d90c753

File tree

3 files changed

+68
-7
lines changed

3 files changed

+68
-7
lines changed

pkg/controllers/netpol/pod.go

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package netpol
33
import (
44
"crypto/sha256"
55
"encoding/base32"
6-
"reflect"
76
"strings"
87

98
api "k8s.io/api/core/v1"
@@ -23,12 +22,21 @@ func (npc *NetworkPolicyController) newPodEventHandler() cache.ResourceEventHand
2322
}
2423
},
2524
UpdateFunc: func(oldObj, newObj interface{}) {
26-
newPodObj := newObj.(*api.Pod)
27-
oldPodObj := oldObj.(*api.Pod)
28-
if newPodObj.Status.Phase != oldPodObj.Status.Phase ||
29-
newPodObj.Status.PodIP != oldPodObj.Status.PodIP ||
30-
!reflect.DeepEqual(newPodObj.Labels, oldPodObj.Labels) {
31-
// for the network policies, we are only interested in pod status phase change or IP change
25+
var newPodObj, oldPodObj *api.Pod
26+
var ok bool
27+
28+
// If either of these objects are not pods, quit now
29+
if newPodObj, ok = newObj.(*api.Pod); !ok {
30+
return
31+
}
32+
if oldPodObj, ok = oldObj.(*api.Pod); !ok {
33+
return
34+
}
35+
36+
// We don't check isNetPolActionable here, because if it is transitioning in or out of the actionable state
37+
// we want to run the full sync so that it can be added or removed from the existing network policy of the host
38+
// For the network policies, we are only interested in some changes, most pod changes aren't relevant to network policy
39+
if isPodUpdateNetPolRelevant(oldPodObj, newPodObj) {
3240
npc.OnPodUpdate(newObj)
3341
}
3442
},

pkg/controllers/netpol/utils.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package netpol
22

33
import (
44
"fmt"
5+
"reflect"
56
"regexp"
67
"strconv"
78

@@ -12,6 +13,20 @@ const (
1213
PodCompleted api.PodPhase = "Completed"
1314
)
1415

16+
// isPodUpdateNetPolRelevant checks the attributes that we care about for building NetworkPolicies on the host and if it
17+
// finds a relevant change, it returns true otherwise it returns false. The things we care about for NetworkPolicies:
18+
// 1) Is the phase of the pod changing? (matters for catching completed, succeeded, or failed jobs)
19+
// 2) Is the pod IP changing? (changes how the network policy is applied to the host)
20+
// 3) Is the pod's host IP changing? (should be caught in the above, with the CNI kube-router runs with but we check this as well for sanity)
21+
// 4) Is a pod's label changing? (potentially changes which NetworkPolicies select this pod)
22+
func isPodUpdateNetPolRelevant(oldPod, newPod *api.Pod) bool {
23+
return newPod.Status.Phase != oldPod.Status.Phase ||
24+
newPod.Status.PodIP != oldPod.Status.PodIP ||
25+
!reflect.DeepEqual(newPod.Status.PodIPs, oldPod.Status.PodIPs) ||
26+
newPod.Status.HostIP != oldPod.Status.HostIP ||
27+
!reflect.DeepEqual(newPod.Labels, oldPod.Labels)
28+
}
29+
1530
func isNetPolActionable(pod *api.Pod) bool {
1631
return !isFinished(pod) && pod.Status.PodIP != "" && !pod.Spec.HostNetwork
1732
}

pkg/controllers/netpol/utils_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,44 @@ var (
3838
}
3939
)
4040

41+
func Test_isPodUpdateNetPolRelevant(t *testing.T) {
42+
t.Run("Pod phase change should be detected as NetworkPolicy relevant", func(t *testing.T) {
43+
newPod := fakePod.DeepCopy()
44+
newPod.Status.Phase = api.PodFailed
45+
assert.True(t, isPodUpdateNetPolRelevant(&fakePod, newPod))
46+
})
47+
t.Run("Pod IP change should be detected as NetworkPolicy relevant", func(t *testing.T) {
48+
newPod := fakePod.DeepCopy()
49+
newPod.Status.PodIP = "172.16.0.2"
50+
assert.True(t, isPodUpdateNetPolRelevant(&fakePod, newPod))
51+
})
52+
t.Run("Pod IPs change should be detected as NetworkPolicy relevant", func(t *testing.T) {
53+
newPod := fakePod.DeepCopy()
54+
newPod.Status.PodIPs = []api.PodIP{{IP: "172.16.0.2"}}
55+
assert.True(t, isPodUpdateNetPolRelevant(&fakePod, newPod))
56+
})
57+
t.Run("Pod Label change should be detected as NetworkPolicy relevant", func(t *testing.T) {
58+
newPod := fakePod.DeepCopy()
59+
newPod.ObjectMeta.Labels = map[string]string{"bar": "foo"}
60+
assert.True(t, isPodUpdateNetPolRelevant(&fakePod, newPod))
61+
})
62+
t.Run("Pod Host IP change should be detected as NetworkPolicy relevant", func(t *testing.T) {
63+
newPod := fakePod.DeepCopy()
64+
newPod.Status.HostIP = "10.0.0.2"
65+
assert.True(t, isPodUpdateNetPolRelevant(&fakePod, newPod))
66+
})
67+
t.Run("Pod Image change should NOT be detected as NetworkPolicy relevant", func(t *testing.T) {
68+
newPod := fakePod.DeepCopy()
69+
newPod.Spec.Containers[0].Image = "k8s.gcr.io/otherimage"
70+
assert.False(t, isPodUpdateNetPolRelevant(&fakePod, newPod))
71+
})
72+
t.Run("Pod Name change should NOT be detected as NetworkPolicy relevant", func(t *testing.T) {
73+
newPod := fakePod.DeepCopy()
74+
newPod.ObjectMeta.Name = "otherpod"
75+
assert.False(t, isPodUpdateNetPolRelevant(&fakePod, newPod))
76+
})
77+
}
78+
4179
func Test_isPodFinished(t *testing.T) {
4280
t.Run("Failed pod should be detected as finished", func(t *testing.T) {
4381
fakePod.Status.Phase = api.PodFailed

0 commit comments

Comments
 (0)