@@ -179,42 +179,67 @@ func (r *AppWrapperReconciler) createComponent(ctx context.Context, aw *workload
179
179
180
180
func (r * AppWrapperReconciler ) createComponents (ctx context.Context , aw * workloadv1beta2.AppWrapper ) (error , bool ) {
181
181
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
+ })
185
195
}
186
196
}
187
197
return nil , false
188
198
}
189
199
190
200
func (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
+
191
227
meta .SetStatusCondition (& aw .Status .Conditions , metav1.Condition {
192
228
Type : string (workloadv1beta2 .DeletingResources ),
193
229
Status : metav1 .ConditionTrue ,
194
230
Reason : "DeletionInitiated" ,
195
231
})
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
211
236
}
212
237
213
238
deletionGracePeriod := r .forcefulDeletionGraceDuration (ctx , aw )
214
239
whenInitiated := meta .FindStatusCondition (aw .Status .Conditions , string (workloadv1beta2 .DeletingResources )).LastTransitionTime
215
240
gracePeriodExpired := time .Now ().After (whenInitiated .Time .Add (deletionGracePeriod ))
216
241
217
- if remaining > 0 && ! gracePeriodExpired {
242
+ if componentsRemaining && ! gracePeriodExpired {
218
243
// Resources left and deadline hasn't expired, just requeue the deletion
219
244
return false
220
245
}
@@ -224,10 +249,10 @@ func (r *AppWrapperReconciler) deleteComponents(ctx context.Context, aw *workloa
224
249
client .UnsafeDisableDeepCopy ,
225
250
client .InNamespace (aw .Namespace ),
226
251
client.MatchingLabels {AppWrapperLabel : aw .Name }); err != nil {
227
- log .Error (err , "Pod list error" )
252
+ log .FromContext ( ctx ). Error (err , "Pod list error" )
228
253
}
229
254
230
- if remaining == 0 && len (pods .Items ) == 0 {
255
+ if ! componentsRemaining && len (pods .Items ) == 0 {
231
256
// no resources or pods left; deletion is complete
232
257
clearCondition (aw , workloadv1beta2 .DeletingResources , "DeletionComplete" , "" )
233
258
return true
@@ -238,20 +263,13 @@ func (r *AppWrapperReconciler) deleteComponents(ctx context.Context, aw *workloa
238
263
// force deletion of pods first
239
264
for _ , pod := range pods .Items {
240
265
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" )
242
267
}
243
268
}
244
269
} else {
245
270
// 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 ))
255
273
}
256
274
}
257
275
}
0 commit comments