@@ -448,6 +448,163 @@ var _ = Describe("OVN External Gateway pod", func() {
448448 })
449449
450450 })
451+
452+ var _ = Context ("When pod goes into terminating or not ready state" , func () {
453+
454+ DescribeTable ("reconciles a pod gateway in terminating or not ready state that matches two policies" , func (
455+ terminating bool ,
456+ ) {
457+ initController ([]runtime.Object {namespaceGW , namespaceTarget , namespaceTarget2 , targetPod1 , targetPod2 , pod1 },
458+ []runtime.Object {dynamicPolicy , dynamicPolicyDiffTargetNS })
459+
460+ expectedPolicy1 , expectedRefs1 := expectedPolicyStateAndRefs (
461+ []* namespaceWithPods {namespaceTarget2WithPod },
462+ nil ,
463+ []* namespaceWithPods {namespaceGWWithPod }, false )
464+
465+ expectedPolicy2 , expectedRefs2 := expectedPolicyStateAndRefs (
466+ []* namespaceWithPods {namespaceTargetWithPod },
467+ nil ,
468+ []* namespaceWithPods {namespaceGWWithPod }, false )
469+
470+ eventuallyExpectNumberOfPolicies (2 )
471+ eventuallyExpectConfig (dynamicPolicy .Name , expectedPolicy1 , expectedRefs1 )
472+ eventuallyExpectConfig (dynamicPolicyDiffTargetNS .Name , expectedPolicy2 , expectedRefs2 )
473+
474+ if terminating {
475+ By ("Setting deletion timestamp for the ex gw pod" )
476+ setPodDeletionTimestamp (pod1 , & metav1.Time {Time : time .Now ().Add (1000 * time .Second )}, fakeClient )
477+ } else {
478+ By ("Updating the ex gw pod status to mark it as not ready" )
479+ setPodConditionReady (pod1 , corev1 .ConditionFalse , fakeClient )
480+ }
481+
482+ expectedPolicy1 , expectedRefs1 = expectedPolicyStateAndRefs (
483+ []* namespaceWithPods {namespaceTarget2WithPod },
484+ nil ,
485+ []* namespaceWithPods {namespaceGWWithoutPod }, false )
486+
487+ expectedPolicy2 , expectedRefs2 = expectedPolicyStateAndRefs (
488+ []* namespaceWithPods {namespaceTargetWithPod },
489+ nil ,
490+ []* namespaceWithPods {namespaceGWWithoutPod }, false )
491+
492+ eventuallyExpectNumberOfPolicies (2 )
493+ eventuallyExpectConfig (dynamicPolicy .Name , expectedPolicy1 , expectedRefs1 )
494+ eventuallyExpectConfig (dynamicPolicyDiffTargetNS .Name , expectedPolicy2 , expectedRefs2 )
495+ },
496+ Entry ("Gateway pod in terminating state" , true ),
497+ Entry ("Gateway pod in not ready state" , false ),
498+ )
499+
500+ DescribeTable ("reconciles a pod gateway in terminating or not ready state that does not match any policy" , func (
501+ terminating bool ,
502+ ) {
503+ noMatchPolicy := newPolicy (
504+ "noMatchPolicy" ,
505+ & metav1.LabelSelector {MatchLabels : targetNamespace1Match },
506+ nil ,
507+ & metav1.LabelSelector {MatchLabels : gatewayNamespaceMatch },
508+ & metav1.LabelSelector {MatchLabels : map [string ]string {"key" : "nomatch" }},
509+ false ,
510+ )
511+ initController ([]runtime.Object {namespaceGW , namespaceTarget , pod1 }, []runtime.Object {noMatchPolicy })
512+
513+ expectedPolicy , expectedRefs := expectedPolicyStateAndRefs (
514+ []* namespaceWithPods {namespaceTargetWithoutPod },
515+ nil ,
516+ []* namespaceWithPods {namespaceGWWithoutPod }, false )
517+
518+ eventuallyExpectNumberOfPolicies (1 )
519+ eventuallyExpectConfig (noMatchPolicy .Name , expectedPolicy , expectedRefs )
520+
521+ if terminating {
522+ By ("Setting deletion timestamp for the ex gw pod" )
523+ setPodDeletionTimestamp (pod1 , & metav1.Time {Time : time .Now ().Add (1000 * time .Second )}, fakeClient )
524+ } else {
525+ By ("Updating the ex gw pod status to mark it as not ready" )
526+ setPodConditionReady (pod1 , corev1 .ConditionFalse , fakeClient )
527+ }
528+ // make sure pod event is handled
529+ time .Sleep (100 * time .Millisecond )
530+
531+ eventuallyExpectNumberOfPolicies (1 )
532+ eventuallyExpectConfig (noMatchPolicy .Name , expectedPolicy , expectedRefs )
533+ },
534+ Entry ("Gateway pod in terminating state" , true ),
535+ Entry ("Gateway pod in not ready state" , false ),
536+ )
537+
538+ DescribeTable ("reconciles a pod gateway in terminating or not ready state that is one of two pods that matches two policies" , func (
539+ terminating bool ,
540+ ) {
541+ initController ([]runtime.Object {namespaceGW , namespaceTarget , namespaceTarget2 , targetPod1 , targetPod2 , pod1 , pod2 },
542+ []runtime.Object {dynamicPolicy , dynamicPolicyDiffTargetNS })
543+ namespaceGWWith2Pods := newNamespaceWithPods (namespaceGW .Name , pod1 , pod2 )
544+ expectedPolicy1 , expectedRefs1 := expectedPolicyStateAndRefs (
545+ []* namespaceWithPods {namespaceTarget2WithPod },
546+ nil ,
547+ []* namespaceWithPods {namespaceGWWith2Pods }, false )
548+
549+ expectedPolicy2 , expectedRefs2 := expectedPolicyStateAndRefs (
550+ []* namespaceWithPods {namespaceTargetWithPod },
551+ nil ,
552+ []* namespaceWithPods {namespaceGWWith2Pods }, false )
553+
554+ eventuallyExpectNumberOfPolicies (2 )
555+ eventuallyExpectConfig (dynamicPolicy .Name , expectedPolicy1 , expectedRefs1 )
556+ eventuallyExpectConfig (dynamicPolicyDiffTargetNS .Name , expectedPolicy2 , expectedRefs2 )
557+
558+ if terminating {
559+ By ("Setting deletion timestamp for the ex gw pod" )
560+ setPodDeletionTimestamp (pod1 , & metav1.Time {Time : time .Now ().Add (1000 * time .Second )}, fakeClient )
561+ } else {
562+ By ("Updating the ex gw pod status to mark it as not ready" )
563+ setPodConditionReady (pod1 , corev1 .ConditionFalse , fakeClient )
564+ }
565+
566+ namespaceGWWith1Pod := newNamespaceWithPods (namespaceGW .Name , pod2 )
567+
568+ expectedPolicy1 , expectedRefs1 = expectedPolicyStateAndRefs (
569+ []* namespaceWithPods {namespaceTarget2WithPod },
570+ nil ,
571+ []* namespaceWithPods {namespaceGWWith1Pod }, false )
572+
573+ expectedPolicy2 , expectedRefs2 = expectedPolicyStateAndRefs (
574+ []* namespaceWithPods {namespaceTargetWithPod },
575+ nil ,
576+ []* namespaceWithPods {namespaceGWWith1Pod }, false )
577+
578+ eventuallyExpectNumberOfPolicies (2 )
579+ eventuallyExpectConfig (dynamicPolicy .Name , expectedPolicy1 , expectedRefs1 )
580+ eventuallyExpectConfig (dynamicPolicyDiffTargetNS .Name , expectedPolicy2 , expectedRefs2 )
581+
582+ if terminating {
583+ By ("Removing deletion timestamp for the ex gw pod" )
584+ setPodDeletionTimestamp (pod1 , nil , fakeClient )
585+ } else {
586+ By ("Updating the ex gw pod status to mark it as ready" )
587+ setPodConditionReady (pod1 , corev1 .ConditionTrue , fakeClient )
588+ }
589+
590+ expectedPolicy1 , expectedRefs1 = expectedPolicyStateAndRefs (
591+ []* namespaceWithPods {namespaceTarget2WithPod },
592+ nil ,
593+ []* namespaceWithPods {namespaceGWWith2Pods }, false )
594+
595+ expectedPolicy2 , expectedRefs2 = expectedPolicyStateAndRefs (
596+ []* namespaceWithPods {namespaceTargetWithPod },
597+ nil ,
598+ []* namespaceWithPods {namespaceGWWith2Pods }, false )
599+
600+ eventuallyExpectNumberOfPolicies (2 )
601+ eventuallyExpectConfig (dynamicPolicy .Name , expectedPolicy1 , expectedRefs1 )
602+ eventuallyExpectConfig (dynamicPolicyDiffTargetNS .Name , expectedPolicy2 , expectedRefs2 )
603+ },
604+ Entry ("Gateway pod in terminating state" , true ),
605+ Entry ("Gateway pod in not ready state" , false ),
606+ )
607+ })
451608})
452609
453610func deletePod (pod * corev1.Pod , fakeClient * fake.Clientset ) {
@@ -478,6 +635,36 @@ func updatePodStatus(pod *corev1.Pod, podStatus corev1.PodStatus) {
478635 Expect (err ).NotTo (HaveOccurred ())
479636}
480637
638+ func setPodDeletionTimestamp (pod * corev1.Pod , deletionTimestamp * metav1.Time , fakeClient * fake.Clientset ) {
639+ p , err := fakeClient .CoreV1 ().Pods (pod .Namespace ).Get (context .TODO (), pod .Name , metav1.GetOptions {})
640+ Expect (err ).NotTo (HaveOccurred ())
641+ incrementResourceVersion (p )
642+ p .DeletionTimestamp = deletionTimestamp
643+ _ , err = fakeClient .CoreV1 ().Pods (pod .Namespace ).Update (context .Background (), p , metav1.UpdateOptions {})
644+ Expect (err ).NotTo (HaveOccurred ())
645+ }
646+
647+ func setPodConditionReady (pod * corev1.Pod , condStatus corev1.ConditionStatus , fakeClient * fake.Clientset ) {
648+ p , err := fakeClient .CoreV1 ().Pods (pod .Namespace ).Get (context .TODO (), pod .Name , metav1.GetOptions {})
649+ Expect (err ).NotTo (HaveOccurred ())
650+ incrementResourceVersion (p )
651+ if p .Status .Conditions != nil {
652+ for i := range p .Status .Conditions {
653+ if p .Status .Conditions [i ].Type == corev1 .PodReady {
654+ p .Status .Conditions [i ].Status = condStatus
655+ }
656+ }
657+ } else {
658+ notReadyCondition := corev1.PodCondition {
659+ Type : corev1 .PodReady ,
660+ Status : corev1 .ConditionFalse ,
661+ }
662+ p .Status .Conditions = []corev1.PodCondition {notReadyCondition }
663+ }
664+ _ , err = fakeClient .CoreV1 ().Pods (pod .Namespace ).Update (context .Background (), p , metav1.UpdateOptions {})
665+ Expect (err ).NotTo (HaveOccurred ())
666+ }
667+
481668func incrementResourceVersion (obj metav1.Object ) {
482669 var rs int64
483670 if obj .GetResourceVersion () != "" {
0 commit comments