]>
Commit | Line | Data |
---|---|---|
15c0b25d AP |
1 | package terraform |
2 | ||
3 | import ( | |
4 | "fmt" | |
5 | ||
107c1cdb ND |
6 | "github.com/hashicorp/hcl2/hcl" |
7 | "github.com/zclconf/go-cty/cty" | |
8 | ||
9 | "github.com/hashicorp/terraform/addrs" | |
10 | "github.com/hashicorp/terraform/lang" | |
11 | "github.com/hashicorp/terraform/tfdiags" | |
15c0b25d AP |
12 | ) |
13 | ||
14 | // EvalLocal is an EvalNode implementation that evaluates the | |
15 | // expression for a local value and writes it into a transient part of | |
16 | // the state. | |
17 | type EvalLocal struct { | |
107c1cdb ND |
18 | Addr addrs.LocalValue |
19 | Expr hcl.Expression | |
15c0b25d AP |
20 | } |
21 | ||
22 | func (n *EvalLocal) Eval(ctx EvalContext) (interface{}, error) { | |
107c1cdb ND |
23 | var diags tfdiags.Diagnostics |
24 | ||
25 | // We ignore diags here because any problems we might find will be found | |
26 | // again in EvaluateExpr below. | |
27 | refs, _ := lang.ReferencesInExpr(n.Expr) | |
28 | for _, ref := range refs { | |
29 | if ref.Subject == n.Addr { | |
30 | diags = diags.Append(&hcl.Diagnostic{ | |
31 | Severity: hcl.DiagError, | |
32 | Summary: "Self-referencing local value", | |
33 | Detail: fmt.Sprintf("Local value %s cannot use its own result as part of its expression.", n.Addr), | |
34 | Subject: ref.SourceRange.ToHCL().Ptr(), | |
35 | Context: n.Expr.Range().Ptr(), | |
36 | }) | |
37 | } | |
15c0b25d | 38 | } |
107c1cdb ND |
39 | if diags.HasErrors() { |
40 | return nil, diags.Err() | |
15c0b25d AP |
41 | } |
42 | ||
107c1cdb ND |
43 | val, moreDiags := ctx.EvaluateExpr(n.Expr, cty.DynamicPseudoType, nil) |
44 | diags = diags.Append(moreDiags) | |
45 | if moreDiags.HasErrors() { | |
46 | return nil, diags.Err() | |
15c0b25d AP |
47 | } |
48 | ||
107c1cdb ND |
49 | state := ctx.State() |
50 | if state == nil { | |
51 | return nil, fmt.Errorf("cannot write local value to nil state") | |
15c0b25d AP |
52 | } |
53 | ||
107c1cdb | 54 | state.SetLocalValue(n.Addr.Absolute(ctx.Path()), val) |
15c0b25d AP |
55 | |
56 | return nil, nil | |
57 | } | |
58 | ||
59 | // EvalDeleteLocal is an EvalNode implementation that deletes a Local value | |
60 | // from the state. Locals aren't persisted, but we don't need to evaluate them | |
61 | // during destroy. | |
62 | type EvalDeleteLocal struct { | |
107c1cdb | 63 | Addr addrs.LocalValue |
15c0b25d AP |
64 | } |
65 | ||
66 | func (n *EvalDeleteLocal) Eval(ctx EvalContext) (interface{}, error) { | |
107c1cdb | 67 | state := ctx.State() |
15c0b25d AP |
68 | if state == nil { |
69 | return nil, nil | |
70 | } | |
71 | ||
107c1cdb | 72 | state.RemoveLocalValue(n.Addr.Absolute(ctx.Path())) |
15c0b25d AP |
73 | return nil, nil |
74 | } |