@@ -208,11 +208,18 @@ func (r *AppWrapperReconciler) Reconcile(ctx context.Context, req ctrl.Request)
208208
209209 // Handle Success
210210 if podStatus .succeeded >= podStatus .expected && (podStatus .pending + podStatus .running + podStatus .failed == 0 ) {
211+ msg := fmt .Sprintf ("%v pods succeeded and no running, pending, or failed pods" , podStatus .succeeded )
211212 meta .SetStatusCondition (& aw .Status .Conditions , metav1.Condition {
212213 Type : string (workloadv1beta2 .QuotaReserved ),
213214 Status : metav1 .ConditionFalse ,
214215 Reason : string (workloadv1beta2 .AppWrapperSucceeded ),
215- Message : fmt .Sprintf ("%v pods succeeded and no running, pending, or failed pods" , podStatus .succeeded ),
216+ Message : msg ,
217+ })
218+ meta .SetStatusCondition (& aw .Status .Conditions , metav1.Condition {
219+ Type : string (workloadv1beta2 .ResourcesDeployed ),
220+ Status : metav1 .ConditionTrue ,
221+ Reason : string (workloadv1beta2 .AppWrapperSucceeded ),
222+ Message : msg ,
216223 })
217224 return r .updateStatus (ctx , aw , workloadv1beta2 .AppWrapperSucceeded )
218225 }
@@ -370,6 +377,29 @@ func (r *AppWrapperReconciler) Reconcile(ctx context.Context, req ctrl.Request)
370377 Message : "No resources deployed" ,
371378 })
372379 return ctrl.Result {}, r .Status ().Update (ctx , aw )
380+
381+ case workloadv1beta2 .AppWrapperSucceeded :
382+ if meta .IsStatusConditionTrue (aw .Status .Conditions , string (workloadv1beta2 .ResourcesDeployed )) {
383+ deletionDelay := r .timeToLiveAfterSucceededDuration (ctx , aw )
384+ whenSucceeded := meta .FindStatusCondition (aw .Status .Conditions , string (workloadv1beta2 .ResourcesDeployed )).LastTransitionTime
385+ now := time .Now ()
386+ deadline := whenSucceeded .Add (deletionDelay )
387+ if now .Before (deadline ) {
388+ return ctrl.Result {RequeueAfter : deadline .Sub (now )}, r .Status ().Update (ctx , aw )
389+ }
390+
391+ if ! r .deleteComponents (ctx , aw ) {
392+ return ctrl.Result {RequeueAfter : 5 * time .Second }, nil
393+ }
394+ meta .SetStatusCondition (& aw .Status .Conditions , metav1.Condition {
395+ Type : string (workloadv1beta2 .ResourcesDeployed ),
396+ Status : metav1 .ConditionFalse ,
397+ Reason : string (workloadv1beta2 .AppWrapperSucceeded ),
398+ Message : fmt .Sprintf ("Time to live after success of %v expired" , deletionDelay ),
399+ })
400+ return ctrl.Result {}, r .Status ().Update (ctx , aw )
401+ }
402+ return ctrl.Result {}, nil
373403 }
374404
375405 return ctrl.Result {}, nil
@@ -495,6 +525,19 @@ func (r *AppWrapperReconciler) debuggingFailureDeletionDelay(ctx context.Context
495525 return 0 * time .Second
496526}
497527
528+ func (r * AppWrapperReconciler ) timeToLiveAfterSucceededDuration (ctx context.Context , aw * workloadv1beta2.AppWrapper ) time.Duration {
529+ if userPeriod , ok := aw .Annotations [workloadv1beta2 .SuccessTTLDurationAnnotation ]; ok {
530+ if duration , err := time .ParseDuration (userPeriod ); err == nil {
531+ if duration > 0 && duration < r .Config .FaultTolerance .SuccessTTLCeiling {
532+ return duration
533+ }
534+ } else {
535+ log .FromContext (ctx ).Info ("Malformed successTTL annotation" , "annotation" , userPeriod , "error" , err )
536+ }
537+ }
538+ return r .Config .FaultTolerance .SuccessTTLCeiling
539+ }
540+
498541func clearCondition (aw * workloadv1beta2.AppWrapper , condition workloadv1beta2.AppWrapperCondition , reason string , message string ) {
499542 if meta .IsStatusConditionTrue (aw .Status .Conditions , string (condition )) {
500543 meta .SetStatusCondition (& aw .Status .Conditions , metav1.Condition {
0 commit comments