88
99 "github.com/hashicorp/terraform/internal/addrs"
1010 "github.com/hashicorp/terraform/internal/configs"
11- "github.com/hashicorp/terraform/internal/dag"
1211 "github.com/hashicorp/terraform/internal/plans"
1312)
1413
@@ -21,85 +20,41 @@ type ActionDiffTransformer struct {
2120
2221func (t * ActionDiffTransformer ) Transform (g * Graph ) error {
2322 applyNodes := addrs .MakeMap [addrs.AbsResourceInstance , * NodeApplyableResourceInstance ]()
23+ actionTriggerNodes := addrs .MakeMap [addrs.ConfigResource , []* nodeActionTriggerApplyExpand ]()
2424 for _ , vs := range g .Vertices () {
25- applyableResource , ok := vs .(* NodeApplyableResourceInstance )
26- if ! ok {
27- continue
25+ if applyableResource , ok := vs .(* NodeApplyableResourceInstance ); ok {
26+ applyNodes .Put (applyableResource .Addr , applyableResource )
2827 }
2928
30- applyNodes .Put (applyableResource .Addr , applyableResource )
29+ if atn , ok := vs .(* nodeActionTriggerApplyExpand ); ok {
30+ configResource := actionTriggerNodes .Get (atn .lifecycleActionTrigger .resourceAddress )
31+ actionTriggerNodes .Put (atn .lifecycleActionTrigger .resourceAddress , append (configResource , atn ))
32+ }
3133 }
3234
33- invocationMap := map [* plans.ActionInvocationInstanceSrc ]* nodeActionTriggerApplyInstance {}
34- triggerMap := addrs .MakeMap [addrs.AbsResourceInstance , []* plans.ActionInvocationInstanceSrc ]()
35- for _ , action := range t .Changes .ActionInvocations {
36- // Add nodes for each action invocation
37- node := & nodeActionTriggerApplyInstance {
38- ActionInvocation : action ,
35+ for _ , ai := range t .Changes .ActionInvocations {
36+ lat , ok := ai .ActionTrigger .(* plans.LifecycleActionTrigger )
37+ if ! ok {
38+ continue
3939 }
40+ isBefore := lat .ActionTriggerEvent == configs .BeforeCreate || lat .ActionTriggerEvent == configs .BeforeUpdate
41+ isAfter := lat .ActionTriggerEvent == configs .AfterCreate || lat .ActionTriggerEvent == configs .AfterUpdate
4042
41- // If the action invocations is triggered within the lifecycle of a resource
42- // we want to add information about the source location to the apply node
43- if at , ok := action .ActionTrigger .(* plans.LifecycleActionTrigger ); ok {
44- moduleInstance := t .Config .DescendantForInstance (at .TriggeringResourceAddr .Module )
45- if moduleInstance == nil {
46- panic (fmt .Sprintf ("Could not find module instance for resource %s in config" , at .TriggeringResourceAddr .String ()))
47- }
48-
49- resourceInstance := moduleInstance .Module .ResourceByAddr (at .TriggeringResourceAddr .Resource .Resource )
50- if resourceInstance == nil {
51- panic (fmt .Sprintf ("Could not find resource instance for resource %s in config" , at .TriggeringResourceAddr .String ()))
52- }
53-
54- triggerBlock := resourceInstance .Managed .ActionTriggers [at .ActionTriggerBlockIndex ]
55- if triggerBlock == nil {
56- panic (fmt .Sprintf ("Could not find action trigger block %d for resource %s in config" , at .ActionTriggerBlockIndex , at .TriggeringResourceAddr .String ()))
57- }
58-
59- triggerMap .Put (at .TriggeringResourceAddr , append (triggerMap .Get (at .TriggeringResourceAddr ), action ))
60-
61- act := triggerBlock .Actions [at .ActionsListIndex ]
62- node .ActionTriggerRange = & act .Range
63- node .ConditionExpr = triggerBlock .Condition
43+ atns , ok := actionTriggerNodes .GetOk (lat .TriggeringResourceAddr .ConfigResource ())
44+ if ! ok {
45+ return fmt .Errorf ("no action trigger nodes found for resource %s" , lat .TriggeringResourceAddr )
6446 }
47+ // We add the action invocations one by one
48+ for _ , atn := range atns {
49+ beforeMatches := atn .relativeTiming == RelativeActionTimingBefore && isBefore
50+ afterMatches := atn .relativeTiming == RelativeActionTimingAfter && isAfter
6551
66- g .Add (node )
67- invocationMap [action ] = node
68-
69- // Add edge to triggering resource
70- if lat , ok := action .ActionTrigger .(* plans.LifecycleActionTrigger ); ok {
71- // Add edges for lifecycle action triggers
72- resourceNode , ok := applyNodes .GetOk (lat .TriggeringResourceAddr )
73- if ! ok {
74- panic ("Could not find resource node for lifecycle action trigger" )
52+ if (beforeMatches || afterMatches ) && atn .lifecycleActionTrigger .actionTriggerBlockIndex == lat .ActionTriggerBlockIndex && atn .lifecycleActionTrigger .actionListIndex == lat .ActionsListIndex {
53+ atn .actionInvocationInstances = append (atn .actionInvocationInstances , ai )
7554 }
7655
77- switch lat .ActionTriggerEvent {
78- case configs .BeforeCreate , configs .BeforeUpdate , configs .BeforeDestroy :
79- g .Connect (dag .BasicEdge (resourceNode , node ))
80- case configs .AfterCreate , configs .AfterUpdate , configs .AfterDestroy :
81- g .Connect (dag .BasicEdge (node , resourceNode ))
82- default :
83- panic ("Unknown event" )
84- }
8556 }
8657 }
8758
88- // Find all dependencies between action invocations
89- for _ , action := range t .Changes .ActionInvocations {
90- at , ok := action .ActionTrigger .(* plans.LifecycleActionTrigger )
91- if ! ok {
92- // only add dependencies between lifecycle actions. invoke actions
93- // all act independently.
94- continue
95- }
96-
97- node := invocationMap [action ]
98- others := action .FilterLaterActionInvocations (triggerMap .Get (at .TriggeringResourceAddr ))
99- for _ , other := range others {
100- otherNode := invocationMap [other ]
101- g .Connect (dag .BasicEdge (otherNode , node ))
102- }
103- }
10459 return nil
10560}
0 commit comments