diff --git a/jobspec2/parse_test.go b/jobspec2/parse_test.go index 986be77fb..409001b34 100644 --- a/jobspec2/parse_test.go +++ b/jobspec2/parse_test.go @@ -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 { diff --git a/jobspec2/types.config.go b/jobspec2/types.config.go index 0c25d9f2f..12bb58f34 100644 --- a/jobspec2/types.config.go +++ b/jobspec2/types.config.go @@ -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 }, }