Ansible with yaml synthaxe

Hi,
i am trying to get something as:

network:
  version: 2
  ethernets:
    eth0:
      dhcp4: no
      dhcp6: no
      addresses: [x.x.x.1/24]
      routes:
        - to: 10.1.1.0/24
          via: x.x.x.254
        - to: 10.1.2.0/24
          via: x.x.x.254

Here is my code:

    - name: network | ubuntu | configure | update {{ etc_netplan_adm }} file
      ansible.builtin.copy:
        dest: "{{ etc_netplan_adm }}"
        content: |
          {{ ansible_managed_message }}
          network:
            version: 2
            ethernets:
              {{ iface_adm }}:
                dhcp4: no
                dhcp6: no
                addresses: [{{ addr_adm[0].address }}/{{ addr_adm[0].cidr }}]
                routes:
                  {% for route in adm_default_routes | flatten | map('string') | list %}
                  - to: {{ route }}
                    via: {{ addr_adm[0].gateway }}
                {% endfor %}

But with this code, i get something that is not matching to yaml format:

network:
  version: 2
  ethernets:
    ens32:
      dhcp4: no
      dhcp6: no
      addresses: [x.x.x.232/24]
      routes:
              - to: 10.1.1.0/24
          via: x.x.x.254
              - to: 10.1.2.0/24
          via: x.x.x.254

So it fails when running ‘netplan apply’.

Any help would be appreciated.

Sorry, not fully understanding … is it just the indentation of the - to: lines that is not matching to yaml format?

    - name: network | ubuntu | configure | update {{ etc_netplan_adm }} file
      ansible.builtin.copy:
        dest: "{{ etc_netplan_adm }}"
        content: |
          {{ ansible_managed_message }}
          network:
            version: 2
            ethernets:
              {{ iface_adm }}:
                dhcp4: no
                dhcp6: no
                addresses: [{{ addr_adm[0].address }}/{{ addr_adm[0].cidr }}]
                routes:
          {% for route in adm_default_routes | flatten | map('string') | list %}
                  - to: {{ route }}
                    via: {{ addr_adm[0].gateway }}
          {% endfor %}

I was able to get this to work doing by adjusting the spacing. It looks awful, but it seems to produce the correct results.

---
- name: Write File
  hosts: localhost
  connection: local
  gather_facts: false

  tasks:
    - name: "network | ubuntu | configure | update {{ etc_netplan_adm }} file"
      ansible.builtin.copy:
        dest: "{{ etc_netplan_adm }}"
        content: |
          {{ ansible_managed_message }}
          network:
            version: 2
            ethernets:
              {{ iface_adm }}:
                dhcp4: no
                dhcp6: no
                addresses: [{{ addr_adm[0].address }}/{{ addr_adm[0].cidr }}]
                routes:
                {% for route in adm_default_routes | flatten | map('string') | list %}
            - to: {{ route }}
                    via: {{ addr_adm[0].gateway }}
                {% endfor %}
      vars:
        iface_adm: eth0
        addr_adm:
          - address: 10.1.1.1
            cidr: 24
            gateway: x.x.x.254
        adm_default_routes:
          - 10.1.1.0/24
          - 10.1.2.0/24
          - 10.1.3.0/24
        etc_netplan_adm: ./netplan.yml
        ansible_managed_message: "## Block Managed via Ansbile"

I was also able to get this to work using ansible.builtin.template

templates/netplan.yml.j2

{{ ansible_managed_message }}
network:
  version: 2
  ethernets:
    {{ iface_adm }}:
      dhcp4: no
      dhcp6: no
      addresses: [{{ addr_adm[0].address }}/{{ addr_adm[0].cidr }}]
      routes:
      {% for route in adm_default_routes | flatten | map('string') | list %}
  - to: {{ route }}
          via: {{ addr_adm[0].gateway }}
      {% endfor %}

and a playbook template_test.yml

---
- name: Write File - Template
  hosts: localhost
  connection: local
  gather_facts: false

  tasks:
    - name: "network | ubuntu | configure | update {{ etc_netplan_adm }} file"
      ansible.builtin.template:
        src: "{{ template_file }}"
        dest: "{{ etc_netplan_adm }}"
      vars:
        iface_adm: eth0
        addr_adm:
          - address: 10.1.1.1
            cidr: 24
            gateway: x.x.x.254
        adm_default_routes:
          - 10.1.1.0/24
          - 10.1.2.0/24
          - 10.1.3.0/24
        etc_netplan_adm: ./netplan.yml
        ansible_managed_message: "## Block Managed via Ansbile"
        template_file: netplan.yml.j2

Neither of them have spacing that looks reasonable, but the both seem to produce a file that looks like it matches your desired state.

Hope that helps.

Turn off Jinja2 trim_blocks by putting a plus symbol at the end of the block:

{% endfor +%}

Everything in the block will start at the same indentation depth as the block itself:

routes:
  {% for route in adm_default_routes | flatten | map('string') | list %}
  - to: {{ route }}
    via: {{ addr_adm[0].gateway }}
  {% endfor +%}

EDIT: I Put too many spaces in the for loop. corrected

Using the code I provided above (adjusting to match your suggestions) this didn’t work as expected. I ended up with results mangled in the same way as the initial posting.

Is there a setting in ansible.cfg (or elsewhere) that might need enabled for this too? If it work working as described, I much prefer your solution to the much harder to read “working” examples I provided.

Try put the Plus at the end of the block opening statement instead:
{% for route in adm_default_routes | flatten | map(‘string’) | list +%}

routes:
  {% for route in adm_default_routes | flatten | map('string') | list +%}
  - to: {{ route }}
    via: {{ addr_adm[0].gateway }}
  {% endfor %}

That’s much closer. The only thing that I’d consider still sub-optimal is additional newlines. The relevant block looks like this in both the inline and template file versions

      routes:
      
        - to: 10.1.1.0/24
          via: x.x.x.254
      
        - to: 10.1.2.0/24
          via: x.x.x.254
      
        - to: 10.1.3.0/24
          via: x.x.x.254

Kill the new lines with a minus sign in the block opening statement:
{%- for route in adm_default_routes | flatten | map(‘string’) | list +%}

May also try on the block closing statement:
{%- endfor %}

For both the inline version and the template version, I found that adding the - in both the beginning and block statements gave the desired results.

@chumi, this is what I ended up for the jinja block (either inline with content like you have, or in a separate template file) with after the help form @Narizz28

{{ ansible_managed_message }}
network:
  version: 2
  ethernets:
    {{ iface_adm }}:
      dhcp4: no
      dhcp6: no
      addresses: [{{ addr_adm[0].address }}/{{ addr_adm[0].cidr }}]
      routes:
      {%- for route in adm_default_routes | flatten | map('string') | list +%}
        - to: {{ route }}
          via: {{ addr_adm[0].gateway }}
      {%- endfor %}

For my preference, I like to put the loop block at the same indentation level as the outputs instead of the parent. It is easier to read to my eyes:

{{ ansible_managed_message }}
network:
  version: 2
  ethernets:
    {{ iface_adm }}:
      dhcp4: no
      dhcp6: no
      addresses: [{{ addr_adm[0].address }}/{{ addr_adm[0].cidr }}]
      routes:
        {%- for route in adm_default_routes | flatten | map('string') | list +%}
        - to: {{ route }}
          via: {{ addr_adm[0].gateway }}
        {%- endfor %}

+1.
I will remember that.

+1.
I like it because it is easier to read.

And many thanks for all your return.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.