levant icon indicating copy to clipboard operation
levant copied to clipboard

Problems with nested YAML

Open pop opened this issue 3 years ago • 3 comments

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 {}

pop avatar Sep 22 '21 17:09 pop

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.

pop avatar Sep 22 '21 17:09 pop

I'm having the same problem.

alistairking avatar Nov 23 '21 20:11 alistairking

2022 and i'm still having this problem

JamesAwesome avatar Dec 22 '22 00:12 JamesAwesome