hcl2: Use the actual string snippet as it appears from undefined
With the updated undefined variable code, we attempt to pick the text of `${....}` verbatim from the hcl body. Previously, we'd attempt to regenerate the string from the AST and pray it matches input; the generation is lossy, as the same AST can represent multiple variations (e.g. `${v.0}` and `${v[0]}` have the same HCLv2 AST). In this change, we attempt to go back to the hcl2 source and find the string snippet corresponding to the variable reference.
This commit is contained in:
parent
6de35bd1b7
commit
04bfeacc5b
|
@ -855,6 +855,7 @@ func TestParse_UndefinedVariables(t *testing.T) {
|
|||
"foo-${attr.network.dev-us-east1-relay-vpc.external-ip.0}",
|
||||
`${env["BLAH"]}`,
|
||||
`${mixed-indexing.0[3]["FOO"].5}`,
|
||||
`with spaces ${ root. field[ "FOO"].5 }`,
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package jobspec2
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
|
@ -308,8 +309,26 @@ func (c *jobConfig) EvalContext() *hcl.EvalContext {
|
|||
inputVariablesAccessor: cty.ObjectVal(vars),
|
||||
localsAccessor: cty.ObjectVal(locals),
|
||||
},
|
||||
UnknownVariable: func(expr string) (cty.Value, error) {
|
||||
v := "${" + expr + "}"
|
||||
UndefinedVariable: func(t hcl.Traversal) (cty.Value, hcl.Diagnostics) {
|
||||
body := c.ParseConfig.Body
|
||||
start := t.SourceRange().Start.Byte
|
||||
end := t.SourceRange().End.Byte
|
||||
|
||||
v := string(body[start:end])
|
||||
if i := bytes.IndexByte(body[end:], '}'); i != -1 {
|
||||
v += string(body[end : end+i+1])
|
||||
} else {
|
||||
// fallback for unexpected cases
|
||||
v += "}"
|
||||
}
|
||||
|
||||
if i := bytes.LastIndex(body[:start], []byte("${")); i != 0 {
|
||||
v = string(body[i:start]) + v
|
||||
} else {
|
||||
// fallback for unexpected cases
|
||||
v = "${" + v
|
||||
}
|
||||
|
||||
return cty.StringVal(v), nil
|
||||
},
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue