admin管理员组

文章数量:1123801

Considering the following test playbook:

---
- name: Playbook
  hosts: localhost
  become: false
  gather_facts: false
  vars:
    modes:
      - ReadWriteOnce
  tasks:
    - name: Template output
      ansible.builtin.debug:
        msg: "{{ lookup('ansible.builtin.template', 'template.j2') }}"

And related template.js Jinja2 template:

storage:
  accessModes:
    {{ modes | to_nice_yaml | indent(4) }}
  resources:
    requests:
      storage: 5Gi

The output is:

ok: [localhost] =>
  msg: |-
    storage:
      accessModes:
        - ReadWriteOnce

      resources:
        requests:
          storage: 50Gi

My goal is to remove the empty line present after ReadWriteOnce list element, while keeping the exact yaml structure presented above. I tried setting into template the newline suppression with -, after indent(4):

storage:
  accessModes:
    {{ modes | to_nice_yaml | indent(4) -}}
  resources:
    requests:
      storage: 5Gi

Unfortunately, this produces an unexpected yaml formatting, note the resources:

ok: [localhost] =>
  msg: |-
    storage:
      accessModes:
        - ReadWriteOnce
    resources: <-- resources are shifted to left, by two spaces
        requests:
          storage: 5Gi

I'm wondering what is the correct fix for this issue? Thank you for your suggestions.

Considering the following test playbook:

---
- name: Playbook
  hosts: localhost
  become: false
  gather_facts: false
  vars:
    modes:
      - ReadWriteOnce
  tasks:
    - name: Template output
      ansible.builtin.debug:
        msg: "{{ lookup('ansible.builtin.template', 'template.j2') }}"

And related template.js Jinja2 template:

storage:
  accessModes:
    {{ modes | to_nice_yaml | indent(4) }}
  resources:
    requests:
      storage: 5Gi

The output is:

ok: [localhost] =>
  msg: |-
    storage:
      accessModes:
        - ReadWriteOnce

      resources:
        requests:
          storage: 50Gi

My goal is to remove the empty line present after ReadWriteOnce list element, while keeping the exact yaml structure presented above. I tried setting into template the newline suppression with -, after indent(4):

storage:
  accessModes:
    {{ modes | to_nice_yaml | indent(4) -}}
  resources:
    requests:
      storage: 5Gi

Unfortunately, this produces an unexpected yaml formatting, note the resources:

ok: [localhost] =>
  msg: |-
    storage:
      accessModes:
        - ReadWriteOnce
    resources: <-- resources are shifted to left, by two spaces
        requests:
          storage: 5Gi

I'm wondering what is the correct fix for this issue? Thank you for your suggestions.

Share Improve this question edited yesterday Floren asked yesterday FlorenFloren 5116 silver badges17 bronze badges 2
  • accessModes:{{ modes | to_yaml | replace('\n', '') | indent(4, False) }} – 0xn0b174 Commented yesterday
  • I know the actual yaml is valid accessModes: [ReadWriteOnce, ReadWriteOncePod], but I want to respect the OP expected output. – Floren Commented yesterday
Add a comment  | 

2 Answers 2

Reset to default 1

Use the template to create the structure only

shell> cat template.j2
storage:
  accessModes: {{ modes }}
  resources:
    requests:
      storage: 5Gi

The output of the template lookup plugin is a string. Convert it to YAML. For example,

result: "{{ lookup('template', 'template.j2') | from_yaml }}"

Then ask the filter to_nice_yaml to format the output

    - debug:
        msg: |
          {{ result | to_nice_yaml(indent=4) }}

gives

    msg: |-
        storage:
            accessModes:
            - ReadWriteOnce
            resources:
                requests:
                    storage: 5Gi

You'll have to ask the Ansible callback to write YAML. For example,

shell> ANSIBLE_CALLBACK_RESULT_FORMAT=yaml ansible-playbook pb.yml

Notes:

  • The list isn't indented inside the dictionary. See python yaml.dump bad indentation.

  • Run the play below to see the results of various options.


Example of a complete playbook for testing

shell> cat pb.yml
- hosts: localhost
  gather_facts: false

  vars:

    modes: [ReadWriteOnce]

  tasks:

    - debug:
        msg: |
          {{ result | type_debug }}

          {{ result | to_nice_yaml(indent=4) }}

          {{ result | to_nice_yaml | indent(4, true) }}

          {{ result | to_nice_yaml(indent=4) | indent(4) }}
      vars:
        result: "{{ lookup('template', 'template.j2') | from_yaml }}"
#       result: "{{ lookup('template', 'template.j2') }}"

Thanks to @vladimir-botka's hint mentioning the template lookup plugin outputs a string, I figured an easy fix:

storage:
  accessModes:
    {{ modes | to_nice_yaml | trim | indent(4) }}
  resources:
    requests:
      storage: 5Gi

The trim takes care of the problematic code output:

ok: [localhost] =>
  msg: |-
    storage:
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 50Gi

Related to indent(4) usage, I'm using it to inject the contents of a template, into another template:

alertmanager:
  config:
    {{ lookup('ansible.builtin.template', 'config_alertmanager.j2') | trim | indent(4) }}

本文标签: Incorrect Ansible Jinja2 template concatenationStack Overflow