This repository has been archived by the owner on Jan 8, 2024. It is now read-only.
/
eval_context.go
111 lines (93 loc) · 3.41 KB
/
eval_context.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package config
import (
"github.com/hashicorp/hcl/v2"
"github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/gocty"
"github.com/hashicorp/waypoint/internal/config/variables"
"github.com/hashicorp/waypoint/pkg/config/funcs"
)
// EvalContext returns the common eval context to use for parsing all
// configurations. This should always be available for all config types.
//
// The pwd param is the directory to use as a working directory
// for determining things like relative paths. This should be considered
// the pwd over the actual process pwd.
func EvalContext(parent *hcl.EvalContext, pwd string) *hcl.EvalContext {
// NewChild works even with parent == nil so this is valid
result := parent.NewChild()
funcs.AddStandardFunctions(result, pwd)
return result
}
// appendContext makes child a child of parent and returns the new context.
// If child is nil this returns parent.
func appendContext(parent, child *hcl.EvalContext) *hcl.EvalContext {
if child == nil {
return parent
}
// We need to get the full tree of contexts since we need to go
// parent => child traversal but HCL only supports child => parent.
var tree []*hcl.EvalContext
for current := child; current != nil; current = current.Parent() {
tree = append(tree, current)
}
// Go backward through the tree (parent => child) order to ensure
// that we merge all the context trees properly.
for i := len(tree) - 1; i >= 0; i-- {
current := tree[i]
parent = parent.NewChild()
parent.Variables = current.Variables
parent.Functions = current.Functions
}
return parent
}
// defineContextVarsIfNeeded will set an empty map to ctx.Variables if needed
func defineContextVarsIfNeeded(ctx *hcl.EvalContext) {
if ctx.Variables == nil {
ctx.Variables = map[string]cty.Value{}
}
}
// addWorkspaceValue adds the workspace values to the context. This
// adds the `workspace` map and currently only supports the `workspace.name`
// value.
func addWorkspaceValue(ctx *hcl.EvalContext, v string) {
addMapVariable(ctx, "workspace", map[string]string{
"name": v,
})
}
// addPathValue adds the "path" variable to the context.
func addPathValue(ctx *hcl.EvalContext, v map[string]string) {
addMapVariable(ctx, "path", v)
}
// addMapVariable adds a map[string]string to the context
func addMapVariable(ctx *hcl.EvalContext, varName string, v map[string]string) {
value, err := gocty.ToCtyValue(v, cty.Map(cty.String))
if err != nil {
// map[string]string conversion should never fail
panic(err)
}
addCtyVariable(ctx, varName, value)
}
// addCtyVariable adds a cty variable to the context
func addCtyVariable(ctx *hcl.EvalContext, varName string, value cty.Value) {
defineContextVarsIfNeeded(ctx)
ctx.Variables[varName] = value
}
// finalizeContext should be called whenever an HCL context is being used
// as the final call.
func finalizeContext(ctx *hcl.EvalContext) *hcl.EvalContext {
ctx = ctx.NewChild()
ctx.Functions = funcs.MakeTemplateFuncs(ctx)
return ctx
}
// AddVariables uses the final map of InputValues to add all input variables
// to the given hcl EvalContext.
func AddVariables(ctx *hcl.EvalContext, vs variables.Values) *hcl.EvalContext {
variables.AddInputVariables(ctx, vs)
return ctx
}
// hclContextContainer is an interface that config structs that have an HCL
// context may implement. We use this for certain things such as mapoperation()
// to set the proper context.
type hclContextContainer interface {
hclContext() *hcl.EvalContext
}