github.com/r3labs/terraform@v0.8.4/terraform/node_resource_plan.go (about) 1 package terraform 2 3 import ( 4 "github.com/hashicorp/terraform/dag" 5 ) 6 7 // NodePlannableResource represents a resource that is "plannable": 8 // it is ready to be planned in order to create a diff. 9 type NodePlannableResource struct { 10 *NodeAbstractResource 11 12 // Set by GraphNodeTargetable and used during DynamicExpand to 13 // forward targets downwards. 14 targets []ResourceAddress 15 } 16 17 // GraphNodeTargetable 18 func (n *NodePlannableResource) SetTargets(targets []ResourceAddress) { 19 n.targets = targets 20 } 21 22 // GraphNodeEvalable 23 func (n *NodePlannableResource) EvalTree() EvalNode { 24 return &EvalSequence{ 25 Nodes: []EvalNode{ 26 // The EvalTree for a plannable resource primarily involves 27 // interpolating the count since it can contain variables 28 // we only just received access to. 29 // 30 // With the interpolated count, we can then DynamicExpand 31 // into the proper number of instances. 32 &EvalInterpolate{Config: n.Config.RawCount}, 33 34 &EvalCountCheckComputed{Resource: n.Config}, 35 &EvalCountFixZeroOneBoundary{Resource: n.Config}, 36 }, 37 } 38 } 39 40 // GraphNodeDynamicExpandable 41 func (n *NodePlannableResource) DynamicExpand(ctx EvalContext) (*Graph, error) { 42 // Grab the state which we read 43 state, lock := ctx.State() 44 lock.RLock() 45 defer lock.RUnlock() 46 47 // Expand the resource count which must be available by now from EvalTree 48 count, err := n.Config.Count() 49 if err != nil { 50 return nil, err 51 } 52 53 // The concrete resource factory we'll use 54 concreteResource := func(a *NodeAbstractResource) dag.Vertex { 55 // Add the config and state since we don't do that via transforms 56 a.Config = n.Config 57 58 return &NodePlannableResourceInstance{ 59 NodeAbstractResource: a, 60 } 61 } 62 63 // The concrete resource factory we'll use for oprhans 64 concreteResourceOrphan := func(a *NodeAbstractResource) dag.Vertex { 65 // Add the config and state since we don't do that via transforms 66 a.Config = n.Config 67 68 return &NodePlannableResourceOrphan{ 69 NodeAbstractResource: a, 70 } 71 } 72 73 // Start creating the steps 74 steps := []GraphTransformer{ 75 // Expand the count. 76 &ResourceCountTransformer{ 77 Concrete: concreteResource, 78 Count: count, 79 Addr: n.ResourceAddr(), 80 }, 81 82 // Add the count orphans 83 &OrphanResourceCountTransformer{ 84 Concrete: concreteResourceOrphan, 85 Count: count, 86 Addr: n.ResourceAddr(), 87 State: state, 88 }, 89 90 // Attach the state 91 &AttachStateTransformer{State: state}, 92 93 // Targeting 94 &TargetsTransformer{ParsedTargets: n.targets}, 95 96 // Connect references so ordering is correct 97 &ReferenceTransformer{}, 98 99 // Make sure there is a single root 100 &RootTransformer{}, 101 } 102 103 // Build the graph 104 b := &BasicGraphBuilder{ 105 Steps: steps, 106 Validate: true, 107 Name: "NodePlannableResource", 108 } 109 return b.Build(ctx.Path()) 110 }