diff --git a/npc/controller.go b/npc/controller.go index 09a7556f..841afec9 100644 --- a/npc/controller.go +++ b/npc/controller.go @@ -61,9 +61,9 @@ func New(nodeName string, ipt iptables.Interface, ips ipset.Interface, clientset func (npc *controller) onNewNsSelector(selector *selector) error { for _, ns := range npc.nss { - if ns.namespace != nil { - if selector.matchesNamespaceSelector(ns.namespace.ObjectMeta.Labels) { - if err := selector.addEntry(nsuid(ns.namespace), string(ns.allPods.ipsetName), namespaceComment(ns)); err != nil { + if ns.namespaceUID != "" { + if selector.matchesNamespaceSelector(ns.namespaceLabels) { + if err := selector.addEntry(ns.namespaceUID, string(ns.allPods.ipsetName), namespaceComment(ns)); err != nil { return err } } @@ -74,10 +74,10 @@ func (npc *controller) onNewNsSelector(selector *selector) error { func (npc *controller) onNewNamespacePodsSelector(selector *selector) error { for _, ns := range npc.nss { - if ns.namespace != nil && len(ns.pods) > 0 { + if ns.namespaceUID != "" && len(ns.pods) > 0 { for _, pod := range ns.pods { if hasIP(pod) { - if selector.matchesNamespacedPodSelector(pod.ObjectMeta.Labels, ns.namespace.ObjectMeta.Labels) { + if selector.matchesNamespacedPodSelector(pod.ObjectMeta.Labels, ns.namespaceLabels) { if err := selector.addEntry(uid(pod), pod.Status.PodIP, podComment(pod)); err != nil { return err } diff --git a/npc/controller_test.go b/npc/controller_test.go index cf78241d..1f6cd266 100644 --- a/npc/controller_test.go +++ b/npc/controller_test.go @@ -160,6 +160,7 @@ func TestRegressionPolicyNamespaceOrdering3059(t *testing.T) { sourceNamespace := &coreapi.Namespace{ ObjectMeta: metav1.ObjectMeta{ Name: "source", + UID: "source", Labels: map[string]string{ "app": "source", }, @@ -169,6 +170,7 @@ func TestRegressionPolicyNamespaceOrdering3059(t *testing.T) { destinationNamespace := &coreapi.Namespace{ ObjectMeta: metav1.ObjectMeta{ Name: "destination", + UID: "destination", }, } @@ -249,6 +251,7 @@ func TestDefaultAllow(t *testing.T) { defaultNamespace := &coreapi.Namespace{ ObjectMeta: metav1.ObjectMeta{ Name: "default", + UID: "default", }, } controller.AddNamespace(defaultNamespace) @@ -378,6 +381,7 @@ func TestOutOfOrderPodEvents(t *testing.T) { defaultNamespace := &coreapi.Namespace{ ObjectMeta: metav1.ObjectMeta{ Name: "default", + UID: "default", }, } client.CoreV1().Namespaces().Create(defaultNamespace) @@ -462,6 +466,7 @@ func TestNewTargetSelector(t *testing.T) { defaultNamespace := &coreapi.Namespace{ ObjectMeta: metav1.ObjectMeta{ Name: "default", + UID: "default", }, } client.CoreV1().Namespaces().Create(defaultNamespace) @@ -540,11 +545,13 @@ func TestEgressPolicyWithIPBlock(t *testing.T) { defaultNamespace := &coreapi.Namespace{ ObjectMeta: metav1.ObjectMeta{ Name: "default", + UID: "default", }, } nonDefaultNamespace := &coreapi.Namespace{ ObjectMeta: metav1.ObjectMeta{ Name: "non-default", + UID: "non-default", }, } client.CoreV1().Namespaces().Create(defaultNamespace) @@ -635,6 +642,7 @@ func TestIngressPolicyWithIPBlockAndPortSpecified(t *testing.T) { defaultNamespace := &coreapi.Namespace{ ObjectMeta: metav1.ObjectMeta{ Name: "default", + UID: "default", }, } diff --git a/npc/namespace.go b/npc/namespace.go index 13e59651..7bbc723b 100644 --- a/npc/namespace.go +++ b/npc/namespace.go @@ -22,11 +22,12 @@ type ns struct { ipt iptables.Interface // interface to iptables ips ipset.Interface // interface to ipset - name string // k8s Namespace name - nodeName string // my node name - namespace *coreapi.Namespace // k8s Namespace object - pods map[ipset.UID]*coreapi.Pod // k8s Pod objects by UID - policies map[ipset.UID]interface{} // k8s NetworkPolicy objects by UID + name string // k8s Namespace name + nodeName string // my node name + namespaceUID ipset.UID // k8s Namespace UID + namespaceLabels map[string]string // k8s Namespace labels + pods map[ipset.UID]*coreapi.Pod // k8s Pod objects by UID + policies map[ipset.UID]interface{} // k8s NetworkPolicy objects by UID uid ipset.UID // surrogate UID to own allPods selector allPods *selectorSpec // hash:ip ipset of all pod IPs in this namespace @@ -54,7 +55,8 @@ func newNS(name, nodeName string, ipt iptables.Interface, ips ipset.Interface, n ipt: ipt, ips: ips, name: name, - namespace: namespaceObj, + namespaceUID: nsuid(namespaceObj), + namespaceLabels: namespaceObj.ObjectMeta.Labels, nodeName: nodeName, pods: make(map[ipset.UID]*coreapi.Pod), policies: make(map[ipset.UID]interface{}), @@ -88,7 +90,7 @@ func newNS(name, nodeName string, ipt iptables.Interface, ips ipset.Interface, n } func (ns *ns) empty() bool { - return len(ns.pods) == 0 && len(ns.policies) == 0 && ns.namespace == nil + return len(ns.pods) == 0 && len(ns.policies) == 0 && ns.namespaceUID == "" } func (ns *ns) destroy() error { @@ -181,7 +183,7 @@ func (ns *ns) addPod(obj *coreapi.Pod) error { } } - err = ns.namespacedPodsSelectors.addToMatchingNamespacedPodSelector(uid(obj), obj.ObjectMeta.Labels, ns.namespace.ObjectMeta.Labels, obj.Status.PodIP, podComment(obj)) + err = ns.namespacedPodsSelectors.addToMatchingNamespacedPodSelector(uid(obj), obj.ObjectMeta.Labels, ns.namespaceLabels, obj.Status.PodIP, podComment(obj)) if err != nil { return err } @@ -204,7 +206,7 @@ func (ns *ns) updatePod(oldObj, newObj *coreapi.Pod) error { if err := ns.ips.DelEntry(uid(oldObj), ns.egressDefaultAllowIPSet, oldObj.Status.PodIP); err != nil { return err } - if err := ns.namespacedPodsSelectors.delFromMatchingNamespacedPodSelector(uid(oldObj), oldObj.ObjectMeta.Labels, ns.namespace.ObjectMeta.Labels, oldObj.Status.PodIP); err != nil { + if err := ns.namespacedPodsSelectors.delFromMatchingNamespacedPodSelector(uid(oldObj), oldObj.ObjectMeta.Labels, ns.namespaceLabels, oldObj.Status.PodIP); err != nil { return err } @@ -227,7 +229,7 @@ func (ns *ns) updatePod(oldObj, newObj *coreapi.Pod) error { return err } } - err = ns.namespacedPodsSelectors.addToMatchingNamespacedPodSelector(uid(newObj), newObj.ObjectMeta.Labels, ns.namespace.ObjectMeta.Labels, newObj.Status.PodIP, podComment(newObj)) + err = ns.namespacedPodsSelectors.addToMatchingNamespacedPodSelector(uid(newObj), newObj.ObjectMeta.Labels, ns.namespaceLabels, newObj.Status.PodIP, podComment(newObj)) if err != nil { return err } @@ -272,8 +274,8 @@ func (ns *ns) updatePod(oldObj, newObj *coreapi.Pod) error { } } for _, ps := range ns.namespacedPodsSelectors.entries { - oldMatch := ps.matchesNamespacedPodSelector(oldObj.ObjectMeta.Labels, ns.namespace.ObjectMeta.Labels) - newMatch := ps.matchesNamespacedPodSelector(newObj.ObjectMeta.Labels, ns.namespace.ObjectMeta.Labels) + oldMatch := ps.matchesNamespacedPodSelector(oldObj.ObjectMeta.Labels, ns.namespaceLabels) + newMatch := ps.matchesNamespacedPodSelector(newObj.ObjectMeta.Labels, ns.namespaceLabels) if oldMatch == newMatch && oldObj.Status.PodIP == newObj.Status.PodIP { continue } @@ -326,7 +328,7 @@ func (ns *ns) deletePod(obj *coreapi.Pod) error { if err := ns.podSelectors.delFromMatchingPodSelector(uid(obj), obj.ObjectMeta.Labels, obj.Status.PodIP); err != nil { return err } - if err := ns.namespacedPodsSelectors.delFromMatchingNamespacedPodSelector(uid(obj), obj.ObjectMeta.Labels, ns.namespace.ObjectMeta.Labels, obj.Status.PodIP); err != nil { + if err := ns.namespacedPodsSelectors.delFromMatchingNamespacedPodSelector(uid(obj), obj.ObjectMeta.Labels, ns.namespaceLabels, obj.Status.PodIP); err != nil { return err } return nil @@ -488,7 +490,8 @@ func (ns *ns) deleteBypassRules() error { } func (ns *ns) addNamespace(obj *coreapi.Namespace) error { - ns.namespace = obj + ns.namespaceUID = ipset.UID(obj.ObjectMeta.UID) + ns.namespaceLabels = obj.ObjectMeta.Labels // Insert a rule to bypass policies if err := ns.ensureBypassRules(); err != nil { @@ -501,10 +504,10 @@ func (ns *ns) addNamespace(obj *coreapi.Namespace) error { } func (ns *ns) updateNamespace(oldObj, newObj *coreapi.Namespace) error { - ns.namespace = newObj - // Re-evaluate namespace selector membership if labels have changed if !equals(oldObj.ObjectMeta.Labels, newObj.ObjectMeta.Labels) { + ns.namespaceLabels = newObj.ObjectMeta.Labels + for _, selector := range ns.nsSelectors.entries { oldMatch := selector.matchesNamespaceSelector(oldObj.ObjectMeta.Labels) newMatch := selector.matchesNamespaceSelector(newObj.ObjectMeta.Labels) @@ -512,12 +515,12 @@ func (ns *ns) updateNamespace(oldObj, newObj *coreapi.Namespace) error { continue } if oldMatch { - if err := selector.delEntry(nsuid(ns.namespace), string(ns.allPods.ipsetName)); err != nil { + if err := selector.delEntry(ns.namespaceUID, string(ns.allPods.ipsetName)); err != nil { return err } } if newMatch { - if err := selector.addEntry(nsuid(ns.namespace), string(ns.allPods.ipsetName), namespaceComment(ns)); err != nil { + if err := selector.addEntry(ns.namespaceUID, string(ns.allPods.ipsetName), namespaceComment(ns)); err != nil { return err } } @@ -528,7 +531,7 @@ func (ns *ns) updateNamespace(oldObj, newObj *coreapi.Namespace) error { } func (ns *ns) deleteNamespace(obj *coreapi.Namespace) error { - ns.namespace = nil + ns.namespaceUID = "" // Remove bypass rule if err := ns.deleteBypassRules(); err != nil {