This fixes a regression in #10326, to handle unquoted unknown variables.
The HCL job may contain unquoted undefined variable references without ${...} wrapping, e.g. value = meta.node_class. In 1.0.4, this got parsed as value = "${meta.node_class}".
This code performs a scan to find the relevant ${ and }, and only tries to find the closest ones with whitespace as the only separator.
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.
Variables that are unset return the correct diagnostic but throw a panic when
we later parse the job body. Return early if there are any variable parsing
errors instead of continuing in a potentially invalid state.
Allow expressing `meta` and `env` blocks as map attributes as well.
`env` and `meta` should support arbitrary key and values, yet hcl2
restricts the keys to valid identifiers. For example, block attribute
identifiers may not contain dots, `.`, which frequently used in meta
fields, and sometimes in environment variable fields.
This change attempts to parse `env`/`meta` both as an attribute and as a
block.
This additionally allows better expressivity for env/meta blocks, using
functions. For example, one can reuse a set of environment variables for
multiple tasks, using a local common_envs value:
```hcl
env = merge(local.common_envs, {"more_env_key", "..."})
```
The HCL2 parser needs to apply special parsing tweaks so it can parse
the task config the same way as HCL1. Particularly, it needs to
reinterprets `map[string]interface{}` fields and blocks that appear when
attributes are expected.
This commit restricts the special casing to the Job fields, and ignore
`variables` and `locals` block.