@@ -179,42 +179,67 @@ func (r *AppWrapperReconciler) createComponent(ctx context.Context, aw *workload
179179
180180func (r * AppWrapperReconciler ) createComponents (ctx context.Context , aw * workloadv1beta2.AppWrapper ) (error , bool ) {
181181 for componentIdx := range aw .Spec .Components {
182- _ , err , fatal := r .createComponent (ctx , aw , componentIdx )
183- if err != nil {
184- return err , fatal
182+ if ! meta .IsStatusConditionTrue (aw .Status .ComponentStatus [componentIdx ].Conditions , string (workloadv1beta2 .ResourcesDeployed )) {
183+ obj , err , fatal := r .createComponent (ctx , aw , componentIdx )
184+ if err != nil {
185+ return err , fatal
186+ }
187+ aw .Status .ComponentStatus [componentIdx ].Name = obj .GetName ()
188+ aw .Status .ComponentStatus [componentIdx ].Kind = obj .GetKind ()
189+ aw .Status .ComponentStatus [componentIdx ].APIVersion = obj .GetAPIVersion ()
190+ meta .SetStatusCondition (& aw .Status .ComponentStatus [componentIdx ].Conditions , metav1.Condition {
191+ Type : string (workloadv1beta2 .ResourcesDeployed ),
192+ Status : metav1 .ConditionTrue ,
193+ Reason : "CompononetCreated" ,
194+ })
185195 }
186196 }
187197 return nil , false
188198}
189199
190200func (r * AppWrapperReconciler ) deleteComponents (ctx context.Context , aw * workloadv1beta2.AppWrapper ) bool {
201+ deleteIfPresent := func (idx int , opts ... client.DeleteOption ) bool {
202+ cs := & aw .Status .ComponentStatus [idx ]
203+ if ! meta .IsStatusConditionTrue (cs .Conditions , string (workloadv1beta2 .ResourcesDeployed )) {
204+ return false // not present
205+ }
206+ obj := & metav1.PartialObjectMetadata {
207+ TypeMeta : metav1.TypeMeta {Kind : cs .Kind , APIVersion : cs .APIVersion },
208+ ObjectMeta : metav1.ObjectMeta {Name : cs .Name , Namespace : aw .Namespace },
209+ }
210+ if err := r .Delete (ctx , obj , opts ... ); err != nil {
211+ if apierrors .IsNotFound (err ) {
212+ // Has already been undeployed; update componentStatus and return not present
213+ meta .SetStatusCondition (& cs .Conditions , metav1.Condition {
214+ Type : string (workloadv1beta2 .ResourcesDeployed ),
215+ Status : metav1 .ConditionFalse ,
216+ Reason : "CompononetDeleted" ,
217+ })
218+ return false
219+ } else {
220+ log .FromContext (ctx ).Error (err , "Deletion error" )
221+ return true // unexpected error ==> still present
222+ }
223+ }
224+ return true // still present
225+ }
226+
191227 meta .SetStatusCondition (& aw .Status .Conditions , metav1.Condition {
192228 Type : string (workloadv1beta2 .DeletingResources ),
193229 Status : metav1 .ConditionTrue ,
194230 Reason : "DeletionInitiated" ,
195231 })
196- log := log .FromContext (ctx )
197- remaining := 0
198- for _ , component := range aw .Spec .Components {
199- obj , err := parseComponent (aw , component .Template .Raw )
200- if err != nil {
201- log .Error (err , "Parsing error" )
202- continue
203- }
204- if err := r .Delete (ctx , obj , client .PropagationPolicy (metav1 .DeletePropagationBackground )); err != nil {
205- if ! apierrors .IsNotFound (err ) {
206- log .Error (err , "Deletion error" )
207- }
208- continue
209- }
210- remaining ++ // no error deleting resource, resource therefore still exists
232+
233+ componentsRemaining := false
234+ for componentIdx := range aw .Spec .Components {
235+ componentsRemaining = deleteIfPresent (componentIdx , client .PropagationPolicy (metav1 .DeletePropagationBackground )) || componentsRemaining
211236 }
212237
213238 deletionGracePeriod := r .forcefulDeletionGraceDuration (ctx , aw )
214239 whenInitiated := meta .FindStatusCondition (aw .Status .Conditions , string (workloadv1beta2 .DeletingResources )).LastTransitionTime
215240 gracePeriodExpired := time .Now ().After (whenInitiated .Time .Add (deletionGracePeriod ))
216241
217- if remaining > 0 && ! gracePeriodExpired {
242+ if componentsRemaining && ! gracePeriodExpired {
218243 // Resources left and deadline hasn't expired, just requeue the deletion
219244 return false
220245 }
@@ -224,10 +249,10 @@ func (r *AppWrapperReconciler) deleteComponents(ctx context.Context, aw *workloa
224249 client .UnsafeDisableDeepCopy ,
225250 client .InNamespace (aw .Namespace ),
226251 client.MatchingLabels {AppWrapperLabel : aw .Name }); err != nil {
227- log .Error (err , "Pod list error" )
252+ log .FromContext ( ctx ). Error (err , "Pod list error" )
228253 }
229254
230- if remaining == 0 && len (pods .Items ) == 0 {
255+ if ! componentsRemaining && len (pods .Items ) == 0 {
231256 // no resources or pods left; deletion is complete
232257 clearCondition (aw , workloadv1beta2 .DeletingResources , "DeletionComplete" , "" )
233258 return true
@@ -238,20 +263,13 @@ func (r *AppWrapperReconciler) deleteComponents(ctx context.Context, aw *workloa
238263 // force deletion of pods first
239264 for _ , pod := range pods .Items {
240265 if err := r .Delete (ctx , & pod , client .GracePeriodSeconds (0 )); err != nil {
241- log .Error (err , "Forceful pod deletion error" )
266+ log .FromContext ( ctx ). Error (err , "Forceful pod deletion error" )
242267 }
243268 }
244269 } else {
245270 // force deletion of wrapped resources once pods are gone
246- for _ , component := range aw .Spec .Components {
247- obj , err := parseComponent (aw , component .Template .Raw )
248- if err != nil {
249- log .Error (err , "Parsing error" )
250- continue
251- }
252- if err := r .Delete (ctx , obj , client .GracePeriodSeconds (0 )); err != nil && ! apierrors .IsNotFound (err ) {
253- log .Error (err , "Forceful deletion error" )
254- }
271+ for componentIdx := range aw .Spec .Components {
272+ _ = deleteIfPresent (componentIdx , client .GracePeriodSeconds (0 ))
255273 }
256274 }
257275 }
0 commit comments