clj-yaml

mmer 2023-04-19T09:00:08.220239Z

@mmer has joined the channel

mmer 2023-04-19T09:03:49.509719Z

Hi I was recently working with some yaml files that were actually ansible playbooks. I noticed the following - with a map entry {:name "sh {{ var}} {{ var1}}"} When out put the is :

- name: sh {{ var}} {{ var1}} 
I was hoping it would have been output as :
-name:  "sh {{ var}} {{ var1}}"
Any thoughts?

mmer 2023-04-21T08:17:02.827109Z

@lee thank you for your digging. The reason I went with flow style block is that was the way that the playbooks I was manipulating were laid out and so I was trying to preserve that. I think you are right that the stack overflow seems to hint that it might be OK. What I have done is a simple text replace when this occurs, just to keep the source and the target in a similar format. Previously I have written loads of XSLT and writing code in yaml to me has the same pitfalls as writing code in XML - would be easier just to use EDN. Thanks again

lread 2023-04-21T12:57:34.595819Z

Cool, glad it is all good @mmer. I find YAML downright confusing. Please don't be shy to drop by with other clj-yaml mysteries and we'll try to help.

lread 2023-04-19T13:30:23.621989Z

Hi @mmer, I don't (yet) understand from your question what your actual problematic input YAML is nor exactly what you are trying to do with it. It feels like you are wanting to parse YAML and then output YAML? I'll play in a REPL session in my editor against clj-commons/clj-yaml 1.0.26

(require '[clj-yaml.core :as yaml])

;; Let's start with parsing... this all seems fine to me, but probably does not match your case?
(yaml/parse-string "name: 'sh {{ var}} {{ var1}}'")
;; => {:name "sh {{ var}} {{ var1}}"}

(yaml/parse-string "name: \"sh {{ var}} {{ var1}}\"")
;; => {:name "sh {{ var}} {{ var1}}"}

(yaml/parse-string "name: sh {{ var}} {{ var1}}")
;; => {:name "sh {{ var}} {{ var1}}"}

;; Let's try parsing then generating, this seems fine too
(-> "name: sh {{ var}} {{ var1}}"
    yaml/parse-string
    yaml/generate-string)
;; => "{name: 'sh {{ var}} {{ var1}}'}\n"
I'm obviously missing some detail. Happy to try to help if you can provide a minimal reproducible example that illustrates the problem.

lread 2023-04-19T13:30:41.358459Z

Ah... maybe... the confusion is around this? One thing to note about YAML is that quotes on strings are optional when the sequence of characters can only be a string. These two YAML snippets are interpreted the same:

name: sh {{ var}} {{ var1}}
name: 'sh {{ var}} {{ var1}}'
Is that the confusion?

mmer 2023-04-19T13:36:49.962989Z

Thanks @lee the issue is that Ansible does not treat them as the same. Ansible requires sections with variable substitutions to be surrounded by double quotes. Yet again another reason to hate yaml! What I am trying to do is modify a pre-existing Ansible file. SO I am using Specter to find the part I want to change and then rewriting the file and I have the weirdness:

- name: "sh {{ var}} {{ var1}}"
becomes
- name: sh {{ var}} {{ var1}}
but
- name: "{{ var1}}"
Is output the same as the input. Just an annoying quirk.

lread 2023-04-19T13:48:31.578369Z

Yeah, YAML can cause bags under the eyes, hair loss, and in some cases, gnashing of teeth at the moon. Are you using v1.0.26? Here's what I'm getting for your sample YAML:

(-> "- name: \"sh {{ var}} {{ var1}}\""
    yaml/parse-string
    yaml/generate-string)
;; => "- {name: 'sh {{ var}} {{ var1}}'}\n"
Note that if we use an unambiguous string the output will leave out the quotes:
(-> "- name: \"bingo\"" 
    yaml/parse-string
    yaml/generate-string)
;; => "- {name: bingo}\n"

lread 2023-04-19T13:57:39.667299Z

It just occurred to me you might be using clj-yaml from babashka, I just reran my above snippets under bb v1.3.176 and got the same results.

mmer 2023-04-19T16:21:07.865899Z

I am using it in bb. So is this an issue with bb?

lread 2023-04-19T16:56:49.003019Z

I don't think so, no: > I just reran my above snippets under bb v1.3.176 and got the same results. Are you using the same version of bb as me? bb --version

mmer 2023-04-19T16:57:40.293149Z

I am using the same one - I am running on wsl in windows.

lread 2023-04-19T16:59:50.833289Z

So from the examples I provided above, I cannot reproduce your issue. If you provide me with small reproducible examples that I can run, we can maybe figure out what is not working for you and why.

mmer 2023-04-20T14:41:55.281229Z

He are some sample files - example-orig.yml is the input and example-out.yml is the output. I have cheated as I have converted single quotes to double quotes as a step after generating the yamml string.

mmer 2023-04-20T14:42:18.858929Z

Note the line with command on it. It should be quoted.

lread 2023-04-20T14:53:36.973229Z

@mmer I would need the exact minimal code you are running so I can do exactly what you are doing.

mmer 2023-04-20T14:58:57.472399Z

Here is the code and a new output file it generates. As I said ansible files are sensitive to quotes.

lread 2023-04-20T19:21:29.973159Z

Good stuff @mmer, I can now experience what you are experiencing. It seems to be related to :flow-style :block , if I remove that, I see the quotes in the output:

- name: Inventory
  hosts: localhost
  gather_facts: false
  tasks:
  - {name: Get password, command: 'sh {{ pnf_secret }} {{ er_host_primary }}', delegate_to: '{{ pam_ip }}', register: response}
  - name: Report PROPERTIES
    debug: {msg: 'pnf_passwd: {{ response.stdout_lines[0] }}'}
But I expect this is not the format you'd like.

lread 2023-04-20T19:51:36.749649Z

This kind of feels like a bug in snakeyaml, I'm not sure why it would print the command: string without quotes when the flow style is block.

lread 2023-04-20T20:02:55.059199Z

But the YAML syntax rules are extremely complex. If a string can be unambiguously interpreted as a string the quotes can be omitted. I really don't know why the YAML spec designers went for ambiguity as a feature. It makes things difficult.

lread 2023-04-20T20:58:38.365659Z

Ah, this https://stackoverflow.com/a/66705463 seems to be close to what maybe we are experiencing.

lread 2023-04-20T21:04:55.666189Z

Are you absolutely sure you actually have a problem here @mmer? I just glanced at the ansible docs. The docs https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_variables.html#when-to-quote-variables-a-yaml-gotcha, but I think they are just talking about ambiguous YAML strings that need to be quoted. If the string is unambiguously a string, won't it be interpreted as a string by the YAML parser that ansible uses?