levant
levant copied to clipboard
Problems with nested YAML
Description
Levant does not handle nested YAML well.
Given equivalent variables files in YAML and a JSON, Levant will successfully render with the JSON variables but fail to render with the JSON variables.
Relevant Nomad job specification file
Template file:
[[ range $serviceName := keys $.services ]]
[[ with $service := get $.services $serviceName ]]
[[ $serviceName ]] health endpoint is [[ $service.health ]]
[[ end ]]
[[ end ]]
variables.json
:
{
"services": {
"api": {
"health": "/v1/health"
},
"backend": {
"health": "/health"
}
}
}
variables.yaml
:
services:
api:
health: /v1/health
backend:
health: /health
Output of levant version
:
0.3.0
Output of consul version
:
N/A
Output of nomad version
:
N/A
Additional environment details:
I have a fork that very haphazardly resolves the issue. If this is a feature Levant would like to support I can clean up that fork and submit a pull request.
Debug log outputs from Levant:
Rendering w/ JSON variables is fine:
$ levant render -log-level=debug -var-file=variables.json template.hcl
2021-09-22T10:37:31-07:00 |DEBU| template/render: variable file extension .json detected
2021-09-22T10:37:31-07:00 |DEBU| template/render: no command line variables passed
2021-09-22T10:37:31-07:00 |DEBU| template/funcs: renaming "env" function to "levantEnv"
2021-09-22T10:37:31-07:00 |DEBU| template/funcs: renaming "add" function to "levantAdd"
2021-09-22T10:37:31-07:00 |DEBU| template/funcs: renaming "replace" function to "levantReplace"
2021-09-22T10:37:31-07:00 |INFO| helper/variable: using variable with key services and value map[api:map[health:/v1/health] backend:map[health:/health]] from file
api health endpoint is /v1/health
backend health endpoint is /health
Rendering w/ YAML variables fails:
$ levant render -log-level=debug -var-file=variables.yaml template.hcl
2021-09-22T10:37:05-07:00 |DEBU| template/render: variable file extension .yaml detected
2021-09-22T10:37:05-07:00 |DEBU| template/render: no command line variables passed
2021-09-22T10:37:05-07:00 |DEBU| template/funcs: renaming "env" function to "levantEnv"
2021-09-22T10:37:05-07:00 |DEBU| template/funcs: renaming "replace" function to "levantReplace"
2021-09-22T10:37:05-07:00 |DEBU| template/funcs: renaming "add" function to "levantAdd"
2021-09-22T10:37:05-07:00 |INFO| helper/variable: using variable with key services and value map[api:map[health:/v1/health] backend:map[health:/health]] from file
[ERROR] levant/command: template: jobTemplate:1:31: executing "jobTemplate" at <$.services>: wrong type for value; expected map[string]interface {}; got map[interface {}]interface {}
One workaround I've tried is using yq to convert my YAML vars into JSON vars before passing them to Levant. This works, but I expected Levant to support this out of the box.
I'm having the same problem.
2022 and i'm still having this problem