fix-actions-not-respecting-resource-dependencies
Daniel Schmidt 2 months ago
parent ab4ae3d9c1
commit 8e004867db
No known key found for this signature in database
GPG Key ID: 377C3A4D62FBBBE2

@ -2857,6 +2857,30 @@ func TestContextApply_actions_resource_action_ordering(t *testing.T) {
"InvokeAction action_example - cty.ObjectVal(map[string]cty.Value{\"attr\":cty.StringVal(\"hello\")})",
},
},
"resource dependencies in before_create action": {
module: map[string]string{
"main.tf": `
action "action_example" "hello" {}
resource "test_object" "dep" {
name = "dep"
}
resource "test_object" "a" {
depends_on = [test_object.dep]
name = "a"
lifecycle {
action_trigger {
events = [before_create]
actions = [action.action_example.hello]
}
}
}`,
},
expectedOrder: []string{
"ApplyResourceChangeFn test_object - cty.ObjectVal(map[string]cty.Value{\"name\":cty.StringVal(\"dep\")})",
"InvokeAction action_example - cty.NilVal",
"ApplyResourceChangeFn test_object - cty.ObjectVal(map[string]cty.Value{\"name\":cty.StringVal(\"a\")})",
},
},
} {
t.Run(name, func(t *testing.T) {
m := testModuleInline(t, tc.module)

@ -167,11 +167,12 @@ func (b *ApplyGraphBuilder) Steps() []GraphTransformer {
Operation: b.Operation,
ActionTargets: b.ActionTargets,
ConcreteActionTriggerNodeFunc: func(node *nodeAbstractActionTriggerExpand, timing RelativeActionTiming) dag.Vertex {
ConcreteActionTriggerNodeFunc: func(node *nodeAbstractActionTriggerExpand, timing RelativeActionTiming, refs []*addrs.Reference) dag.Vertex {
return &nodeActionTriggerApplyExpand{
nodeAbstractActionTriggerExpand: node,
relativeTiming: timing,
relativeTiming: timing,
inheritedReferences: refs,
}
},
},

@ -178,7 +178,7 @@ func (b *PlanGraphBuilder) Steps() []GraphTransformer {
ActionTargets: b.ActionTargets,
queryPlanMode: b.queryPlan,
ConcreteActionTriggerNodeFunc: func(node *nodeAbstractActionTriggerExpand, _ RelativeActionTiming) dag.Vertex {
ConcreteActionTriggerNodeFunc: func(node *nodeAbstractActionTriggerExpand, _ RelativeActionTiming, _ []*addrs.Reference) dag.Vertex {
return &nodeActionTriggerPlanExpand{
nodeAbstractActionTriggerExpand: node,
}

@ -23,7 +23,7 @@ const (
// ConcreteActionTriggerNodeFunc is a callback type used to convert an
// abstract action trigger to a concrete one of some type.
type ConcreteActionTriggerNodeFunc func(*nodeAbstractActionTriggerExpand, RelativeActionTiming) dag.Vertex
type ConcreteActionTriggerNodeFunc func(*nodeAbstractActionTriggerExpand, RelativeActionTiming, []*addrs.Reference) dag.Vertex
type nodeAbstractActionTriggerExpand struct {
Addr addrs.ConfigAction

@ -18,6 +18,7 @@ type nodeActionTriggerApplyExpand struct {
actionInvocationInstances []*plans.ActionInvocationInstanceSrc
relativeTiming RelativeActionTiming
inheritedReferences []*addrs.Reference
}
var (
@ -74,6 +75,7 @@ func (n *nodeActionTriggerApplyExpand) References() []*addrs.Reference {
refs = append(refs, &addrs.Reference{
Subject: n.Addr.Action,
})
refs = append(refs, n.inheritedReferences...)
if n.lifecycleActionTrigger != nil {
conditionRefs, _ := langrefs.ReferencesInExpr(addrs.ParseRef, n.lifecycleActionTrigger.conditionExpr)

@ -28,6 +28,10 @@ type GraphNodeConfigResource interface {
ResourceAddr() addrs.ConfigResource
}
type GraphNodeDependsOn interface {
DependsOn() []*addrs.Reference
}
// ConcreteResourceInstanceNodeFunc is a callback type used to convert an
// abstract resource instance to a concrete one of some type.
type ConcreteResourceInstanceNodeFunc func(*NodeAbstractResourceInstance) dag.Vertex
@ -109,6 +113,7 @@ var (
_ graphNodeAttachDataResourceDependsOn = (*NodeAbstractResource)(nil)
_ dag.GraphNodeDotter = (*NodeAbstractResource)(nil)
_ GraphNodeDestroyerCBD = (*NodeAbstractResource)(nil)
_ GraphNodeDependsOn = (*NodeAbstractResource)(nil)
)
// NewNodeAbstractResource creates an abstract resource graph node for

@ -4,6 +4,9 @@
package terraform
import (
"fmt"
"runtime/debug"
"github.com/hashicorp/terraform/internal/addrs"
"github.com/hashicorp/terraform/internal/dag"
"github.com/hashicorp/terraform/internal/tfdiags"
@ -30,6 +33,11 @@ var (
func (n *nodeExpandApplyableResource) References() []*addrs.Reference {
refs := n.NodeAbstractResource.References()
fmt.Printf("ExpandApplyableResource %s references: %v\n", n.Name(), refs)
fmt.Println("===== refs ======")
debug.PrintStack()
fmt.Println("===== refs (END) ======")
return refs
// The expand node needs to connect to the individual resource instances it
// references, but cannot refer to it's own instances without causing
@ -39,7 +47,8 @@ func (n *nodeExpandApplyableResource) References() []*addrs.Reference {
// filter them out for all resource node types, because the only method we
// have for catching certain invalid configurations are the cycles that
// result from these inter-instance references.
return filterSelfRefs(n.Addr.Resource, refs)
// return filterSelfRefs(n.Addr.Resource, refs)
return refs
}
func (n *nodeExpandApplyableResource) Name() string {

@ -141,10 +141,25 @@ func (t *ActionTriggerConfigTransformer) transformSingle(g *Graph, config *confi
},
}
// Before_* actions during apply need to be aware of any dependent references to resources
additionalReferences := []*addrs.Reference{}
if t.Operation == walkApply {
for _, rn := range resourceNode {
if gr, ok := rn.(*nodeExpandApplyableResource); ok {
fmt.Printf("\n\n Resource Node --> %#v\n", gr.Addr.String())
asd := gr.References()
fmt.Printf("\n\t asd --> %#v\n", asd)
additionalReferences = append(additionalReferences, asd...)
}
}
}
fmt.Printf("\n\n additionalReferences --> %#v\n", additionalReferences)
// If CreateNodesAsAfter is set we want all nodes to run after the resource
// If not we want expansion nodes only to exist if they are being used
if !createNodesAsAfter && containsBeforeEvent {
nat := t.ConcreteActionTriggerNodeFunc(abstract, RelativeActionTimingBefore)
nat := t.ConcreteActionTriggerNodeFunc(abstract, RelativeActionTimingBefore, additionalReferences)
g.Add(nat)
// We want to run before the resource nodes
@ -165,7 +180,7 @@ func (t *ActionTriggerConfigTransformer) transformSingle(g *Graph, config *confi
}
if createNodesAsAfter || containsAfterEvent {
nat := t.ConcreteActionTriggerNodeFunc(abstract, RelativeActionTimingAfter)
nat := t.ConcreteActionTriggerNodeFunc(abstract, RelativeActionTimingAfter, additionalReferences)
g.Add(nat)
// We want to run after the resource nodes

@ -144,6 +144,8 @@ func filterSelfRefs(self addrs.Resource, refs []*addrs.Reference) []*addrs.Refer
for i := 0; i < len(refs); i++ {
ref := refs[i]
fmt.Printf("\n\t ref --> %#v\n", ref)
var subject addrs.Resource
switch subj := ref.Subject.(type) {
case addrs.Resource:
@ -151,10 +153,12 @@ func filterSelfRefs(self addrs.Resource, refs []*addrs.Reference) []*addrs.Refer
case addrs.ResourceInstance:
subject = subj.ContainingResource()
default:
fmt.Println("continueing...")
continue
}
if self.Equal(subject) {
fmt.Println("eqlau")
tail := len(refs) - 1
refs[i], refs[tail] = refs[tail], refs[i]

Loading…
Cancel
Save