@@ -658,6 +658,45 @@ func (d *Deferred) ReportActionInvocationDeferred(ai plans.ActionInvocationInsta
658658 })
659659}
660660
661+ // ShouldDeferActionInvocation returns true if there is a reason to defer the action invocation instance
662+ // We want to defer an action invocation if
663+ // a) the resource was deferred
664+ // or
665+ // b) a previously run action was deferred
666+ func (d * Deferred ) ShouldDeferActionInvocation (ai plans.ActionInvocationInstance ) bool {
667+ d .mu .Lock ()
668+ defer d .mu .Unlock ()
669+
670+ // We only want to defer actions that are lifecycle triggered
671+ at , ok := ai .ActionTrigger .(plans.LifecycleActionTrigger )
672+ if ! ok {
673+ return false
674+ }
675+
676+ // If the resource was deferred, we also need to defer any action potentially triggering from this
677+ if configResourceMap , ok := d .resourceInstancesDeferred .GetOk (at .TriggeringResourceAddr .ConfigResource ()); ok {
678+ if configResourceMap .Has (at .TriggeringResourceAddr ) {
679+ return true
680+ }
681+ }
682+
683+ // Since all actions plan in order we can just check if an action for this resource instance
684+ // has been deferred already
685+ for _ , deferred := range d .actionInvocationDeferred {
686+ deferredAt , deferredOk := deferred .ActionInvocationInstance .ActionTrigger .(plans.LifecycleActionTrigger )
687+ if ! deferredOk {
688+ continue // We only care about lifecycle triggered actions here
689+ }
690+
691+ if deferredAt .TriggeringResourceAddr .Equal (at .TriggeringResourceAddr ) {
692+ return true
693+ }
694+ }
695+
696+ // We found no reason, so we return false
697+ return false
698+ }
699+
661700// UnexpectedProviderDeferralDiagnostic is a diagnostic that indicates that a
662701// provider was deferred although deferrals were not allowed.
663702func UnexpectedProviderDeferralDiagnostic (addrs fmt.Stringer ) tfdiags.Diagnostic {
0 commit comments