sclevine / yj

CLI - Convert between YAML, TOML, JSON, and HCL. Preserves map order.
Apache License 2.0
949 stars 50 forks source link

Converting from yaml to hcl to yaml is losing an array. #23

Closed clushie closed 9 months ago

clushie commented 2 years ago

Hi! I'm running into an issue where converting from YAML to HCL is kind of destructive, with json the issue doesn't show up.

yaml='
route:
  receiver: webhook
  group_by:
    - alertname
    - datacenter
    - app
receivers:
  - name: webhook
    webhook_configs:
      - url: http://localhost:500
      - url: http://localhost:500'

echo -e '-----\nYAML\n-----'
echo "${yaml}"
echo -e '-----\nYAML to YAML\n-----'
echo "${yaml}" | yj yy
echo -e '-----\nYAML to JSON\n-----'
echo "${yaml}" | yj yj
echo -e '-----\nYAML to HCL\n-----'
echo "${yaml}" | yj yc
echo -e '-----\nYAML to HCL to YAML\n-----'
echo "${yaml}" | yj yc | yj yy
echo -e '-----\nYAML to HCL to YAML to HCL\n-----'
echo "${yaml}" | yj yc | yj yy | yj yc

echo -e '-----\nYAML o HCL to YAML vs YAML\n-----'
diff <(echo "${yaml}" | yj yc | yj yy) <(echo "${yaml}" | yj yy)

Results in this output:

-----
YAML
-----
route:
  receiver: webhook
  group_by:
    - alertname
    - datacenter
    - app
receivers:
  - name: webhook
    webhook_configs:
      - url: http://localhost:500
      - url: http://localhost:500
-----
YAML to YAML
-----
route:
  receiver: webhook
  group_by:
    - alertname
    - datacenter
    - app
receivers:
  - name: webhook
    webhook_configs:
      - url: http://localhost:500
      - url: http://localhost:500
-----
YAML to JSON
-----
{"route":{"receiver":"webhook","group_by":["alertname","datacenter","app"]},"receivers":[{"name":"webhook","webhook_configs":[{"url":"http://localhost:500"},{"url":"http://localhost:500"}]}]}
-----
YAML to HCL
-----
"route" = {
  "receiver" = "webhook"

  "group_by" = ["alertname", "datacenter", "app"]
}

"receivers" = {
  "name" = "webhook"

  "webhook_configs" = {
    "url" = "http://localhost:500"
  }

  "webhook_configs" = {
    "url" = "http://localhost:500"
  }
}-----
YAML to HCL to YAML
-----
route
-----
YAML to HCL to YAML to HCL
-----
Error writing HCL: Expected object, got unknown token: 1:1 STRING "route"
-----
YAML o HCL to YAML vs YAML
-----
1c1,11
< route
---
> route:
>   receiver: webhook
>   group_by:
>     - alertname
>     - datacenter
>     - app
> receivers:
>   - name: webhook
>     webhook_configs:
>       - url: http://localhost:500
>       - url: http://localhost:500
sclevine commented 2 years ago

I think there's a bug in your script: yj yc | yj yy outputs HCL and tries to parse it as YAML.

There is a small difference if you convert from YAML to HCL and back to YAML:

route:
  receiver: webhook
  group_by:
    - alertname
    - datacenter
    - app
receivers:
  - name: webhook
    webhook_configs:
      - url: http://localhost:500
      - url: http://localhost:500
route: # route is now an array
  - receiver: webhook 
    group_by:
      - alertname
      - datacenter
      - app
receivers:
  - name: webhook
    webhook_configs:
      - url: http://localhost:500
      - url: http://localhost:500

But this is expected, as HCL's object syntax is also used to express an array of objects.

norpol commented 2 years ago

(private account as I'm on vacation): Ah totally right, I mixed things up when I created the final script in a hurry. You definitively posted the right output though.

Is there a way to avoid the conversion from dict to an array?

I'm trying to pass yaml/json inside terraform and try to avoid having to do in-line json/yaml.

Also do you think its worth mentioning this behavior somewhere in the readme?