6 "github.com/hashicorp/terraform/plans"
7 "github.com/hashicorp/terraform/providers"
8 "github.com/hashicorp/terraform/states"
10 "github.com/hashicorp/terraform/addrs"
11 "github.com/zclconf/go-cty/cty"
14 // NodePlannableResourceInstance represents a _single_ resource
15 // instance that is plannable. This means this represents a single
16 // count index, for example.
17 type NodePlannableResourceInstance struct {
18 *NodeAbstractResourceInstance
19 ForceCreateBeforeDestroy bool
23 _ GraphNodeSubPath = (*NodePlannableResourceInstance)(nil)
24 _ GraphNodeReferenceable = (*NodePlannableResourceInstance)(nil)
25 _ GraphNodeReferencer = (*NodePlannableResourceInstance)(nil)
26 _ GraphNodeResource = (*NodePlannableResourceInstance)(nil)
27 _ GraphNodeResourceInstance = (*NodePlannableResourceInstance)(nil)
28 _ GraphNodeAttachResourceConfig = (*NodePlannableResourceInstance)(nil)
29 _ GraphNodeAttachResourceState = (*NodePlannableResourceInstance)(nil)
30 _ GraphNodeEvalable = (*NodePlannableResourceInstance)(nil)
34 func (n *NodePlannableResourceInstance) EvalTree() EvalNode {
35 addr := n.ResourceInstanceAddr()
37 // State still uses legacy-style internal ids, so we need to shim to get
38 // a suitable key to use.
39 stateId := NewLegacyResourceInstanceAddress(addr).stateId()
41 // Determine the dependencies for the state.
42 stateDeps := n.StateReferences()
44 // Eval info is different depending on what kind of resource this is
45 switch addr.Resource.Resource.Mode {
46 case addrs.ManagedResourceMode:
47 return n.evalTreeManagedResource(addr, stateId, stateDeps)
48 case addrs.DataResourceMode:
49 return n.evalTreeDataResource(addr, stateId, stateDeps)
51 panic(fmt.Errorf("unsupported resource mode %s", n.Config.Mode))
55 func (n *NodePlannableResourceInstance) evalTreeDataResource(addr addrs.AbsResourceInstance, stateId string, stateDeps []addrs.Referenceable) EvalNode {
57 var provider providers.Interface
58 var providerSchema *ProviderSchema
59 var change *plans.ResourceInstanceChange
60 var state *states.ResourceInstanceObject
61 var configVal cty.Value
66 Addr: n.ResolvedProvider,
68 Schema: &providerSchema,
74 ProviderSchema: &providerSchema,
79 // If we already have a non-planned state then we already dealt
80 // with this during the refresh walk and so we have nothing to do
83 If: func(ctx EvalContext) (bool, error) {
86 // Check and see if any of our dependencies have changes.
87 changes := ctx.Changes()
88 for _, d := range n.StateReferences() {
89 ri, ok := d.(addrs.ResourceInstance)
93 change := changes.GetResourceInstanceChange(ri.Absolute(ctx.Path()), states.CurrentGen)
94 if change != nil && change.Action != plans.NoOp {
100 refreshed := state != nil && state.Status != states.ObjectPlanned
102 // If there are no dependency changes, and it's not a forced
103 // read because we there was no Refresh, then we don't need
104 // to re-read. If any dependencies have changes, it means
105 // our config may also have changes and we need to Read the
106 // data source again.
107 if !depChanges && refreshed {
108 return false, EvalEarlyExitError{}
115 &EvalValidateSelfRef{
117 Config: config.Config,
118 ProviderSchema: &providerSchema,
124 Dependencies: n.StateReferences(),
126 ProviderAddr: n.ResolvedProvider,
127 ProviderSchema: &providerSchema,
128 ForcePlanRead: true, // _always_ produce a Read change, even if the config seems ready
129 OutputChange: &change,
130 OutputValue: &configVal,
136 ProviderAddr: n.ResolvedProvider,
137 ProviderSchema: &providerSchema,
143 ProviderSchema: &providerSchema,
150 func (n *NodePlannableResourceInstance) evalTreeManagedResource(addr addrs.AbsResourceInstance, stateId string, stateDeps []addrs.Referenceable) EvalNode {
152 var provider providers.Interface
153 var providerSchema *ProviderSchema
154 var change *plans.ResourceInstanceChange
155 var state *states.ResourceInstanceObject
157 return &EvalSequence{
160 Addr: n.ResolvedProvider,
162 Schema: &providerSchema,
168 ProviderSchema: &providerSchema,
173 &EvalValidateSelfRef{
175 Config: config.Config,
176 ProviderSchema: &providerSchema,
182 CreateBeforeDestroy: n.ForceCreateBeforeDestroy,
184 ProviderAddr: n.ResolvedProvider,
185 ProviderSchema: &providerSchema,
187 OutputChange: &change,
190 &EvalCheckPreventDestroy{
197 ProviderAddr: n.ResolvedProvider,
199 ProviderSchema: &providerSchema,
203 ProviderSchema: &providerSchema,