6 "github.com/hashicorp/terraform/config"
9 // NodePlannableResourceInstance represents a _single_ resource
10 // instance that is plannable. This means this represents a single
11 // count index, for example.
12 type NodePlannableResourceInstance struct {
17 func (n *NodePlannableResourceInstance) EvalTree() EvalNode {
18 addr := n.NodeAbstractResource.Addr
20 // stateId is the ID to put into the state
21 stateId := addr.stateId()
23 // Build the instance info. More of this will be populated during eval
24 info := &InstanceInfo{
27 ModulePath: normalizeModulePath(addr.Path),
30 // Build the resource for eval
31 resource := &Resource{
34 CountIndex: addr.Index,
36 if resource.CountIndex < 0 {
37 resource.CountIndex = 0
40 // Determine the dependencies for the state.
41 stateDeps := n.StateReferences()
43 // Eval info is different depending on what kind of resource this is
44 switch n.Config.Mode {
45 case config.ManagedResourceMode:
46 return n.evalTreeManagedResource(
47 stateId, info, resource, stateDeps,
49 case config.DataResourceMode:
50 return n.evalTreeDataResource(
51 stateId, info, resource, stateDeps)
53 panic(fmt.Errorf("unsupported resource mode %s", n.Config.Mode))
57 func (n *NodePlannableResourceInstance) evalTreeDataResource(
58 stateId string, info *InstanceInfo,
59 resource *Resource, stateDeps []string) EvalNode {
60 var provider ResourceProvider
61 var config *ResourceConfig
62 var diff *InstanceDiff
63 var state *InstanceState
72 // We need to re-interpolate the config here because some
73 // of the attributes may have become computed during
74 // earlier planning, due to other resources having
75 // "requires new resource" diffs.
77 Config: n.Config.RawConfig.Copy(),
83 If: func(ctx EvalContext) (bool, error) {
84 computed := config.ComputedKeys != nil && len(config.ComputedKeys) > 0
86 // If the configuration is complete and we
87 // already have a state then we don't need to
88 // do any further work during apply, because we
89 // already populated the state during refresh.
90 if !computed && state != nil {
91 return true, EvalEarlyExitError{}
100 Name: n.ProvidedBy()[0],
114 ResourceType: n.Config.Type,
115 Provider: n.Config.Provider,
116 Dependencies: stateDeps,
128 func (n *NodePlannableResourceInstance) evalTreeManagedResource(
129 stateId string, info *InstanceInfo,
130 resource *Resource, stateDeps []string) EvalNode {
131 // Declare a bunch of variables that are used for state during
132 // evaluation. Most of this are written to by-address below.
133 var provider ResourceProvider
134 var diff *InstanceDiff
135 var state *InstanceState
136 var resourceConfig *ResourceConfig
138 return &EvalSequence{
141 Config: n.Config.RawConfig.Copy(),
143 Output: &resourceConfig,
146 Name: n.ProvidedBy()[0],
149 // Re-run validation to catch any errors we missed, e.g. type
150 // mismatches on computed values.
151 &EvalValidateResource{
153 Config: &resourceConfig,
154 ResourceName: n.Config.Name,
155 ResourceType: n.Config.Type,
156 ResourceMode: n.Config.Mode,
157 IgnoreWarnings: true,
166 Config: &resourceConfig,
173 &EvalCheckPreventDestroy{
179 ResourceType: n.Config.Type,
180 Provider: n.Config.Provider,
181 Dependencies: stateDeps,