@@ -72,15 +72,59 @@ func (r *RuleS2SReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
7272 return ctrl.Result {}, err
7373 }
7474
75+ // Add finalizer if it doesn't exist
76+ if ! controllerutil .ContainsFinalizer (ruleS2S , "netguard.sgroups.io/finalizer" ) {
77+ logger .Info ("Adding finalizer to RuleS2S" , "name" , ruleS2S .Name )
78+ controllerutil .AddFinalizer (ruleS2S , "netguard.sgroups.io/finalizer" )
79+ if err := UpdateWithRetry (ctx , r .Client , ruleS2S , DefaultMaxRetries ); err != nil {
80+ logger .Error (err , "Failed to add finalizer to RuleS2S" )
81+ return ctrl.Result {}, err
82+ }
83+ // Return to avoid processing the same object twice in one reconciliation
84+ return ctrl.Result {}, nil
85+ }
86+
7587 // Check if the resource is being deleted
7688 if ! ruleS2S .DeletionTimestamp .IsZero () {
7789 // Delete related IEAgAgRules
7890 if err := r .deleteRelatedIEAgAgRules (ctx , ruleS2S ); err != nil {
91+ // Check if this is our custom error type
92+ if failedErr , ok := err .(* FailedToDeleteRulesError ); ok {
93+ // Update status with error condition
94+ errorMsg := fmt .Sprintf ("Cannot delete RuleS2S because some IEAgAgRules could not be deleted: %s" ,
95+ strings .Join (failedErr .FailedRules , ", " ))
96+
97+ meta .SetStatusCondition (& ruleS2S .Status .Conditions , metav1.Condition {
98+ Type : netguardv1alpha1 .ConditionReady ,
99+ Status : metav1 .ConditionFalse ,
100+ Reason : "FailedToDeleteRules" ,
101+ Message : errorMsg ,
102+ })
103+
104+ if updateErr := UpdateStatusWithRetry (ctx , r .Client , ruleS2S , DefaultMaxRetries ); updateErr != nil {
105+ logger .Error (updateErr , "Failed to update RuleS2S status" )
106+ }
107+
108+ logger .Error (err , "Failed to delete all related IEAgAgRules" ,
109+ "failedRules" , strings .Join (failedErr .FailedRules , ", " ))
110+
111+ return ctrl.Result {}, nil
112+ }
113+
114+ // For other errors, log and return the error
79115 logger .Error (err , "Failed to delete related IEAgAgRules" )
80116 return ctrl.Result {}, err
81117 }
82118
83- // Resource is being deleted, no need to do anything else
119+ // All related IEAgAgRules have been deleted, now remove the finalizer
120+ logger .Info ("Removing finalizer from RuleS2S" , "name" , ruleS2S .Name )
121+ controllerutil .RemoveFinalizer (ruleS2S , "netguard.sgroups.io/finalizer" )
122+ if err := UpdateWithRetry (ctx , r .Client , ruleS2S , DefaultMaxRetries ); err != nil {
123+ logger .Error (err , "Failed to remove finalizer from RuleS2S" )
124+ return ctrl.Result {}, err
125+ }
126+
127+ // Resource is being deleted and finalizer has been removed
84128 return ctrl.Result {}, nil
85129 }
86130
@@ -854,7 +898,18 @@ func (r *RuleS2SReconciler) getExistingIEAgAgRules(ctx context.Context, ruleS2S
854898 return relatedRules , nil
855899}
856900
901+ // FailedToDeleteRulesError is a custom error type for failed rule deletions
902+ type FailedToDeleteRulesError struct {
903+ FailedRules []string
904+ }
905+
906+ // Error implements the error interface
907+ func (e * FailedToDeleteRulesError ) Error () string {
908+ return fmt .Sprintf ("failed to delete the following IEAgAgRules: %s" , strings .Join (e .FailedRules , ", " ))
909+ }
910+
857911// deleteRelatedIEAgAgRules deletes all IEAgAgRules that have an OwnerReference to the given RuleS2S
912+ // Returns a FailedToDeleteRulesError if any rules could not be deleted
858913func (r * RuleS2SReconciler ) deleteRelatedIEAgAgRules (ctx context.Context , ruleS2S * netguardv1alpha1.RuleS2S ) error {
859914 logger := log .FromContext (ctx )
860915
@@ -867,29 +922,57 @@ func (r *RuleS2SReconciler) deleteRelatedIEAgAgRules(ctx context.Context, ruleS2
867922 logger .Info ("Deleting IEAgAgRules" )
868923 logger .Info ("Deleting rule" , "ruleName" , ruleS2S .GetName (), "uuid" , ruleS2S .GetUID ())
869924 logger .Info ("ieAgAgRuleList" , "listNumber" , len (ieAgAgRuleList .Items ))
925+
926+ var failedRules []string
927+
870928 // Check each rule for an OwnerReference to this RuleS2S
871929 for _ , rule := range ieAgAgRuleList .Items {
872930 for _ , ownerRef := range rule .GetOwnerReferences () {
873- logger .Info ("Deleting rule" , "Kind" , ownerRef .Kind , "uuid" , ownerRef .UID )
931+ logger .Info ("Checking rule" , "Kind" , ownerRef .Kind , "uuid" , ownerRef .UID )
874932 if ownerRef .UID == ruleS2S .GetUID () &&
875933 ownerRef .Kind == "RuleS2S" &&
876934 ownerRef .APIVersion == netguardv1alpha1 .GroupVersion .String () {
877935
878936 // Found a rule that references this RuleS2S
879937 logger .Info ("Deleting related IEAgAgRule" , "name" , rule .Name , "namespace" , rule .Namespace )
880938
881- // Delete the rule
882- if err := r .Delete (ctx , & rule ); err != nil {
939+ // First, remove the finalizer if it exists
940+ ruleCopy := rule .DeepCopy ()
941+ if controllerutil .ContainsFinalizer (ruleCopy , "provider.sgroups.io/finalizer" ) {
942+ logger .Info ("Removing finalizer from IEAgAgRule" , "name" , ruleCopy .Name , "namespace" , ruleCopy .Namespace )
943+ controllerutil .RemoveFinalizer (ruleCopy , "provider.sgroups.io/finalizer" )
944+
945+ // Update the rule to remove the finalizer with retry
946+ if err := UpdateWithRetry (ctx , r .Client , ruleCopy , DefaultMaxRetries ); err != nil {
947+ if ! errors .IsNotFound (err ) {
948+ logger .Error (err , "Failed to remove finalizer from IEAgAgRule" ,
949+ "name" , ruleCopy .Name , "namespace" , ruleCopy .Namespace )
950+ // Continue with deletion attempt even if finalizer removal fails
951+ }
952+ }
953+ }
954+
955+ // Then delete the rule
956+ if err := r .Delete (ctx , ruleCopy ); err != nil {
883957 if ! errors .IsNotFound (err ) {
884958 logger .Error (err , "Failed to delete related IEAgAgRule" ,
885- "name" , rule .Name , "namespace" , rule .Namespace )
886- return err
959+ "name" , ruleCopy .Name , "namespace" , ruleCopy .Namespace )
960+ // Add to failed rules list instead of returning immediately
961+ failedRules = append (failedRules , fmt .Sprintf ("%s/%s" , ruleCopy .Namespace , ruleCopy .Name ))
887962 }
888963 }
889964 }
890965 }
891966 }
892967
968+ // If any rules failed to delete, return a custom error
969+ if len (failedRules ) > 0 {
970+ logger .Error (fmt .Errorf ("failed to delete some IEAgAgRules" ),
971+ "Some IEAgAgRules could not be deleted" ,
972+ "failedRules" , strings .Join (failedRules , ", " ))
973+ return & FailedToDeleteRulesError {FailedRules : failedRules }
974+ }
975+
893976 return nil
894977}
895978
0 commit comments