github.com/muratcelep/terraform@v1.1.0-beta2-not-internal-4/not-internal/terraform/node_local.go (about) 1 package terraform 2 3 import ( 4 "fmt" 5 "log" 6 7 "github.com/hashicorp/hcl/v2" 8 "github.com/muratcelep/terraform/not-internal/addrs" 9 "github.com/muratcelep/terraform/not-internal/configs" 10 "github.com/muratcelep/terraform/not-internal/dag" 11 "github.com/muratcelep/terraform/not-internal/lang" 12 "github.com/muratcelep/terraform/not-internal/tfdiags" 13 "github.com/zclconf/go-cty/cty" 14 ) 15 16 // nodeExpandLocal represents a named local value in a configuration module, 17 // which has not yet been expanded. 18 type nodeExpandLocal struct { 19 Addr addrs.LocalValue 20 Module addrs.Module 21 Config *configs.Local 22 } 23 24 var ( 25 _ GraphNodeReferenceable = (*nodeExpandLocal)(nil) 26 _ GraphNodeReferencer = (*nodeExpandLocal)(nil) 27 _ GraphNodeDynamicExpandable = (*nodeExpandLocal)(nil) 28 _ graphNodeTemporaryValue = (*nodeExpandLocal)(nil) 29 _ graphNodeExpandsInstances = (*nodeExpandLocal)(nil) 30 ) 31 32 func (n *nodeExpandLocal) expandsInstances() {} 33 34 // graphNodeTemporaryValue 35 func (n *nodeExpandLocal) temporaryValue() bool { 36 return true 37 } 38 39 func (n *nodeExpandLocal) Name() string { 40 path := n.Module.String() 41 addr := n.Addr.String() + " (expand)" 42 43 if path != "" { 44 return path + "." + addr 45 } 46 return addr 47 } 48 49 // GraphNodeModulePath 50 func (n *nodeExpandLocal) ModulePath() addrs.Module { 51 return n.Module 52 } 53 54 // GraphNodeReferenceable 55 func (n *nodeExpandLocal) ReferenceableAddrs() []addrs.Referenceable { 56 return []addrs.Referenceable{n.Addr} 57 } 58 59 // GraphNodeReferencer 60 func (n *nodeExpandLocal) References() []*addrs.Reference { 61 refs, _ := lang.ReferencesInExpr(n.Config.Expr) 62 return refs 63 } 64 65 func (n *nodeExpandLocal) DynamicExpand(ctx EvalContext) (*Graph, error) { 66 var g Graph 67 expander := ctx.InstanceExpander() 68 for _, module := range expander.ExpandModule(n.Module) { 69 o := &NodeLocal{ 70 Addr: n.Addr.Absolute(module), 71 Config: n.Config, 72 } 73 log.Printf("[TRACE] Expanding local: adding %s as %T", o.Addr.String(), o) 74 g.Add(o) 75 } 76 return &g, nil 77 } 78 79 // NodeLocal represents a named local value in a particular module. 80 // 81 // Local value nodes only have one operation, common to all walk types: 82 // evaluate the result and place it in state. 83 type NodeLocal struct { 84 Addr addrs.AbsLocalValue 85 Config *configs.Local 86 } 87 88 var ( 89 _ GraphNodeModuleInstance = (*NodeLocal)(nil) 90 _ GraphNodeReferenceable = (*NodeLocal)(nil) 91 _ GraphNodeReferencer = (*NodeLocal)(nil) 92 _ GraphNodeExecutable = (*NodeLocal)(nil) 93 _ graphNodeTemporaryValue = (*NodeLocal)(nil) 94 _ dag.GraphNodeDotter = (*NodeLocal)(nil) 95 ) 96 97 // graphNodeTemporaryValue 98 func (n *NodeLocal) temporaryValue() bool { 99 return true 100 } 101 102 func (n *NodeLocal) Name() string { 103 return n.Addr.String() 104 } 105 106 // GraphNodeModuleInstance 107 func (n *NodeLocal) Path() addrs.ModuleInstance { 108 return n.Addr.Module 109 } 110 111 // GraphNodeModulePath 112 func (n *NodeLocal) ModulePath() addrs.Module { 113 return n.Addr.Module.Module() 114 } 115 116 // GraphNodeReferenceable 117 func (n *NodeLocal) ReferenceableAddrs() []addrs.Referenceable { 118 return []addrs.Referenceable{n.Addr.LocalValue} 119 } 120 121 // GraphNodeReferencer 122 func (n *NodeLocal) References() []*addrs.Reference { 123 refs, _ := lang.ReferencesInExpr(n.Config.Expr) 124 return refs 125 } 126 127 // GraphNodeExecutable 128 // NodeLocal.Execute is an Execute implementation that evaluates the 129 // expression for a local value and writes it into a transient part of 130 // the state. 131 func (n *NodeLocal) Execute(ctx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) { 132 expr := n.Config.Expr 133 addr := n.Addr.LocalValue 134 135 // We ignore diags here because any problems we might find will be found 136 // again in EvaluateExpr below. 137 refs, _ := lang.ReferencesInExpr(expr) 138 for _, ref := range refs { 139 if ref.Subject == addr { 140 diags = diags.Append(&hcl.Diagnostic{ 141 Severity: hcl.DiagError, 142 Summary: "Self-referencing local value", 143 Detail: fmt.Sprintf("Local value %s cannot use its own result as part of its expression.", addr), 144 Subject: ref.SourceRange.ToHCL().Ptr(), 145 Context: expr.Range().Ptr(), 146 }) 147 } 148 } 149 if diags.HasErrors() { 150 return diags 151 } 152 153 val, moreDiags := ctx.EvaluateExpr(expr, cty.DynamicPseudoType, nil) 154 diags = diags.Append(moreDiags) 155 if moreDiags.HasErrors() { 156 return diags 157 } 158 159 state := ctx.State() 160 if state == nil { 161 diags = diags.Append(fmt.Errorf("cannot write local value to nil state")) 162 return diags 163 } 164 165 state.SetLocalValue(addr.Absolute(ctx.Path()), val) 166 167 return diags 168 } 169 170 // dag.GraphNodeDotter impl. 171 func (n *NodeLocal) DotNode(name string, opts *dag.DotOpts) *dag.DotNode { 172 return &dag.DotNode{ 173 Name: name, 174 Attrs: map[string]string{ 175 "label": n.Name(), 176 "shape": "note", 177 }, 178 } 179 }