Fork me on GitHub
#clj-yaml
<
2023-04-19
>
mmer09:04:49

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?

lread13:04:23

Hi @U4C3ZU6KX, 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.

lread13:04:41

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?

mmer13:04:49

Thanks @UE21H2HHD 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.

lread13:04:31

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"

lread13:04:39

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.

mmer16:04:07

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

lread16:04:49

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

mmer16:04:40

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

lread16:04:50

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.

mmer14:04:55

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.

mmer14:04:18

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

lread14:04:36

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

mmer14:04:57

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

lread19:04:29

Good stuff @U4C3ZU6KX, 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.

lread19:04:36

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.

lread20:04:55

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.

lread20:04:38

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

lread21:04:55

Are you absolutely sure you actually have a problem here @U4C3ZU6KX? 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?

mmer08:04:02

@UE21H2HHD 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

lread12:04:34

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