github.com/wikibal01/hashicorp-terraform@v0.11.12-beta1/terraform/node_resource_plan_instance.go (about) 1 package terraform 2 3 import ( 4 "fmt" 5 6 "github.com/hashicorp/terraform/config" 7 ) 8 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 { 13 *NodeAbstractResource 14 } 15 16 // GraphNodeEvalable 17 func (n *NodePlannableResourceInstance) EvalTree() EvalNode { 18 addr := n.NodeAbstractResource.Addr 19 20 // stateId is the ID to put into the state 21 stateId := addr.stateId() 22 23 // Build the instance info. More of this will be populated during eval 24 info := &InstanceInfo{ 25 Id: stateId, 26 Type: addr.Type, 27 ModulePath: normalizeModulePath(addr.Path), 28 } 29 30 // Build the resource for eval 31 resource := &Resource{ 32 Name: addr.Name, 33 Type: addr.Type, 34 CountIndex: addr.Index, 35 } 36 if resource.CountIndex < 0 { 37 resource.CountIndex = 0 38 } 39 40 // Determine the dependencies for the state. 41 stateDeps := n.StateReferences() 42 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, 48 ) 49 case config.DataResourceMode: 50 return n.evalTreeDataResource( 51 stateId, info, resource, stateDeps) 52 default: 53 panic(fmt.Errorf("unsupported resource mode %s", n.Config.Mode)) 54 } 55 } 56 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 64 65 return &EvalSequence{ 66 Nodes: []EvalNode{ 67 &EvalReadState{ 68 Name: stateId, 69 Output: &state, 70 }, 71 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. 76 &EvalInterpolate{ 77 Config: n.Config.RawConfig.Copy(), 78 Resource: resource, 79 Output: &config, 80 }, 81 82 &EvalIf{ 83 If: func(ctx EvalContext) (bool, error) { 84 computed := config.ComputedKeys != nil && len(config.ComputedKeys) > 0 85 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{} 92 } 93 94 return true, nil 95 }, 96 Then: EvalNoop{}, 97 }, 98 99 &EvalGetProvider{ 100 Name: n.ResolvedProvider, 101 Output: &provider, 102 }, 103 104 &EvalReadDataDiff{ 105 Info: info, 106 Config: &config, 107 Provider: &provider, 108 Output: &diff, 109 OutputState: &state, 110 }, 111 112 &EvalWriteState{ 113 Name: stateId, 114 ResourceType: n.Config.Type, 115 Provider: n.ResolvedProvider, 116 Dependencies: stateDeps, 117 State: &state, 118 }, 119 120 &EvalWriteDiff{ 121 Name: stateId, 122 Diff: &diff, 123 }, 124 }, 125 } 126 } 127 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 137 138 return &EvalSequence{ 139 Nodes: []EvalNode{ 140 &EvalInterpolate{ 141 Config: n.Config.RawConfig.Copy(), 142 Resource: resource, 143 Output: &resourceConfig, 144 }, 145 &EvalGetProvider{ 146 Name: n.ResolvedProvider, 147 Output: &provider, 148 }, 149 // Re-run validation to catch any errors we missed, e.g. type 150 // mismatches on computed values. 151 &EvalValidateResource{ 152 Provider: &provider, 153 Config: &resourceConfig, 154 ResourceName: n.Config.Name, 155 ResourceType: n.Config.Type, 156 ResourceMode: n.Config.Mode, 157 IgnoreWarnings: true, 158 }, 159 &EvalReadState{ 160 Name: stateId, 161 Output: &state, 162 }, 163 &EvalDiff{ 164 Name: stateId, 165 Info: info, 166 Config: &resourceConfig, 167 Resource: n.Config, 168 Provider: &provider, 169 State: &state, 170 OutputDiff: &diff, 171 OutputState: &state, 172 }, 173 &EvalCheckPreventDestroy{ 174 Resource: n.Config, 175 Diff: &diff, 176 }, 177 &EvalWriteState{ 178 Name: stateId, 179 ResourceType: n.Config.Type, 180 Provider: n.ResolvedProvider, 181 Dependencies: stateDeps, 182 State: &state, 183 }, 184 &EvalWriteDiff{ 185 Name: stateId, 186 Diff: &diff, 187 }, 188 }, 189 } 190 }